वर्चुअल फेंसिंग मैच जीतें (अपने साथी स्टाॅक एक्सचेंजर्स के खिलाफ)


16

चेतावनी: यह एक काफी जटिल समस्या है, एक राजा की पहाड़ी युद्ध शैली में, इसके साथ एक यादृच्छिकता के साथ, सबसे अच्छा कोड हमेशा नहीं जीत सकता है। कृपया सभी नियमों को पूरा पढ़ें, क्योंकि यह काफी जटिल है!

FLAVOR TEXT

बिल और स्टीव ने एक "मैत्रीपूर्ण" द्वंद्व का फैसला किया, हालांकि इतना समृद्ध और स्मार्ट होने के नाते, उन्होंने अपने सर्वश्रेष्ठ प्रोग्रामरों को एक दूसरे को हराने के लिए कोड के साथ आने का प्रयास करने का फैसला किया। आप प्रोग्रामर कहे जाते हैं।

OBJECTIVE

तलवारबाजी में, आपका लक्ष्य अपने प्रतिद्वंद्वी पर सबसे अधिक हिट करना है, जबकि खुद को कम से कम हिट करना है

MOVES

आपके कोड में "चाल" के निम्नलिखित विकल्प होंगे

हमला
पैरी
ब्लॉक
लंज
और
हेड
चेस्ट
फीट

SCORING POINTS

धड़क रहा है पर हमला parrying, 1 अंक के लिए
lunging को अवरुद्ध करने धड़कता है, 1 अंक के लिए
parrying lunging बीट्स, 1 अंक के लिए
, धड़कन को अवरुद्ध करने पर हमला 1 अंक के लिए
, पर हमला lunging संबंधों को ब्लॉक या अगले दौर रद करने में असमर्थ lunging खिलाड़ी के साथ, और हमला खिलाड़ी असमर्थ हमला करने के लिए या अगले दौर तलवार का वार
को अवरुद्ध करने संबंधों parrying, parrying खिलाड़ी ब्लॉक या अगले दौर रद करने में असमर्थ के साथ, और अवरुद्ध खिलाड़ी पर हमला करने या अगले दौर तलवार का वार करने में असमर्थ

HEIGHT OF ACTION

आप अपनी कार्रवाई के लिए एक "ऊँचाई" भी चुनेंगे, जिसके ऊपर के परिणाम केवल तभी होंगे जब दोनों खिलाड़ियों की ऊँचाई आक्रमण की ऊँचाई से मेल खाती है। यदि ऊंचाइयां मेल नहीं खाती हैं, तो दोनों खिलाड़ी अब एक ही कार्रवाई का चयन नहीं कर सकते हैं (ऊंचाई प्रतिबंधित नहीं है) पिछले बांधने वाले राउंड के रूप में, जब तक कि एक बिंदु पर गोल नहीं किया जाता है, या सभी 4 क्रियाएं भरी गई हैं (एक बार एक टाई टूट गया है, सभी क्रियाएं फिर से उपलब्ध हैं)

CODE REQUIREMENTS

प्रत्येक राउंड के लिए, इसे प्रतिद्वंद्वी के पिछले राउंड (1 राउंड को छोड़कर) को रोकना चाहिए, इसकी खुद से तुलना करें, पिछले राउंड के परिणाम का निर्धारण करें, फिर अगले राउंड नंबर, स्कोर और उसकी पसंद / स्थिति का आउटपुट करें। उस दौर के लिए

ex:
INPUT: LC (लूंज चेस्ट)
OUTPUT: पिछला राउंड: PM vs LC - PM स्कोर! स्कोर अब 2-1 है, अगले राउंड के लिए एएच (आक्रमण प्रमुख) की कार्रवाई

WINNER

खेल 50 राउंड के बाद, या 3 अंक के बाद समाप्त होता है

AGAINST OTHER PLAYERS

पहले जवाब को तत्काल गारंटी जीत दी जाएगी, जब तक कि यह वास्तव में काम / खेलने के लिए कार्य करता है। प्रत्येक उत्तर का मूल्यांकन, पोस्टिंग के क्रम में, पिछले विजेता के विरुद्ध किया जाएगा, और यदि जीतने पर, उसे नया विजेता घोषित किया जाएगा। मैं पूछता हूं कि जीतने के दौरान, या प्रतिस्पर्धा करने के लिए इंतजार करते हुए, कि आप अपना कोड नहीं बदलते हैं। एक बार पराजित होने के बाद, आप अब उसी भाषा के साथ चैम्पियनशिप स्थिति के लिए प्रतिस्पर्धा नहीं कर सकते हैं, लेकिन आप एक अलग भाषा जवाब प्रस्तुत कर सकते हैं (एक ही आधार सामग्री के भिन्नरूपों का उपयोग करके कोई भिन्नता नहीं होनी चाहिए)।

मैं प्रत्येक चुनौती को चलाने का प्रयास करूंगा और परिणामों को चैंपियन और चैलेंजर की टिप्पणियों में पोस्ट करूंगा, साथ ही एक नए विजेता की घोषणा करूंगा - क्योंकि मैं हर भाषा को चलाने में सक्षम नहीं हो सकता हूं, विशेष रूप से अधिक अस्पष्ट लोगों में से कुछ, मैं पूछता हूं कोई भी संभावित मदद जो आप यह सुनिश्चित करने के लिए दे सकते हैं कि आपके उत्तर के चलने को ध्यान में रखा जाए। धन्यवाद!


1
ध्यान दें: वर्तमान विजेता एल्गोरिदम को लक्षित करने के लिए काउंटर करने के लिए खिलाड़ी बाड़ लगाने की प्रकृति में है, और यह राजा-की-हिल है, इसलिए ऐसी कार्रवाई की अनुमति नहीं है, लेकिन यह भी आवश्यक है! - परिणाम उत्पन्न करने की कुछ विधि के साथ आने की कोशिश करें, अपने कोड को बाधित करें, या किसी अन्य तरीके से खुद को "गार्ड" करें, और दूसरे खिलाड़ी के कोड पर "हमला" करने का सबसे अच्छा तरीका समझें! -
NRGdallas

एक बार पराजित होने के बाद, यदि आप यह जानना चाहते हैं कि आपने चीजों को कैसे किया है, तो आपने चीजों को एक निश्चित तरीके से कैसे किया है, आदि, टिप्पणियों में या अपने उत्तर को संशोधित करके, बेझिझक। हालाँकि, आपका कोड कतार में है, लेकिन कृपया संपादन से बचना :)
NRGdallas

क्या आपका उदाहरण सही है? ऐसा लगता है कि एलएम की कार्रवाई में एलसी के इनपुट को नियंत्रित करना है।
पीटर टेलर

समाधान में यादृच्छिकता के बारे में क्या? मैच निर्णायक होना चाहिए? यदि नहीं, तो न्यायाधीश कैसे बीज का चयन करेगा, और दो कार्यक्रमों के बीच कितने खेल खेले जाएंगे, सिर्फ एक? ब्लाइंडोड प्रतियोगिताओं में आमतौर पर 10 होते हैं, जिससे अंधे अवसर के प्रभाव को सीमित किया जा सकता है।
9

3
मुझे वास्तव में पसंद नहीं है कि यह कैसे डिज़ाइन किया गया है। मुझे लगता है कि आपको 2 सबमिट किए गए प्रोग्राम चलाकर, मूव्स को रिले करने और स्कोर की गणना करके मैच को चलाने के लिए कोड के साथ आना चाहिए। बाड़ लगाने के कार्यक्रमों को बस स्टडआउट करने के लिए अपनी चाल को प्रिंट करना चाहिए और प्रतिद्वंद्वी के चाल स्टैड को पढ़ना चाहिए।
एडित्सू ने छोड़ दिया क्योंकि SE को EVIL

जवाबों:


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()

स्वाद पाठ प्यार करता हूँ! बीमार उम्मीद है कि चारों ओर पाने के लिए इसे इस सप्ताह के अंत में यहां ड्यूक करें। दुर्भाग्य से यह एक बहुत लंबे समय के बाद से यह पोस्ट किया गया था और इसका अभी-अभी कर्षण हो रहा है, इसलिए अभी करने के लिए थोड़ा बीमार तैयार हूं, लेकिन मुझे कुछ दिनों के भीतर यहां सक्षम होना चाहिए!
NRGdallas

1
कोई चिंता नहीं। ईमानदार होने के लिए मैंने ऊपर के पदों की तारीखों की जाँच नहीं की। 8 दिनों के लिए उस पहाड़ी पर @Arkady का बर्बर सुंदर अहंकारी / अकेला महसूस कर रहा होगा। मैं अपने लाभ के लिए उपयोग करेंगे!
ejrb

मैं इसे बाद में जांच लूंगा (मेरे पास काम पर पायथन दुभाषिया नहीं है) और संभवतः बाद में जवाबी हमला किया। जैसा कि वे फ्रांस में कह सकते हैं, "रक्षा पर" रहें।
अर्कडी

2

मैं पहाड़ी का दावा करता हूं!

इसमें एक फ्रेमवर्क शामिल है जो मैच, इनपुट और आउटपुट का ध्यान रखता है। आपको बस "एआईएच" हेडर में दो कार्यों के अपने स्वयं के संस्करणों को परिभाषित करना है जो पहले कदम और हर दूसरे कदम को परिभाषित करते हैं।

यह VS2012 (मुक्त संस्करण) में संकलित है। मेरे ज्ञान का सबसे अच्छा करने के लिए यह किसी भी मानक-अनुरूप संकलक में संकलित करेगा।

मैं इस ऐ को "अनसोफिबल बारबेरियन।" मुझे यकीन है कि किसी को इसे हराने में लंबा समय नहीं लगेगा।

// 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
बस एक संभावित कोड दोष की सूचना - जब आप किसी ब्लॉक के लिए कोड करते हैं, तब भी यह एक लंज की चाल को लौटाता है! - याद रखें, नियमों के अनुसार, जब तक आप पराजित नहीं हो जाते, तब तक किसी भी संपादन की अनुमति नहीं है
NRGdallas

1
अच्छी बात। इसका मतलब हो सकता है कि AI अवैध चालों का प्रयास करे। उस स्थिति में क्या होता है?
अर्कडी

मैं यह भी जोड़ना चाहूंगा कि मैं रूपरेखा को सार्वजनिक मानता हूं और सभी जो इसे उधार लेना चाहते हैं और सिर्फ दो एआई कार्यों को फिर से लिखने के लिए स्वतंत्र हैं।
अर्कडी

कोई भी गैरकानूनी कदम एक तात्कालिक दौर का नुकसान है।
NRGdallas

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.