ভার্চুয়াল বেড়া ম্যাচ জিতে নিন (আপনার সহকর্মী স্ট্যাক এক্সচেঞ্জারদের বিপক্ষে)


16

সতর্কতা: এটি একটি মোটামুটি জটিল সমস্যা, একটি কিং-অফ-পাহাড়ী যুদ্ধের স্টাইলে এতে অতিরিক্ত এলোমেলোতার সাথে, সেরা কোডটি সর্বদা জিতে নাও পারে। এটি সম্পূর্ণ জটিল হিসাবে সমস্ত নিয়ম পুরো পড়ুন দয়া করে!

FLAVOR TEXT

বিল এবং স্টিভ একটি "বন্ধুত্বপূর্ণ" দ্বন্দ্বের সিদ্ধান্ত নিয়েছে, যদিও এটি এত ধনী এবং স্মার্ট, তাদের সেরা প্রোগ্রামারদের কোডটি একে অপরকে পরাস্ত করার জন্য এগিয়ে আসতে চেষ্টা করার সিদ্ধান্ত নিয়েছিল। আপনি প্রোগ্রামার বলা হয়।

OBJECTIVE

বেড়া দেওয়ার সময়, আপনার লক্ষ্যটি হ'ল আপনার প্রতিপক্ষকে সবচেয়ে বেশি হিট করা, যখন নিজেকে কম আঘাত করুন hit

MOVES

আপনার কোডে "চালগুলি" এর নিম্নলিখিত পছন্দগুলি থাকবে

আক্রমণ
প্যারি
ব্লক
লঞ্জ
এবং
প্রধান
বুকের
পা

SCORING POINTS

আক্রমণকারীকে মারধর করে প্যারিিং, 1 পয়েন্টের জন্য
ফুসফুসকে ব্লকিং ব্লকিং, 1 পয়েন্টের জন্য
প্যারিং বিটস লুঙ্গিং, 1 পয়েন্ট
ব্লকিং বিটস এটাকিং, 1 পয়েন্টের জন্য ফুসফুসের
সম্পর্কগুলি আক্রমণ করা, ফুসফুস খেলোয়াড় পরের দফায় অবরুদ্ধ বা প্যারি করতে অক্ষম এবং আক্রমণকারী খেলোয়াড় অক্ষম পরের
দফায় আক্রমণ বা লুঞ্জ করার জন্য প্যারিংয়ের প্লেয়ারিং পরের দফায় অবরুদ্ধ বা প্যারি করতে অক্ষম এবং ব্লকিং প্লেয়ার পরের রাউন্ডে আক্রমণ করতে বা লঞ্জ করতে অক্ষম

HEIGHT OF ACTION

আপনার ক্রিয়াকলাপের জন্য আপনি একটি "উচ্চতা "ও বেছে নেবেন, যেখানে উভয় খেলোয়াড়ের উচ্চতা আক্রমণটির উচ্চতার সাথে মিলে গেলে উপরের ফলাফলগুলি কেবলমাত্র ঘটে। যদি উচ্চতা মেলে না, উভয় খেলোয়াড় আর পয়েন্ট বাঁধা না হয়ে, বা সমস্ত 4 টি ক্রিয়া পূরণ না করা অবধি পূর্বের টাই বাঁধা রাউন্ডগুলির মতো একই ক্রিয়া (উচ্চতা সীমাবদ্ধ নয়) বাছাই করতে পারে না (টাই একবার ভাঙ্গা হয়ে গেলে, সমস্ত ক্রিয়া) আবার উপলব্ধ)

CODE REQUIREMENTS

প্রতিটি রাউন্ডের জন্য, এটি প্রতিপক্ষের পূর্ববর্তী রাউন্ডে (রাউন্ড 1 বাদে) প্রবর্তন করতে হবে, এটি নিজের সাথে তুলনা করে, পূর্ববর্তী রাউন্ডের ফলাফল নির্ধারণ করবে, তারপরে পরবর্তী রাউন্ডের সংখ্যা, স্কোর এবং তার পছন্দ / অবস্থান নির্ধারণ করবে যে রাউন্ডের জন্য

প্রাক্তন:
ইনপুট: এলসি (ল্যাঞ্জ বুকে)
আউটপুট: পূর্ববর্তী রাউন্ড: প্রধানমন্ত্রী বনাম এলসি - প্রধানমন্ত্রী স্কোর! স্কোরটি এখন ২-১, পরের রাউন্ডের জন্য পদক্ষেপ হ'ল এএইচ (অ্যাটাকের মাথা)

WINNER

খেলাটি 50 রাউন্ডের পরে বা 3 পয়েন্টের পরে শেষ হয়

AGAINST OTHER PLAYERS

প্রথম উত্তরটিতে তাত্ক্ষণিক গ্যারান্টিযুক্ত জয় দেওয়া হবে, যতক্ষণ না এটি বাস্তবে কাজ / খেলার জন্য কাজ করে। প্রতিটি উত্তর পূর্ববর্তী বিজয়ীর বিপরীতে পোস্ট করার ক্রমে মূল্যায়ন করা হবে এবং যদি বিজয়ী হয় তবে তাকে নতুন বিজয়ী ঘোষণা করা হবে। আমি আপনাকে বিজয়ী হওয়ার সময়, বা প্রতিযোগিতার অপেক্ষার জন্য জিজ্ঞাসা করছি যে আপনি নিজের কোড পরিবর্তন করবেন না। একবার পরাজিত হয়ে গেলে, আপনি আর একই ভাষার সাথে চ্যাম্পিয়নশিপ স্ট্যাটাসের জন্য আর প্রতিদ্বন্দ্বিতা করতে পারবেন না, তবে আপনি আলাদা ভাষার উত্তর জমা দিতে পারেন (অবশ্যই উল্লেখযোগ্যভাবে আলাদা হতে হবে, একই বেসের স্টাফের কোনও বৈচিত্র নয়)।

আমি প্রতিটি চ্যালেঞ্জ চালানোর চেষ্টা করব এবং চ্যাম্পিয়ন এবং চ্যালেঞ্জারের মন্তব্যে ফলাফল পোস্ট করব, পাশাপাশি একটি নতুন বিজয়ী ঘোষণা করব - যেহেতু আমি প্রতিটি ভাষা, বিশেষত আরও কিছু অস্পষ্ট কিছু চালাতে সক্ষম না হতে পারি, আমি জিজ্ঞাসা করি আপনার উত্তরটি বিবেচনায় নেওয়ার বিষয়টি নিশ্চিত করতে আপনি যে কোনও সম্ভাব্য সহায়তা দিতে পারেন। ধন্যবাদ!


1
দ্রষ্টব্য: সেই খেলোয়াড়কে মোকাবেলায় বর্তমান বিজয়ীদের অ্যালগরিদমকে টার্গেট করা বেড়া দেওয়ার মতো, এবং এটি পাহাড়ের রাজা, সুতরাং এই জাতীয় পদক্ষেপ কেবল অনুমোদিত নয়, তবে উত্সাহিতও! - ফলাফল তৈরির কিছু পদ্ধতি, নিজের কোডটি অবলম্বন করা বা নিজেকে "রক্ষিত" করার জন্য অন্য কোনও উপায় নিয়ে আসার চেষ্টা করুন এবং অন্য খেলোয়াড়ের কোড "আক্রমণ" করার সর্বোত্তম উপায়টি চিহ্নিত করুন! - দয়া করে সমস্ত
ডিসকাশন সিভিল রাখুন

একবার পরাজিত হয়ে গেলে, আপনি কীভাবে জিনিসগুলি করেছেন, আপনি কেন কিছু নির্দিষ্ট উপায়ে করেছেন ইত্যাদি বিষয়ে মন্তব্য বা নিজের উত্তর পরিবর্তন করে যদি অন্তর্দৃষ্টি দিতে চান তবে নির্দ্বিধায়। আপনার কোডটি লাইনে থাকলেও, দয়া করে সম্পাদনা থেকে বিরত থাকুন :)
এনআরজিডালাস

আপনার উদাহরণটি কি সঠিক? এটি এলএম-এর কোনও ক্রিয়ায় এলসির একটি ইনপুট ম্যাঙ্গেল করে মনে হচ্ছে।
পিটার টেলর

সমাধান এলোমেলোতা সম্পর্কে কি? ম্যাচটি অবশ্যই সংঘবদ্ধ হতে হবে? যদি তা না হয় তবে বিচারক কীভাবে বীজ নির্বাচন করবেন এবং মাত্র দুটি প্রোগ্রামের মধ্যে কতটি গেম খেলবে? অন্ধ সুযোগের প্রভাব সীমিত করতে রোবকোড প্রতিযোগিতাগুলিতে সাধারণত 10 থাকে 10
বনাম

3
এটি কীভাবে ডিজাইন করা হয়েছে তা আমি সত্যিই পছন্দ করি না। আমি মনে করি আপনার 2 টি জমা দেওয়া প্রোগ্রাম চালানো, চালগুলি রিলে করে এবং স্কোরগুলি গণনা করে ম্যাচটি চালানোর কোডটি নিয়ে আসা উচিত। বেড়া প্রোগ্রামগুলি কেবল স্টাডাউটে তাদের চাল মুদ্রণ করা উচিত এবং প্রতিপক্ষের চালগুলি স্টিডিন পড়তে হবে।
অদিতসু

উত্তর:


5

পাইথন

এন গার্ডে!

আমার যোদ্ধা তার প্রতিপক্ষের অবস্থানের দুর্বলতার জন্য তীক্ষ্ণ চোখের সাথে অনিশ্চিতাকে একত্রিত করে। তিনি অত্যন্ত আত্মবিশ্বাসী যে তিনি আক্রমণাত্মক শত্রুদের নিষ্পত্তি করতে সক্ষম হবেন তবে তার প্রশিক্ষক (আমি) নির্দিষ্ট পরিস্থিতিগুলি অনুমান করতে ব্যর্থ হতে পেরেছি বা আরও উদ্বেগজনক হতে পারে, নিয়মের (বাগগুলি) ভুল ব্যাখ্যা করতে পারে।

যাইহোক আমি নতুন তাই আশা করি কোডের জন্য এটি একটি ঠিক বিন্যাস:

from random import choice, random

def cleverly_pick_move(me_allowed,op_allowed,opp_last_move=None) :
    """ Behold the genius you're up against!
    Pretty much everything else is just flavour text or match rules
    so you'll probably only want to read this...
    """
    heights = ['head','chest','feet']
    rand_choice = lambda a,h : {'type':choice([t for t in a if a[t]]),
                                'height':choice(h)}

    if opp_last_move is None or feeling_like_a_lucky_punk():
        return rand_choice(me_allowed,heights)

    if sum(1 for x in op_allowed if op_allowed[x]) == 3 :
        for i in op_allowed:
            if not op_allowed[i] :
                weakness = i
                break
        return {'type':exploit_weakness(weakness,me_allowed),
                'height':choice(heights)}
    return rand_choice(me_allowed,heights)

def exploit_weakness(weakness,me_allowed) :
    moves = ['attack','parry','lunge','block']
    for i,move in enumerate(moves) :
        if move == weakness :
            if me_allowed[moves[(i+1) % 4]] :
                return moves[(i+1) % 4]
            break
    if me_allowed[weakness] :
        return weakness
    return choice([x for x in me_allowed if me_allowed[x]])

def feeling_like_a_lucky_punk() :
    return random() > 0.8

def main():

    this_round = 1
    opp_last_move = None
    score   = {'myself':0, 'the blaggard':0}
    quips   = ['blaggard', 'fool', 'scum', 'raggamuffin']
    adverbs = ['deftly', 'skillfully', 'gracefully', 'clumsily']

    me_allowed = {'attack':True,'block':True,'lunge':True,'parry':True}
    op_allowed = {'attack':True,'block':True,'lunge':True,'parry':True}

    while (this_round <= 50 and
           all([points < 3 for points in score.values()])) :

        if this_round == 1 :
            move = cleverly_pick_move(me_allowed,op_allowed) 
        else:
            move = cleverly_pick_move(me_allowed,op_allowed,
                                      opp_last_move=opp_last_move)

        print "Our hero %s %ss at the %s's %s" % (
            choice(adverbs),
            move['type'],
            choice(quips),
            move['height']
            )
        print "We await the %s's response..." % choice(quips)
        print "Our hero's move: " + (move['type'][0]+move['height'][0]).upper()

        opp_move = parse_move(raw_input("Opponent's move: "))

        outcome,me_allowed,op_allowed = get_outcome(move,opp_move,me_allowed,
                                                    op_allowed)
        if outcome == 'WIN' :
            print "Our hero pulls off an excellent round!"
            score['myself'] += 1
        elif outcome == 'LOSE' :
            print "Never before have we seen such blatant cheating!"
            score['the blaggard'] += 1
        else :
            print "Our hero is clearly toying with his opponent as he allows \
a drawn round."

        print ("""The score after round %d:\nOur hero:\t%d\nHis opponent:\t%d""" 
                % (this_round, score['myself'], score['the blaggard']))
        opp_last_move = opp_move
        this_round += 1

    print "Match over, surely the victory is mine!"
    print """Final score:\n
             Our hero:\t%d\nOpponent:\t%d""" % (score['myself'],
                                                score['the blaggard'])

    if score['myself'] > score['the blaggard'] :
        print "My victory was inevitable!"
    elif score['myself'] == score['the blaggard'] :
        print "An even match! Huzzar!"
    else :
        print ""    
    return

def reset_allowed(dictionary) :
    return dict((x,True) for x in dictionary)

def get_outcome(mymove,opmove,me_allowed,op_allowed) :
    result = ''

    if not me_allowed[mymove['type']] :
        print "Whoops, I forgot I couldn't do that..."
        result = 'LOSE'

    if not op_allowed[opmove['type']] :
        print "Haha! What a clutz!"
        result = 'WIN'

    if mymove['height'] != opmove['height'] :
        print "The combatants flail at each other with little effect!"
        print "They'll have to try something else next round!"
        result = 'DRAW'

    if mymove['type'] == opmove['type'] :
        if mymove['type'] in ['attack','lunge']:
            print "The combatants' blades clash dramatically!"
        else :
            print "Both combatants take a moment to practice their \
defensive stance..."
        result = 'DRAW'

    if result :
        me_allowed, op_allowed = (reset_allowed(me_allowed),
                                  reset_allowed(op_allowed))
        if mymove['height'] != opmove['height'] :
            me_allowed[mymove['type']] = op_allowed[opmove['type']] = False
        return (result, me_allowed,op_allowed)
    else :
        return compare_attacks(mymove,opmove,me_allowed,op_allowed)

def compare_attacks(mymove,opmove,me_allowed,op_allowed) :
    """
    0 A > P 1
     ^  x  v
    3 B < L 2
    """
    print "Our hero %ss, his opponent %ss!" % (mymove['type'],opmove['type'])

    move_val = {'attack':0,'parry':1,'lunge':2,'block':3}
    result_num = (move_val[opmove['type']] - move_val[mymove['type']]) % 4
    results = ['DRAW','WIN','DRAW','LOSE']

    me_allowed, op_allowed = (reset_allowed(me_allowed),
                              reset_allowed(op_allowed))    
    if result_num == 1 :
        print "Our hero easily outwits his foe! *Huge cheers from crowd*"
        return ('WIN',me_allowed,op_allowed)
    elif result_num == 3 :
        print "Our hero graciously allows his opponent a charity point.\
*A torrent of boos from the crowd*"
        return ('LOSE',me_allowed,op_allowed)
    else:
        # Combatants drew and will have their moves restricted next round.
        if mymove['type'] in ['attack','parry'] :
            me_allowed['attack'] = me_allowed['lunge'] = False
            me_allowed['parry']  = me_allowed['block'] = True
            op_allowed['parry']  = op_allowed['block'] = False
            op_allowed['attack'] = op_allowed['lunge'] = True
        else :
            me_allowed['parry']  = me_allowed['block'] = False
            me_allowed['attack'] = me_allowed['lunge'] = True 
            op_allowed['attack'] = me_allowed['lunge'] = False
            op_allowed['parry']  = op_allowed['block'] = True
        return ('DRAW',me_allowed,op_allowed)

def parse_move(move_string) :
    m_types = {'A':'attack','B':'block','L':'lunge','P':'parry'}
    m_heights = {'C':'chest','H':'head','F':'feet'}

    move_string = move_string.strip().upper()
    if not move_string :
        print "Couldn't understand your input: %s" % move_string
        return parse_move(raw_input("Opponent's move: "))

    if move_string[0] not in m_types :
        move_string = move_string[::-1] 

    try :
        move = {'type':m_types[move_string[0]],
                'height':m_heights[move_string[1]]}
        return move
    except KeyError :
        print "Couldn't understand your input: %s" % move_string
        return parse_move(raw_input("Opponent's move: "))

if __name__ == '__main__' :
    main()

স্বাদ টেক্সট পছন্দ! অসুস্থ আশা করি এই সপ্তাহান্তে এখানে এটি ডিউক করতে প্রায় পেতে। দুর্ভাগ্যক্রমে এটি পোস্ট হওয়ার পরে এটি একটি দীর্ঘ সময় হয়ে গেছে এবং এটি এখন স্রোত অর্জন করছে, তাই এখনই কিছুটা দুষ্কৃত প্রস্তুত, তবে কিছুদিনের মধ্যেই আমার এখানে সক্ষম হতে হবে!
এনআরজিডাল্লাস

1
কোন চিন্তা করো না. সত্যি কথা বলতে আমি উপরের পোস্টগুলির তারিখগুলি পরীক্ষা করিনি। @ আরক্যাডি'র সেই অসভ্য লোকটি অবশ্যই 8 সপ্তাহ ধরে এই পাহাড়ের উপরে বেশ মজাদার / একাকী বোধ করছে। আমি আমার সুবিধার্থে এটি ব্যবহার করব!
ejrb

আমি এটি পরে যাচাই করব (আমার কাছে কর্মক্ষেত্রে পাইথন দোভাষী নেই) এবং সম্ভবত পরে পাল্টা আক্রমণ attack তারা ফ্রান্সে যেমন বলতে পারে "সতর্ক থাকুন"।
আরকডি

2

আমার দাবি পাহাড়!

এর মধ্যে একটি কাঠামো রয়েছে যা ম্যাচ, ইনপুট এবং আউটপুট যত্ন করে। আপনাকে যা করতে হবে তা হ'ল "এআইএইচ" শিরোনামে দুটি ফাংশনের নিজস্ব সংস্করণ সংজ্ঞায়িত করা যা প্রথম পদক্ষেপ এবং অন্যান্য প্রতিটি পদক্ষেপকে সংজ্ঞায়িত করে।

এটি ভিএস ২০১২ (মুক্ত সংস্করণ) এ সংকলন করে। আমার জ্ঞানের সেরাটি যে কোনও মান-সম্মতিযুক্ত সংকলক সংকলন করবে।

আমি এই এআইকে "অসম্পূর্ণ বার্বারিয়ান" বলি। আমি নিশ্চিত কেউ এটি মারতে বেশি সময় নিবে না।

// A.I.h
    #pragma once

    #include "Fencer.h"

    #include <algorithm>

    Move Fencer::chooseFirstMove() const
    {
        // Choose first move here.
        return Move( Action::Attack , Height::Head );
    }

    Move Fencer::chooseNextMove() const
    {
        using namespace std;

        // Implement A.I. here.
        auto legalActions = match.legalActions();
        auto isLegal = [&legalActions]( Action a ) {
            return find( begin(legalActions) , end(legalActions) , a ) == end(legalActions);
        };

        if( isLegal( Action::Attack ) )
            return Move( Action::Attack , Height::Head );
        if( isLegal( Action::Lunge ) )
            return Move( Action::Lunge , Height::Head );
        if( isLegal( Action::Block ) )
            return Move( Action::Lunge , Height::Head );
        if( isLegal( Action::Parry ) )
            return Move( Action::Parry , Height::Head );

    }

    // Fencer.h
    #pragma once

    #include "Match.h"

    class Fencer
    {
    public:
        std::string nextRound( const std::string& oppsMove );
        std::string getNextMove() const { return nextMove.toStr(); }
        bool matchInProgress() const { return match.inProgress(); }
        Fencer( unsigned int targetScore = 3 , unsigned int match_rounds = 50 );
    private:
        Move chooseNextMove() const;
        Move chooseFirstMove() const;
        Move nextMove;
        Match match;
    };

    // Match.h
    #pragma once

    #include <vector>
    #include <string>

    enum class Action : char
    {
        Attack,
        Parry,
        Block,
        Lunge,
        UNITIALIZED
    };

    enum class Height : char
    {
        Head,
        Chest,
        Feet,
        UNITIALIZED
    };

    enum class Result : char
    {
        Win,
        Tie,
        Lose,
        UNITIALIZED
    };

    struct Move
    {
        Action action;
        Height height;
        Move( Action a , Height h )
            : action(a) , height(h) {}
        std::string toStr() const;

        // For the STL. Please don't use these.
        Move() : action( Action::UNITIALIZED ) , height( Height::UNITIALIZED ) {}
        Move operator=( const Move& );
    };

    Result scoreRound( Move me , Move opp );

    struct Round
    {
        Move myMove;
        Move oppsMove;
        Result result;
        Round( Move me , Move opp )
            : myMove(me) , oppsMove(opp) , result(scoreRound(me,opp)) {}

        // For the STL. Please don't use these.
        Round() : myMove() , oppsMove() , result( Result::UNITIALIZED ) {}
        Round operator=( const Round& );
    };

    class Match
    {
    public:
        // Constructor.
        Match( unsigned int winningScore, unsigned int rounds );

        // Generate a list of legal actions.
        std::vector<Action> legalActions() const;

        // Get a copy of all previous rounds.
        std::vector<Round> getHistory() const { return results; }

        // Gets the scores
        unsigned int myScore() const;
        unsigned int oppsScore() const;
        bool inProgress() const { return in_progress; }

        // Perform next round. Returns the TTY for the round.
        std::string nextRound( const std::string& myMove , const std::string& oppsMove );
    private:
        const unsigned int winning_score;
        const unsigned int n_rounds;
        std::vector<Round> results;
        bool in_progress;
    };

    // Fencer.cpp
    #include "AI.h"

    #include <algorithm>

    using namespace std;

    Fencer::Fencer( unsigned int target , unsigned int rounds ) :
        match( target , rounds ) , nextMove( chooseFirstMove() )
    {}

    string Fencer::nextRound( const string& oppsMove )
    {
        string output = match.nextRound( nextMove.toStr() , oppsMove );
        if( match.inProgress() ) {
            nextMove = chooseNextMove();
            vector<Action> legalActions = match.legalActions();
            auto it = find( legalActions.begin() , legalActions.end() , nextMove.action );
            auto it2 = legalActions.end();
            if( legalActions.end() == it ) {
                output += "\n\nWARNING! Chosen move is illegal!\n\n";
            }
            output += " Action for next round is " + getNextMove() + ".";
        }
        return output;
    }

    // Match.cpp
    #include "Match.h"

    #include <algorithm>
    #include <sstream>
    #include <cassert>
    #include <functional>

    using namespace std;

    string Move::toStr() const
    {
        string str;
        switch( action )
        {
        case Action::Attack:
            str.push_back( 'A' );
            break;
        case Action::Block:
            str.push_back( 'B' );
            break;
        case Action::Lunge:
            str.push_back( 'L' );
            break;
        case Action::Parry:
            str.push_back( 'P' );
            break;
        default:
            assert( false );
            break;
        }
        switch( height )
        {
        case Height::Head:
            str.push_back( 'H' );
            break;
        case Height::Chest:
            str.push_back( 'C' );
            break;
        case Height::Feet:
            str.push_back( 'F' );
            break;
        default:
            assert( false );
            break;
        }
        return str;
    }

    Move Move::operator=( const Move& rhs )
    {
        action = rhs.action;
        height = rhs.height;
        return *this;
    }

    Result scoreRound( Move me , Move opp )
    {
        if( me.height != opp.height ) {
            return Result::Tie;
        }
        if( me.action == opp.action ) {
            return Result::Tie;
        }
        switch ( me.action ) {
        case Action::Attack:
            switch( opp.action ) {
            case Action::Parry:
                return Result::Win;
            case Action::Lunge:
                return Result::Tie;
            case Action::Block:
                return Result::Lose;
            default:
                assert( false );
            }
        case Action::Lunge:
            switch( opp.action ) {
            case Action::Block:
                return Result::Win;
            case Action::Attack:
                return Result::Tie;
            case Action::Parry:
                return Result::Lose;
            default:
                assert( false );
            }
        case Action::Parry:
            switch( opp.action ) {
            case Action::Lunge:
                return Result::Win;
            case Action::Block:
                return Result::Tie;
            case Action::Attack:
                return Result::Lose;
            default:
                assert( false );
            }
        case Action::Block:
            switch( opp.action ) {
            case Action::Attack:
                return Result::Win;
            case Action::Parry:
                return Result::Tie;
            case Action::Lunge:
                return Result::Lose;
            default:
                assert( false );
            }
        default:
            assert( false );
        }
        return Result::Tie;
    }

    Round Round::operator=( const Round& rhs )
    {
        myMove = rhs.myMove;
        oppsMove = rhs.oppsMove;
        result = rhs.result;
        return *this;
    }

    Match::Match( unsigned int targetScore , unsigned int rounds ) :
        winning_score( targetScore ) , n_rounds( rounds) , results() , in_progress( true )
    {
        results.reserve( rounds );
    }

    vector<Action> Match::legalActions() const
    {
        typedef unsigned int ActionBits;

        // Make a bitfield representing the four legal actions.
        const ActionBits ATTACK = 0x1;
        const ActionBits PARRY = 0x2;
        const ActionBits BLOCK = 0x4;
        const ActionBits LUNGE = 0x8;

        const auto actionBitsToVector = [=](ActionBits ab) -> vector<Action> {
            vector<Action> vec;
            if( ab == 0 ) // Nothing is allowed
                ab = ATTACK | PARRY | BLOCK | LUNGE; // So allow all actions
            if( (ATTACK & ab) == ATTACK )
                vec.push_back( Action::Attack );
            if( (PARRY & ab) == PARRY )
                vec.push_back( Action::Parry );
            if( (BLOCK & ab) == BLOCK )
                vec.push_back( Action::Block );
            if( (LUNGE & ab) == LUNGE )
                vec.push_back( Action::Lunge );
            return vec;
        };

        auto availableActions = ATTACK | PARRY | BLOCK | LUNGE;

        const auto lastResult = *results.rbegin();

        // If a point was scored in the last round all actions are available.
        if( lastResult.result != Result::Tie ) {
            return actionBitsToVector( availableActions );
        }

        // If the heights do not match, both players may no longer
        // select the same action (height is not restricted)
        // as the previous tying rounds, until a point is scored,
        // or all 4 actions have been filled.
        if( lastResult.myMove.height != lastResult.oppsMove.height ) {
            for( auto it = results.rbegin() ; it!= results.rend() ; ++it ) {
                if( it->result != Result::Tie )
                    break;
                else {
                    switch( it->myMove.action )
                    {
                    case Action::Attack:
                        availableActions &= ~ATTACK;
                        break;
                    case Action::Parry:
                        availableActions &= ~PARRY;
                        break;
                    case Action::Block:
                        availableActions &= ~BLOCK;
                        break;
                    case Action::Lunge:
                        availableActions &= ~LUNGE;
                        break;
                    default:
                        break;
                    }
                }
            }
            return actionBitsToVector( availableActions );
        }

        // Attack vs. Lunge
        if( lastResult.myMove.action == Action::Attack &&
            lastResult.oppsMove.action == Action::Lunge ) {
                return actionBitsToVector( PARRY | BLOCK );
        }
        if( lastResult.myMove.action == Action::Lunge &&
            lastResult.oppsMove.action == Action::Attack ) {
                return actionBitsToVector( ATTACK | LUNGE );
        }

        // Block vs Parry
        if( lastResult.myMove.action == Action::Block &&
            lastResult.oppsMove.action == Action::Parry ) {
                return actionBitsToVector( ATTACK | LUNGE );
        }
        if( lastResult.myMove.action == Action::Parry &&
            lastResult.oppsMove.action == Action::Block ) {
                return actionBitsToVector( BLOCK | PARRY );
        }
        return actionBitsToVector( availableActions );
    }

    unsigned int Match::myScore() const
    {
        return count_if( begin(results) , end(results) ,
            [=](const Round& r) {
                return r.result == Result::Win;
        });
    }

    unsigned int Match::oppsScore() const
    {
        return count_if( begin(results) , end(results) ,
            [=](const Round& r) {
                return r.result == Result::Lose;
        });
    }

    string Match::nextRound( const string& myMove , const string& oppsMove )
    {
        if( !in_progress )
            return "Match has already finished.\n";

        stringstream output;
        output << "Round " << results.size()+1 << ": ";
        bool parseSuccessful = true;
        auto getMove = [&]( const string& s ) {
            if( s.length() < 2 ) {
                output << "\nError: Move " << s << " does not have enough characters.";
                return Move();
            }
            Action a = Action::UNITIALIZED;
            switch( s[0] )
            {
            case 'a':
            case 'A':
                a = Action::Attack;
                break;
            case 'b':
            case 'B':
                a = Action::Block;
                break;
            case 'l':
            case 'L':
                a = Action::Lunge;
                break;
            case 'p':
            case 'P':
                a = Action::Parry;
                break;
            default:
                parseSuccessful = false;
                output << "\nFailed to parse action part (" << s[0] << ") of " << s;
                break;
            }

            Height h = Height::UNITIALIZED;
            switch( s[1] )
            {
            case 'h':
            case 'H':
                h = Height::Head;
                break;
            case 'c':
            case 'C':
                h = Height::Chest;
                break;
            case 'f':
            case 'F':
                h = Height::Feet;
                break;
            default:
                parseSuccessful = false;
                output << "\nFailed to parse height part (" << s[1] << ") of " << s;
                break;
            }

            if( a == Action::UNITIALIZED || h == Height::UNITIALIZED )
                return Move();
            else
                return Move( a , h );
            };

        Round thisRound( getMove( myMove ),  getMove( oppsMove ) );

        if ( parseSuccessful ) {
            output << "Previous round: " << myMove << " vs " << oppsMove << " - ";
            switch( thisRound.result )
            {
            case Result::Win:
                output << myMove + " Wins! ";
                break;
            case Result::Lose:
                output << oppsMove + " Wins! ";
                break;
            case Result::Tie:
                output << "Tie! ";
                break;
            default:
                assert( false );
                break;
            }

            results.push_back( thisRound );
            const auto score_me = myScore();
            const auto score_opp = oppsScore();
            output << "Score is now " << score_me << "-" << score_opp << ".";

            if( score_me >= winning_score ) {
                output << "\n\tI win! ";
                in_progress = false;
            }
            if( score_opp >= winning_score ) {
                output << "\n\tI lose. ";
                in_progress = false;
            }
            if( results.size() >= n_rounds ) {
                output << "\n\tTime's up. ";
                if( score_me == score_opp )
                    output << "Match drawn. ";
                else
                    output << "I " << (score_me > score_opp ? "win! " : "lose. " );
                in_progress = false;
            }

            if (!in_progress ) {
                output << "Final score: " << score_me << "-" << score_opp << endl;
            }
        }
        return output.str();
    }

1
কেবলমাত্র একটি সম্ভাব্য কোড ত্রুটি লক্ষ্য করে - আপনি যখন কোনও ব্লকের জন্য কোড করেন, এটি এখনও একটি লঞ্জের পদক্ষেপটি ফিরিয়ে দেয়! - মনে রাখবেন, নিয়ম অনুসারে আপনি পরাজিত না হওয়া পর্যন্ত কোনও সম্পাদনা অনুমোদিত নয়
এনআরজিডালাস

1
ভাল যুক্তি. এর অর্থ এআই অবৈধ পদক্ষেপের চেষ্টা করে। এমন পরিস্থিতিতে কী ঘটে?
আরকাদি

আমি আরও যোগ করতে চাই যে আমি কাঠামোটি পাবলিক বিবেচনা করি এবং যারা এটি ধার নিতে চান এবং কেবল দুটি এআই ফাংশন পুনর্লিখন করতে চান তারা এগুলি করতে বিনামূল্যে।
আরকাদি

যে কোনও অবৈধ পদক্ষেপ তাত্ক্ষণিকভাবে ক্ষতি হয়।
এনআরজিডাল্লাস

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.