thắng một trận đấu kiếm ảo (chống lại các trao đổi ngăn xếp đồng bào của bạn)


16

CẢNH BÁO: đây là một vấn đề khá phức tạp, theo kiểu chiến đấu trên đỉnh đồi, với sự ngẫu nhiên được thêm vào, mã tốt nhất có thể không phải lúc nào cũng thắng. Xin vui lòng đọc tất cả các quy tắc đầy đủ, vì nó khá phức tạp!

FLAVOR TEXT

Bill và Steve quyết định có một cuộc đấu tay đôi "thân thiện", tuy nhiên rất giàu có và thông minh, đã quyết định để các lập trình viên giỏi nhất của họ thử sức với việc tìm ra mật mã để đánh bại nhau. Bạn đang nói lập trình viên.

OBJECTIVE

Trong đấu kiếm, mục tiêu của bạn là ghi được nhiều cú đánh nhất vào đối thủ, đồng thời tự mình đánh ít nhất

MOVES

Mã của bạn sẽ có các lựa chọn "di chuyển" sau đây

Tấn công
Parry
Khối
Lunge

Trưởng
ngực
Feet

SCORING POINTS

Nhịp đập tấn công Parrying, cho 1 điểm
Nhịp đập Chặn, cho 1 điểm
Parrying Beats Lunging, cho 1 điểm
Chặn nhịp đập Tấn công, cho 1 điểm Liên kết
phổi Tấn công, với người chơi lung lay không thể chặn hoặc nhảy vào vòng tiếp theo, và người chơi tấn công không thể để tấn công hoặc phá vỡ vòng tiếp theo
Chặn các mối quan hệ Parrying, với người chơi nhảy dù không thể chặn hoặc nhảy vào vòng tiếp theo, và người chơi chặn không thể tấn công hoặc vượt qua vòng tiếp theo

HEIGHT OF ACTION

bạn cũng sẽ chọn "chiều cao" cho hành động của mình, trong đó kết quả ở trên chỉ diễn ra nếu chiều cao của cả hai người chơi phù hợp với chiều cao tấn công. nếu độ cao không khớp, cả hai người chơi có thể không còn chọn cùng một hành động (chiều cao không bị hạn chế) như các vòng buộc trước đó, cho đến khi một điểm được ghi hoặc tất cả 4 hành động đã được lấp đầy (một khi cà vạt bị phá vỡ, tất cả các hành động đều bị phá vỡ có sẵn một lần nữa)

CODE REQUIREMENTS

đối với mỗi vòng, cần nhắc lại sự di chuyển của đối thủ vào vòng trước (chặn vòng 1), so sánh với vòng của nó, xác định kết quả của vòng trước, sau đó đưa ra số vòng tiếp theo, điểm số và lựa chọn / vị trí của nó cho vòng đó

ví dụ:
INPUT: LC (lunge ngực)
OUTPUT: vòng trước: PM vs LC - Điểm số PM! tỷ số hiện là 2-1, hành động cho vòng tiếp theo là AH (đầu tấn công)

WINNER

Trò chơi kết thúc sau 50 vòng, hoặc sau 3 điểm đã được ghi

AGAINST OTHER PLAYERS

câu trả lời đầu tiên sẽ được đưa ra một chiến thắng được đảm bảo ngay lập tức, miễn là nó thực sự hoạt động / chơi. Mỗi câu trả lời sẽ được đánh giá, theo thứ tự đăng, so với người chiến thắng trước đó và nếu chiến thắng, sẽ được tuyên bố là người chiến thắng mới. Tôi yêu cầu trong khi chiến thắng hoặc chờ đợi để cạnh tranh, rằng bạn KHÔNG thay đổi mã của mình. Sau khi bị đánh bại, bạn không còn có thể cạnh tranh cho trạng thái vô địch với cùng một ngôn ngữ, tuy nhiên bạn có thể gửi một câu trả lời ngôn ngữ khác (phải khác biệt đáng kể, không sử dụng các biến thể của cùng một nội dung cơ bản).

Tôi sẽ cố gắng chạy từng thử thách và sẽ đăng kết quả trong các bình luận của nhà vô địch và người thách đấu, cũng như tuyên bố một người chiến thắng mới - vì tôi không thể chạy mọi ngôn ngữ, đặc biệt là một số ngôn ngữ khó hiểu hơn, tôi hỏi bất kỳ trợ giúp có thể nào bạn có thể đưa ra để đảm bảo câu trả lời của bạn sẽ được xem xét. Cảm ơn bạn!


1
lưu ý: nhắm mục tiêu thuật toán người chiến thắng hiện tại để chống lại người chơi đó có bản chất là đấu kiếm, và đây là vua của ngọn đồi, vì vậy hành động như vậy không chỉ được cho phép, mà còn được HẤP DẪN! - hãy thử đưa ra một số phương pháp tạo kết quả, làm xáo trộn mã của bạn hoặc một số cách khác để "bảo vệ" chính bạn và tìm ra cách tốt nhất để "tấn công" mã của người chơi khác! - XIN HÃY GIỮ TẤT CẢ DÂN SỰ THẢO LUẬN -
NRGdallas

một khi bị đánh bại, nếu bạn muốn đưa ra cái nhìn sâu sắc về cách bạn đã làm mọi việc, tại sao bạn lại làm mọi thứ theo một cách nhất định, v.v., trong các bình luận hoặc bằng cách sửa đổi câu trả lời của bạn, hãy thoải mái. Tuy nhiên, trong khi mã của bạn đang xếp hàng, vui lòng không chỉnh sửa :)
NRGdallas

Là ví dụ của bạn đúng? Nó dường như đưa một đầu vào LC vào một hành động của LM.
Peter Taylor

Điều gì về tính ngẫu nhiên trong giải pháp? Trận đấu phải có tính quyết định? Nếu không, thẩm phán sẽ chọn hạt giống như thế nào và có bao nhiêu trò chơi sẽ được chơi giữa hai chương trình, chỉ một? Các cuộc thi robocode thường có 10, để hạn chế ảnh hưởng của cơ hội mù.
vsz

3
Tôi không thực sự thích cách nó được thiết kế. Tôi nghĩ bạn nên đưa ra mã để chạy trận đấu bằng cách chạy 2 chương trình đã gửi, chuyển tiếp các bước di chuyển và tính điểm. Các chương trình đấu kiếm chỉ nên in các bước di chuyển của chúng ra thiết bị xuất chuẩn và đọc các động tác của đối thủ dưới dạng stdin.
aditsu

Câu trả lời:


5

Con trăn

Làm vườn!

Chiến binh của tôi kết hợp sự khó đoán với một con mắt sắc sảo cho sự yếu đuối trong lập trường của đối thủ. Anh ta khá tự tin rằng anh ta sẽ có thể loại bỏ những kẻ thù hung hãn nhưng huấn luyện viên của anh ta (tôi) có thể đã không lường trước được những kịch bản nhất định hoặc, có lẽ đáng lo ngại hơn, có thể đã hiểu sai các quy tắc (lỗi !!).

Dù sao tôi cũng mới nên hy vọng đây là định dạng ok cho mã:

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

yêu văn bản hương vị! Tôi hy vọng có được xung quanh để có được những thứ này để công kích nó ra đây vào cuối tuần này. Thật không may, đã rất lâu kể từ khi nó được đăng và nó mới đạt được lực kéo, vì vậy tôi có một chút không chuẩn bị ngay bây giờ để làm, nhưng tôi sẽ có thể ở đây trong vài ngày!
NRGdallas

1
Đừng lo lắng. Thành thật mà nói tôi đã không kiểm tra ngày của các bài viết ở trên. Người man rợ đó của @Arkady phải cảm thấy khá tự phụ / cô đơn trên ngọn đồi đó trong 8 tuần. Tôi sẽ sử dụng nó để lợi thế của tôi!
ejrb

Tôi sẽ kiểm tra điều này sau (Tôi không có trình thông dịch Python tại nơi làm việc) và có thể phản công sau. Hãy "cảnh giác" như họ có thể nói ở Pháp.
Arkady

2

Tôi yêu đồi!

Điều này bao gồm một khung chăm sóc khớp, đầu vào và đầu ra. Tất cả những gì bạn phải làm là xác định các phiên bản hai chức năng của riêng bạn trong tiêu đề "AIh" xác định bước di chuyển đầu tiên và mọi di chuyển khác.

Điều này biên dịch trong VS2012 (phiên bản miễn phí). Theo hiểu biết tốt nhất của tôi, nó sẽ biên dịch trong bất kỳ trình biên dịch tuân thủ tiêu chuẩn nào.

Tôi gọi AI này là "Người man rợ không tinh vi." Tôi chắc chắn sẽ không mất nhiều thời gian để ai đó đánh bại nó.

// 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
chỉ cần nhận thấy một lỗ hổng mã tiềm năng - khi bạn mã cho một khối, nó vẫn trả về bước di chuyển của một lunge! - hãy nhớ, theo các quy tắc, không được phép chỉnh sửa cho đến khi bạn bị đánh bại
NRGdallas

1
Điểm tốt. Điều đó có thể có nghĩa là AI cố gắng di chuyển bất hợp pháp. Điều gì xảy ra trong tình huống đó?
Arkady

Tôi cũng muốn nói thêm rằng tôi xem xét khung công khai và tất cả những ai muốn mượn nó và chỉ cần viết lại hai chức năng AI là miễn phí.
Arkady

bất kỳ động thái bất hợp pháp là một mất mát ngay lập tức.
NRGdallas

UNITIALIZED?!
Soham Chowdhury
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.