Exemple #1
0
def play(bot1_path, bot2_path, seconds_per_player):
    white_bot_name, white_player_cls = load_player(bot1_path)
    black_bot_name, black_player_cls = load_player(bot2_path)

    game = LocalGame(seconds_per_player)

    try:
        winner_color, win_reason, history = play_local_game(white_player_cls(), black_player_cls(), game=game)

        winner = 'Draw' if winner_color is None else chess.COLOR_NAMES[winner_color]
    except:
        traceback.print_exc()
        game.end()

        winner = 'ERROR'
        history = game.get_game_history()

    print('Game Over!')
    print('Winner: {}!'.format(winner))

    timestamp = datetime.datetime.now().strftime('%Y_%m_%d-%H_%M_%S')

    replay_path = '{}-{}-{}-{}.json'.format(white_bot_name, black_bot_name, winner, timestamp)
    print('Saving replay to {}...'.format(replay_path))
    history.save(replay_path)

    return winner
Exemple #2
0
 def test_white_resign(self):
     game = LocalGame()
     game.start()
     game.resign()
     game.end()
     self.assertEqual(BLACK, game.get_winner_color())
     self.assertEqual(WinReason.RESIGN, game.get_win_reason())
Exemple #3
0
def main():
    white_bot_name, black_bot_name = 'TroutBot', 'StrangeFish'

    game = LocalGame()

    try:
        winner_color, win_reason, history = play_local_game(
            TroutBot(),
            StrangeFish(*multiprocessing_strategies.create_strategy()),
            game=game)

        winner = 'Draw' if winner_color is None else chess.COLOR_NAMES[
            winner_color]
    except:
        traceback.print_exc()
        game.end()

        winner = 'ERROR'
        history = game.get_game_history()

    print('Game Over!')
    print('Winner: {}!'.format(winner))

    timestamp = datetime.now().strftime('%Y_%m_%d-%H_%M_%S')

    replay_path = '{}-{}-{}-{}.json'.format(white_bot_name, black_bot_name,
                                            winner, timestamp)
    print('Saving replay to {}...'.format(replay_path))
    history.save(replay_path)
class LocalGameSenseTest(unittest.TestCase):
    def setUp(self):
        self.game = LocalGame()

    def test_senses_actions_content(self):
        sense_actions = self.game.sense_actions()

        for square in SQUARES:
            self.assertIn(square, sense_actions)

    def test_sense_invalid(self):
        for square in [-1, 65, 66, 1023730, -2]:
            with self.assertRaises(ValueError):
                self.game.sense(square)

    def test_sense_squares(self):
        for square in SQUARES:
            sense_result = self.game.sense(square)
            squares = [s for s, p in sense_result]
            self.assertEqual(squares, SENSE_BY_SQUARE[square])

    def test_sense_pieces(self):
        for sense_square in SQUARES:
            sense_result = self.game.sense(sense_square)
            for square, piece in sense_result:
                self.assertEqual(piece, self.game.board.piece_at(square))
Exemple #5
0
class LocalGameMoveActionsTest(unittest.TestCase):
    STARTING_WHITE_PAWN_CAPTURES = [
        Move(A2, B3),
        Move(B2, A3),
        Move(B2, C3),
        Move(C2, B3),
        Move(C2, D3),
        Move(D2, C3),
        Move(D2, E3),
        Move(E2, D3),
        Move(E2, F3),
        Move(F2, E3),
        Move(F2, G3),
        Move(G2, F3),
        Move(G2, H3),
        Move(H2, G3),
    ]
    BLACK_STARTING_PAWN_CAPTURES = [
        Move(A7, B6),
        Move(B7, A6),
        Move(B7, C6),
        Move(C7, B6),
        Move(C7, D6),
        Move(D7, C6),
        Move(D7, E6),
        Move(E7, D6),
        Move(E7, F6),
        Move(F7, E6),
        Move(F7, G6),
        Move(G7, F6),
        Move(G7, H6),
        Move(H7, G6),
    ]

    def setUp(self):
        self.game = LocalGame()

    def test_starting_pawn_capture_moves(self):
        move_actions = self.game.move_actions()
        for move in self.STARTING_WHITE_PAWN_CAPTURES:
            self.assertIn(move, move_actions)
        self.game.board.turn = BLACK
        move_actions = self.game.move_actions()
        for move in self.BLACK_STARTING_PAWN_CAPTURES:
            self.assertIn(move, move_actions)

    def test_pass(self):
        self.assertNotIn(None, self.game.move_actions())
        self.assertNotIn(Move.null(), self.game.move_actions())

    def test_superset_fuzz(self, max_turns=500):
        turn = 1
        while not self.game.board.is_game_over() and turn < max_turns:
            truth_moves = set(self.game.board.generate_pseudo_legal_moves())
            recon_moves = set(self.game.move_actions())
            self.assertTrue(recon_moves.issuperset(truth_moves))

            self.game.board.push(random.sample(truth_moves, 1)[0])
            turn += 1
Exemple #6
0
 def test_expired_black(self):
     game = LocalGame()
     game.seconds_left_by_color[BLACK] = 0.5
     game.start()
     self.assertFalse(game.is_over())
     time.sleep(1)
     self.assertFalse(game.is_over())
     game.turn = BLACK
     self.assertTrue(game.is_over())
Exemple #7
0
 def test_black_king_captured(self):
     """
     r n b q . b n r
     p p p p p p p p
     . . . . . . . .
     . . . . . . . .
     . . . . . . . .
     . . . . . . . .
     P P P P P P P P
     R N B Q K B N R
     """
     game = LocalGame()
     game.board.set_board_fen('rnbq1bnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR')
     game.start()
     self.assertTrue(game.is_over())
Exemple #8
0
 def test_expired_white(self):
     game = LocalGame()
     game.seconds_left_by_color[WHITE] = 0.5
     game.start()
     self.assertFalse(game.is_over())
     time.sleep(1)
     self.assertTrue(game.is_over())
Exemple #9
0
def main():
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument('white_bot_path', help='path to white bot source file')
    parser.add_argument('black_bot_path', help='path to black bot source file')
    parser.add_argument(
        '--seconds_per_player',
        default=900,
        type=float,
        help='number of seconds each player has to play the entire game.')
    args = parser.parse_args()

    white_bot_name, white_player_cls = load_player(args.white_bot_path)
    black_bot_name, black_player_cls = load_player(args.black_bot_path)

    game = LocalGame(args.seconds_per_player)

    try:
        winner_color, win_reason, history = play_local_game(white_player_cls(),
                                                            black_player_cls(),
                                                            game=game)

        winner = 'Draw' if winner_color is None else chess.COLOR_NAMES[
            winner_color]
    except:
        traceback.print_exc()
        game.end()

        winner = 'ERROR'
        history = game.get_game_history()

    print('Game Over!')
    print('Winner: {}!'.format(winner))

    timestamp = datetime.datetime.now().strftime('%Y_%m_%d-%H_%M_%S')

    replay_path = '{}-{}-{}-{}.json'.format(white_bot_name, black_bot_name,
                                            winner, timestamp)
    print('Saving replay to {}...'.format(replay_path))
    history.save(replay_path)
Exemple #10
0
 def test_black_king_captured(self):
     """
     r n b q . b n r
     p p p p p p p p
     . . . . . . . .
     . . . . . . . .
     . . . . . . . .
     . . . . . . . .
     P P P P P P P P
     R N B Q K B N R
     """
     game = LocalGame()
     game.board.set_board_fen('rnbq1bnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR')
     game.start()
     self.assertEqual(WHITE, game.get_winner_color())
     self.assertEqual(WinReason.KING_CAPTURE, game.get_win_reason())
Exemple #11
0
def main():
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument('bot1_path', help='path to first bot source file')
    parser.add_argument('bot2_path', help='path to second bot source file')
    parser.add_argument(
        '--seconds_per_player',
        default=900,
        type=float,
        help='number of seconds each player has to play the entire game.')
    args = parser.parse_args()

    if random.randint(0, 1) == 0:
        white_bot_name, white_player_cls = load_player(args.bot1_path)
        black_bot_name, black_player_cls = load_player(args.bot2_path)
    else:
        white_bot_name, white_player_cls = load_player(args.bot2_path)
        black_bot_name, black_player_cls = load_player(args.bot1_path)

    game = LocalGame(args.seconds_per_player)

    winner_color, win_reason, history = play_local_game(white_player_cls(),
                                                        black_player_cls(),
                                                        game=game)

    winner = 'Draw' if winner_color is None else chess.COLOR_NAMES[winner_color]

    print('Game Over!')
    print('Winner: {}!'.format(winner))

    timestamp = datetime.datetime.now().strftime('%Y_%m_%d-%H_%M_%S')

    replay_path = '{}-{}-{}-{}.json'.format(white_bot_name, black_bot_name,
                                            winner, timestamp)
    print('Saving replay to {}...'.format(replay_path))
    history.save(replay_path)
 def test_turn_limit(self):
     game = LocalGame(full_turn_limit=1)
     game.start()
     for half_turn in range(2):
         game.sense(None)
         game.move(None)
         game.end_turn()
     self.assertEqual(None, game.get_winner_color())
     self.assertEqual(WinReason.TURN_LIMIT, game.get_win_reason())
Exemple #13
0
 def test_forced_over(self):
     game = LocalGame()
     game.start()
     game.end()
     self.assertIsNone(game.get_winner_color())
     self.assertIsNone(game.get_win_reason())
Exemple #14
0
 def test_white_resign(self):
     game = LocalGame()
     game.start()
     game.resign()
     self.assertTrue(game.is_over())
 def test_move_limit(self):
     game = LocalGame(reversible_moves_limit=1)
     game.start()
     for half_turn in range(2):
         game.sense(None)
         game.move(None)
         game.end_turn()
     self.assertEqual(None, game.get_winner_color())
     self.assertEqual(WinReason.MOVE_LIMIT, game.get_win_reason())
Exemple #16
0
 def test_no_time_white(self):
     game = LocalGame()
     game.seconds_left_by_color[WHITE] = 0
     game.start()
     self.assertTrue(game.is_over())
Exemple #17
0
 def test_no_time_black(self):
     game = LocalGame()
     game.seconds_left_by_color[BLACK] = 0
     game.start()
     self.assertTrue(game.is_over())
Exemple #18
0
 def test_forced_over(self):
     game = LocalGame()
     game.start()
     self.assertFalse(game.is_over())
     game.end()
     self.assertTrue(game.is_over())
Exemple #19
0
 def test_black_resign(self):
     game = LocalGame()
     game.start()
     game.end_turn()
     game.resign()
     game.end()
     self.assertEqual(WHITE, game.get_winner_color())
     self.assertEqual(WinReason.RESIGN, game.get_win_reason())
Exemple #20
0
    def test_capture(self):
        """
        r n b q k b n r
        p p p . . p p p
        . . . . . . . .
        . . . p p . . .
        . . . P P . . .
        . . . . . . . .
        P P P . . P P P
        R N B Q K B N R
        """
        game = LocalGame()
        game.board.set_board_fen('rnbqkbnr/ppp2ppp/8/3pp3/3PP3/8/PPP2PPP/RNBQKBNR')
        game.start()

        _, _, result1 = game.move(Move(D4, E5))
        self.assertEqual(result1, E5)
        self.assertEqual(result1, game.opponent_move_results())
        game.end_turn()

        self.assertEqual(result1, game.opponent_move_results())
        game.sense(E5)
        self.assertEqual(result1, game.opponent_move_results())
        _, _, result2 = game.move(Move(D5, E4))
        self.assertEqual(result2, E4)
        self.assertEqual(result2, game.opponent_move_results())
Exemple #21
0
 def test_not_over(self):
     game = LocalGame()
     game.start()
     self.assertFalse(game.is_over())
Exemple #22
0
 def test_black_resign(self):
     game = LocalGame()
     game.start()
     game.end_turn()
     game.resign()
     self.assertTrue(game.is_over())
Exemple #23
0
 def setUp(self):
     self.game = LocalGame()
Exemple #24
0
    def test_time(self, seconds=1, turns=20, phases=3):
        delta = seconds / (turns * phases)

        game = LocalGame(seconds_per_player=seconds)

        turn = True
        time_by_color = game.seconds_left_by_color.copy()

        game.start()
        for i in range(turns):
            for _ in range(phases):
                start = game.get_seconds_left()
                time.sleep(delta)
                end = game.get_seconds_left()

                self.assertAlmostEqual(start - end, delta, places=2)

            time_by_color[turn] = game.get_seconds_left()
            turn = not turn
            game.end_turn()
            self.assertAlmostEqual(game.get_seconds_left(), time_by_color[turn], places=2)
        game.end()
        self.assertAlmostEqual(game.get_seconds_left(), time_by_color[turn], places=2)
        time.sleep(delta)
        self.assertAlmostEqual(game.get_seconds_left(), time_by_color[turn], places=2)
Exemple #25
0
 def test_no_time_black(self):
     game = LocalGame()
     game.seconds_left_by_color[BLACK] = 0
     game.start()
     self.assertEqual(WHITE, game.get_winner_color())
     self.assertEqual(WinReason.TIMEOUT, game.get_win_reason())
Exemple #26
0
 def test_no_time_both(self):
     game = LocalGame(seconds_per_player=0)
     game.start()
     self.assertTrue(game.is_over())
Exemple #27
0
class LocalGameMoveTest(unittest.TestCase):
    def setUp(self):
        self.game = LocalGame()

    def test_legal_kingside_castle(self):
        """
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        R . . . K . . R
        """
        self.game.board.set_board_fen('8/8/8/8/8/8/8/R3K2R')
        self.game.board.set_castling_fen('KQkq')
        req, taken, opt_capture = self.game.move(Move(E1, G1))
        self.assertEqual(req, taken)
        self.assertIsNone(opt_capture)
        self.assertEqual(self.game.board.board_fen(), '8/8/8/8/8/8/8/R4RK1')

    def test_legal_queenside_castle(self):
        """
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        R . . . K . . R
        """
        self.game.board.set_board_fen('8/8/8/8/8/8/8/R3K2R')
        self.game.board.set_castling_fen('KQkq')
        req, taken, opt_capture = self.game.move(Move(E1, C1))
        self.assertEqual(req, taken)
        self.assertIsNone(opt_capture)
        self.assertEqual(self.game.board.board_fen(), '8/8/8/8/8/8/8/2KR3R')

    def test_queenside_castle_piece_between(self):
        """
        r . P . k b n r     r . . P k b n r     r P . . k b n r
        p p . p p p p p     p p . p p p p p     p p . p p p p p
        . . . . . . . .     . . . . . . . .     . . . . . . . .
        . . . . . . . .     . . . . . . . .     . . . . . . . .
        . . . . . . . .     . . . . . . . .     . . . . . . . .
        . . . . . . . .     . . . . . . . .     . . . . . . . .
        P P . P P P P P     P P . P P P P P     P P . P P P P P
        R . p . K B N R     R . . p K B N R     R p . . K B N R
        """

        for fen in ['r1P1kbnr/pp1ppppp/8/8/8/8/PP1PPPPP/R1p1KBNR',
                    'r2Pkbnr/pp1ppppp/8/8/8/8/PP1PPPPP/R2pKBNR',
                    'rP2kbnr/pp1ppppp/8/8/8/8/PP1PPPPP/Rp2KBNR']:
            self.game.board.set_board_fen(fen)
            self.game.board.turn = WHITE
            self.game.turn = WHITE
            req, tak, opt_capture = self.game.move(Move(E1, C1))
            self.assertEqual(tak, None)

            self.game.board.turn = BLACK
            self.game.turn = BLACK
            req, tak, opt_capture = self.game.move(Move(E8, C8))
            self.assertEqual(tak, None)

    def test_kingside_castle_piece_between(self):
        """
        r n b q k P . r     r n b q k . P r
        p p p p p . p p     p p p p p . p p
        . . . . . . . .     . . . . . . . .
        . . . . . . . .     . . . . . . . .
        . . . . . . . .     . . . . . . . .
        . . . . . . . .     . . . . . . . .
        P P P P P . P P     P P P P P . P P
        R N B Q K p . R     R N B Q K . p R
        :return:
        """
        for fen in ['rnbqkP1r/ppppp1pp/8/8/8/8/PPPPP1PP/RNBQKp1R',
                    'rnbqk1Pr/ppppp1pp/8/8/8/8/PPPPP1PP/RNBQK1pR']:
            self.game.board.set_board_fen(fen)
            self.game.board.turn = WHITE
            self.game.turn = WHITE
            req, tak, opt_capture = self.game.move(Move(E1, G1))
            self.assertEqual(tak, None)

            self.game.board.turn = BLACK
            self.game.turn = BLACK
            req, tak, opt_capture = self.game.move(Move(E8, G8))
            self.assertEqual(tak, None)

    def test_queenside_castle_no_rights(self):
        """
        r . . . k . . r
        p p p p p p p p
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        P P P P P P P P
        R . . . K . . R
        """
        self.game.board.set_board_fen('r3k2r/pppppppp/8/8/8/8/PPPPPPPP/R3K2R')

        self.game.board.turn = WHITE
        self.game.turn = WHITE
        for castling_fen in ['-', 'k', 'q', 'kq', 'Kk', 'Kq', 'Kkq']:
            self.game.board.set_castling_fen(castling_fen)
            with self.assertRaises(ValueError):
                self.game.move(Move(E1, C1))

        self.game.board.turn = BLACK
        self.game.turn = BLACK
        for castling_fen in ['-', 'K', 'Q', 'KQ', 'Kk', 'Qk', 'KQk']:
            self.game.board.set_castling_fen(castling_fen)
            with self.assertRaises(ValueError):
                self.game.move(Move(E8, C8))

    def test_kingside_castle_no_rights(self):
        """
        r . . . k . . r
        p p p p p p p p
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        P P P P P P P P
        R . . . K . . R
        """
        self.game.board.set_board_fen('r3k2r/pppppppp/8/8/8/8/PPPPPPPP/R3K2R')

        self.game.board.turn = WHITE
        self.game.turn = WHITE
        for castling_fen in ['-', 'k', 'q', 'kq', 'Qk', 'Qq', 'Qkq']:
            self.game.board.set_castling_fen(castling_fen)
            with self.assertRaises(ValueError):
                self.game.move(Move(E1, G1))

        self.game.board.turn = BLACK
        self.game.turn = BLACK
        for castling_fen in ['-', 'K', 'Q', 'KQ', 'Kq', 'Qq', 'KQq']:
            self.game.board.set_castling_fen(castling_fen)
            with self.assertRaises(ValueError):
                self.game.move(Move(E8, G8))

    def test_castling_into_check(self):
        """
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . q .
        . . . . . . . .
        . . . . . . . .
        . . . . K . . R
        """
        self.game.board.set_board_fen('8/8/8/8/6q1/8/8/4K2R')
        self.assertFalse(self.game.board.is_check())
        move = Move(E1, G1)
        req, taken, opt_capture = self.game.move(move)
        self.assertEqual(req, taken)
        self.assertIsNone(opt_capture)
        self.game.board.turn = WHITE
        self.assertTrue(self.game.board.is_check())

    def test_castling_out_of_check(self):
        """
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        q . . . K . . R
        """
        self.game.board.set_board_fen('8/8/8/8/8/8/8/q3K2R')
        self.assertTrue(self.game.board.is_check())
        move = Move(E1, G1)
        req, taken, opt_capture = self.game.move(move)
        self.assertEqual(req, taken)
        self.assertIsNone(opt_capture)
        self.game.board.turn = WHITE
        self.assertFalse(self.game.board.is_check())

    def test_castling_stay_in_check(self):
        """
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . q .
        . . . . . . . .
        . . . . K . . R
        """
        self.game.board.set_board_fen('8/8/8/8/8/6q1/8/4K2R')
        self.assertTrue(self.game.board.is_check())
        move = Move(E1, G1)
        req, taken, opt_capture = self.game.move(move)
        self.assertEqual(req, taken)
        self.assertIsNone(opt_capture)
        self.game.board.turn = WHITE
        self.assertTrue(self.game.board.is_check())

    def test_en_passant_white(self):
        """
        r n b q k b n r
        p . p p p p p p
        . . . . . . . .
        . . . . . . . .
        P p . . . . . .
        . . . . . . . .
        . P P P P P P P
        R N B Q K B N R
        """
        # test that en passant captures result in the correct capture square
        self.game.board.set_board_fen('rnbqkbnr/p1pppppp/8/8/1p6/8/PPPPPPPP/RNBQKBNR')

        req, taken, opt_capture = self.game.move(Move(A2, A4))
        self.assertEqual(req, taken)
        self.assertIsNone(opt_capture)

        req, taken, opt_capture = self.game.move(Move(B4, A3))
        self.assertEqual(req, taken)
        self.assertIsNotNone(opt_capture)
        self.assertEqual(opt_capture, A4)

    def test_en_passant_black(self):
        """
        r n b q k b n r
        p p p p p . p p
        . . . . . . . .
        . . . . . p P .
        . . . . . . . .
        . . . . . . . .
        P P P P P P . P
        R N B Q K B N R
        """
        # test that en passant captures result in the correct capture square
        self.game.board.set_board_fen('rnbqkbnr/pppppppp/8/6P1/8/8/PPPPPP1P/RNBQKBNR')
        self.game.turn = BLACK
        self.game.board.turn = BLACK

        req, taken, opt_capture = self.game.move(Move(F7, F5))
        self.assertEqual(req, taken)
        self.assertIsNone(opt_capture)

        req, taken, opt_capture = self.game.move(Move(G5, F6))
        self.assertEqual(req, taken)
        self.assertIsNotNone(opt_capture)
        self.assertEqual(opt_capture, F5)

    def test_move_opponent_piece(self):
        # test moving opponent pieces
        b = Board()
        b.turn = BLACK

        for move in b.generate_pseudo_legal_moves():
            with self.assertRaises(ValueError):
                self.game.move(move)

    def test_move_no_piece(self):
        # test a move from a square with no piece
        for from_square in SquareSet(BB_RANK_3 | BB_RANK_4 | BB_RANK_5 | BB_RANK_6):
            for to_square in SQUARES:
                with self.assertRaises(ValueError):
                    m = Move(from_square, to_square)
                    self.game.move(m)

    def test_move_illegal(self):
        for from_square in SquareSet(BB_RANK_1 | BB_RANK_2):
            for to_square in SQUARES:
                move = Move(from_square, to_square)
                if move not in self.game.move_actions():
                    with self.assertRaises(ValueError):
                        self.game.move(move)

    def test_sliding_straight_capture(self):
        """
        . . . . . . . .
        . . . p . . . .
        . . . . . . . .
        . p . R . p . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        """

        result_by_move = {
            Move(D5, C5): (Move(D5, C5), None),
            Move(D5, B5): (Move(D5, B5), B5),
            Move(D5, A5): (Move(D5, B5), B5),
            Move(D5, D6): (Move(D5, D6), None),
            Move(D5, D7): (Move(D5, D7), D7),
            Move(D5, D8): (Move(D5, D7), D7),
            Move(D5, E5): (Move(D5, E5), None),
            Move(D5, F5): (Move(D5, F5), F5),
            Move(D5, G5): (Move(D5, F5), F5),
            Move(D5, H5): (Move(D5, F5), F5),
            Move(D5, D4): (Move(D5, D4), None),
            Move(D5, D3): (Move(D5, D3), None),
            Move(D5, D2): (Move(D5, D2), None),
            Move(D5, D1): (Move(D5, D1), None),
        }
        for expected_req, (expected_taken, expected_capture) in result_by_move.items():
            self.game.board.set_board_fen('8/3p4/8/1p1R1p2/8/8/8/8')
            self.game.board.turn = WHITE
            self.game.turn = WHITE
            req, taken, opt_capture = self.game.move(expected_req)
            self.assertEqual(req, expected_req)
            self.assertEqual(taken, expected_taken)
            self.assertEqual(opt_capture, expected_capture)

    def test_sliding_straight_into_ally(self):
        """
        . . . . . . . .
        . . . p . . . .
        . . . . . . . .
        . p . R . p . .
        . . . . . . . .
        . . . . . . . .
        . . . P . . . .
        . . . . . . . .
        """
        for move in [Move(D5, D2), Move(D5, D1)]:
            self.game.board.set_board_fen('8/3p4/8/1p1R1p2/8/8/3P4/8')
            self.game.board.turn = WHITE
            self.game.turn = WHITE
            with self.assertRaises(ValueError):
                req, taken, opt_capture = self.game.move(move)

    def test_sliding_diagonal_capture(self):
        """
        p . . . . . p .
        . . . . . . . .
        . . . . . . . .
        . . . X . . . .
        . . . . . . . .
        . . . . . . . .
        p . . . . . p .
        . . . . . . . .
        """
        result_by_move = {
            Move(D5, C6): (Move(D5, C6), None),
            Move(D5, B7): (Move(D5, B7), None),
            Move(D5, A8): (Move(D5, A8), A8),
            Move(D5, E6): (Move(D5, E6), None),
            Move(D5, F7): (Move(D5, F7), None),
            Move(D5, G8): (Move(D5, G8), G8),
            Move(D5, E4): (Move(D5, E4), None),
            Move(D5, F3): (Move(D5, F3), None),
            Move(D5, G2): (Move(D5, G2), G2),
            Move(D5, H1): (Move(D5, G2), G2),
            Move(D5, C4): (Move(D5, C4), None),
            Move(D5, B3): (Move(D5, B3), None),
            Move(D5, A2): (Move(D5, A2), A2),
        }

        for expected_req, (expected_taken, expected_capture) in result_by_move.items():
            self.game.board.set_board_fen('p5p1/8/8/3B4/8/8/p5p1/8')
            self.game.board.turn = WHITE
            self.game.turn = WHITE
            req, taken, opt_capture = self.game.move(expected_req)
            self.assertEqual(req, expected_req)
            self.assertEqual(taken, expected_taken)
            self.assertEqual(opt_capture, expected_capture)

    def test_sliding_diagonal_into_ally(self):
        """
        p . . . . . p .
        . . . . . . . .
        . . . . . . . .
        . . . X . . . .
        . . . . . . . .
        . . . . . . . .
        p . . . . . P .
        . . . . . . . .
        """
        for move in [Move(D5, G2), Move(D5, H1)]:
            self.game.board.set_board_fen('p5p1/8/8/3B4/8/8/p5P1/8')
            self.game.board.turn = WHITE
            self.game.turn = WHITE
            with self.assertRaises(ValueError):
                req, taken, opt_capture = self.game.move(move)

    def test_pawn_auto_promotion(self):
        """
        . . . . . . . .
        . . . P . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        . . . . . . . .
        """
        self.game.board.set_board_fen('8/3P4/8/8/8/8/8/8')
        req, taken, opt_capture = self.game.move(Move(D7, D8))
        self.assertEqual(Move(D7, D8), req)
        self.assertNotEqual(req, taken)
        self.assertEqual(req.to_square, taken.to_square)
        self.assertEqual(req.from_square, taken.from_square)
        self.assertIsNone(req.promotion)
        self.assertEqual(taken.promotion, QUEEN)

    def test_pass(self):
        req, taken, opt_capture = self.game.move(None)
        self.assertEqual(req, None)
        self.assertEqual(taken, None)
        self.assertIsNone(opt_capture)

        self.game.board.turn = BLACK
        req, taken, opt_capture = self.game.move(None)
        self.assertEqual(req, None)
        self.assertEqual(taken, None)
        self.assertIsNone(opt_capture)

        self.game.board.turn = WHITE
        self.game.board.remove_piece_at(0)
        req, taken, opt_capture = self.game.move(None)
        self.assertEqual(req, None)
        self.assertEqual(taken, None)
        self.assertIsNone(opt_capture)

    def test_legal_fuzz(self, max_turns=500):
        board = Board()

        turn = 1
        while not board.is_game_over() and turn < max_turns:
            move = random.choice(list(board.generate_pseudo_legal_moves()) + [None])

            req, taken, opt_square = self.game.move(move)
            self.assertEqual(req, taken)
            if move is not None and board.is_capture(move):
                self.assertIsNotNone(opt_square)

            board.push(move if move is not None else Move.null())
            self.assertEqual(self.game.board, board)

            turn += 1
Exemple #28
0
def playback(game_history: GameHistory, player: Player, color: Color):
    game = LocalGame()

    player.handle_game_start(color, game.board.copy())
    game.start()

    turn = game_history.first_turn()

    while not game.is_over() and turn < game_history.last_turn():
        opt_capture_square = game.opponent_move_results()
        if game.turn == color:
            player.handle_opponent_move_result(opt_capture_square is not None,
                                               opt_capture_square)

        sense_actions = game.sense_actions()
        move_actions = game.move_actions()

        sense = game_history.sense(turn)
        player_sense = player.choose_sense(sense_actions, move_actions,
                                           game.get_seconds_left())
        if game.turn == color and sense != player_sense:
            print(
                'Warning: Sense action did not match history on turn {}. Using the sense action from history.'
                .format(turn))
        sense_result = game.sense(sense)
        if game.turn == color:
            player.handle_sense_result(sense_result)

        move = game_history.requested_move(turn)
        player_move = player.choose_move(move_actions, game.get_seconds_left())
        if game.turn == color and move != player_move:
            print(
                'Warning: Move action did not match history on turn {}. Using the move action from history.'
                .format(turn))
        requested_move, taken_move, opt_enemy_capture_square = game.move(move)
        if game.turn == color:
            player.handle_move_result(requested_move, taken_move,
                                      opt_enemy_capture_square is not None,
                                      opt_enemy_capture_square)

        game.end_turn()
        turn = turn.next

    game.end()
    winner_color = game.get_winner_color()
    win_reason = game.get_win_reason()
    game_history = game.get_game_history()

    player.handle_game_end(winner_color, win_reason, game_history)
Exemple #29
0
 def test_no_history_until_game_over(self):
     g = LocalGame()
     g.sense(E2)
     self.assertEqual(g.get_game_history(), None)
     g.move(Move(E2, E4))
     self.assertEqual(g.get_game_history(), None)
     g.sense(A8)
     g.move(Move(E7, E5))
     self.assertEqual(g.get_game_history(), None)
     g.sense(E2)
     g.move(Move(F1, B5))
     g.sense(A8)
     g.move(Move(D7, D5))
     g.sense(E8)
     g.move(Move(B5, E8))
     self.assertTrue(g.is_over())
     self.assertNotEqual(g.get_game_history(), None)
Exemple #30
0
 def test_no_capture(self):
     game = LocalGame()
     game.start()
     _, _, result1 = game.move(Move(A2, A4))
     self.assertIsNone(result1)
     self.assertEqual(result1, game.opponent_move_results())
     game.end_turn()
     self.assertEqual(result1, game.opponent_move_results())
     game.sense(E5)
     self.assertEqual(result1, game.opponent_move_results())
     _, _, result2 = game.move(Move(F7, F5))
     self.assertIsNone(result2)
     self.assertEqual(result2, game.opponent_move_results())