gagner un match d'escrime virtuel (contre vos collègues échangeurs de pile)

16

AVERTISSEMENT: il s'agit d'un problème assez complexe, dans un style de combat roi de la colline, avec un caractère aléatoire supplémentaire, le meilleur code peut ne pas toujours gagner. Veuillez lire toutes les règles en entier, car c'est assez complexe!

FLAVOR TEXT

Bill et Steve ont décidé d'avoir un duel "amical", mais étant si riches et intelligents, ils ont décidé de laisser leurs meilleurs programmeurs essayer de trouver le code pour se battre. Vous êtes dit programmeur.

OBJECTIVE

En escrime, votre objectif est de marquer le plus de coups sur votre adversaire, tout en étant le moins touché par vous-même

MOVES

Votre code aura les choix suivants de "coups"

Attack
Parry
Block
Lunge
AND
Head
Chest
Feet

SCORING POINTS

Battements d'attaque Parade, pour 1 point
Battements de poumon Blocage, pour 1 point
Parade battements Battement, pour 1 point
Battements de blocage Attaque, pour 1 point
Traumatisme ligoté Attaque, avec le joueur qui brasse incapable de bloquer ou de parer le tour suivant, et le joueur attaquant ne peut pas pour attaquer ou fendre le tour suivant
Blocage des liens Parade, avec le joueur parer incapable de bloquer ou de parer le tour suivant, et le joueur bloquant incapable d'attaquer ou de fendre le tour suivant

HEIGHT OF ACTION

vous choisirez également une "hauteur" pour votre action, après quoi les résultats ci-dessus n'auront lieu que si les hauteurs des deux joueurs correspondent à la hauteur d'attaque. si les hauteurs ne correspondent pas, les deux joueurs ne peuvent plus sélectionner la même action (la hauteur n'est pas limitée) que les tours de liage précédents, jusqu'à ce qu'un point soit marqué, ou que les 4 actions aient été remplies (une fois une égalité rompue, toutes les actions sont à nouveau disponibles)

CODE REQUIREMENTS

pour chaque tour, il doit inciter l'adversaire à se déplacer au tour précédent (à l'exception du tour 1), le comparer au sien, déterminer le résultat du tour précédent, puis afficher le numéro du tour suivant, le score et son choix / position pour ce tour

ex:
ENTRÉE: LC (poitrine fendue)
SORTIE: tour précédent: PM vs LC - scores PM! le score est désormais de 2-1, l'action pour le prochain tour est AH (tête d'attaque)

WINNER

le jeu se termine après 50 tours ou après que 3 points ont été marqués

AGAINST OTHER PLAYERS

la première réponse sera donnée une victoire garantie instantanée, tant qu'elle fonctionne pour fonctionner / jouer réellement. Chaque réponse sera évaluée, par ordre de publication, par rapport au gagnant précédent et, si elle est gagnante, sera déclarée le nouveau gagnant. Je demande qu'en gagnant ou en attendant de participer, vous ne changez PAS votre code. Une fois vaincu, vous ne pouvez plus concourir pour le statut de championnat avec cette même langue, vous pouvez cependant soumettre une réponse de langue différente (doit être significativement différente, sans utiliser de variations de la même substance de base).

J'essaierai de lancer chaque défi et publierai les résultats dans les commentaires du champion et du challenger, ainsi que de déclarer un nouveau gagnant - car je ne pourrai peut-être pas exécuter toutes les langues, en particulier certaines des plus obscures, je demande toute aide possible que vous pouvez apporter pour vous assurer que votre réponse est exécutée soit prise en considération. Je vous remercie!

NRGdallas
la source
1
note: cibler l'algorithme des gagnants actuels pour contrer ce joueur est dans la nature de l'escrime, et c'est le roi de la colline, donc une telle action est non seulement autorisée, mais aussi ENCOURAGÉE! - essayez de trouver une méthode pour générer des résultats, brouiller votre code, ou une autre façon de vous "protéger", et trouver la meilleure façon "d'attaquer" le code de l'autre joueur! - VEUILLEZ GARDER TOUTE DISCUSSION CIVILE -
NRGdallas
une fois vaincu, si vous voulez donner un aperçu de la façon dont vous avez fait les choses, pourquoi vous avez fait les choses d'une certaine manière, etc., dans les commentaires ou en modifiant votre réponse, n'hésitez pas à. Pendant que votre code est en ligne, cependant, veuillez ne pas modifier :)
NRGdallas
Votre exemple est-il correct? Il semble transformer une entrée de LC en une action de LM.
Peter Taylor
Qu'en est-il du hasard dans la solution? La correspondance doit-elle être déterministe? Sinon, comment le juge sélectionnera-t-il la graine et combien de matchs seront joués entre deux programmes, un seul? Les compétitions de robocode ont généralement 10, pour limiter les effets de la chance aveugle.
vsz
3
Je n'aime pas vraiment comment cela est conçu. Je pense que vous devriez trouver le code pour exécuter le match en exécutant 2 programmes soumis, en relayant les mouvements et en calculant les scores. Les programmes d'escrime doivent simplement imprimer leurs mouvements sur stdout et lire les mouvements de l'adversaire sous stdin.
aditsu

Réponses:

5

Python

En garde!

Mon guerrier combine l'imprévisibilité avec un œil attentif à la faiblesse de la position de son adversaire. Il est assez confiant qu'il sera en mesure de se débarrasser d'ennemis agressifs mais son entraîneur (moi) n'a peut-être pas anticipé certains scénarios ou, peut-être plus inquiétant, peut avoir mal interprété les règles (bugs !!).

Quoi qu'il en soit, je suis nouveau, donc j'espère que c'est un format correct pour le code:

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()
ejrb
la source
j'aime le texte de saveur! J'espère que j'arriverai à les faire venir ici ce week-end. Malheureusement, cela fait très longtemps que cela n'a pas été publié et il commence à gagner du terrain, alors je suis un peu mal préparé en ce moment, mais je devrais pouvoir le faire d'ici quelques jours!
NRGdallas
1
Pas de soucis. Pour être honnête, je n'ai pas vérifié les dates des articles ci-dessus. Ce barbare de @Arkady doit se sentir assez arrogant / solitaire sur cette colline pendant 8 semaines. Je vais l'utiliser à mon avantage!
ejrb
Je vérifierai cela plus tard (je n'ai pas d'interprète Python au travail) et peut-être contre-attaquer plus tard. Soyez "sur vos gardes" comme on pourrait le dire en France.
Arkady
2

Je réclame la colline!

Cela comprend un cadre qui prend en charge la correspondance, l'entrée et la sortie. Tout ce que vous avez à faire est de définir vos propres versions de deux fonctions dans l'en-tête "AIh" qui définissent le premier mouvement et tous les autres mouvements.

Cela se compile dans VS2012 (version gratuite). À ma connaissance, il sera compilé dans n'importe quel compilateur conforme aux normes.

J'appelle cette IA "Barbare non sophistiqué". Je suis sûr qu'il ne faudra pas longtemps à quelqu'un pour le battre.

// 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();
    }
Arkady
la source
1
juste remarquer un défaut de code potentiel - lorsque vous codez pour un bloc, il retourne toujours le mouvement d'une fente! - rappelez-vous, selon les règles, aucune modification n'est autorisée jusqu'à ce que vous soyez vaincu
NRGdallas
1
Bon point. Cela peut signifier que l'IA tente des mouvements illégaux. Que se passe-t-il dans cette situation?
Arkady
Je voudrais également ajouter que je considère le cadre public et tous ceux qui souhaitent l'emprunter et simplement réécrire les deux fonctions d'IA sont libres de le faire.
Arkady
tout mouvement illégal est une perte de round instantanée.
NRGdallas
UNITIALIZED?!
Soham Chowdhury