Beispiel #1
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())
 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.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())
 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())
Beispiel #5
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())
 def test_unlimited(self):
     game = LocalGame(
         seconds_per_player=None,
         seconds_increment=None,
         full_turn_limit=None,
         reversible_moves_limit=None,
     )
     game.start()
     for half_turn in range(20):
         game.sense(None)
         game.move(None)
         game.end_turn()
     self.assertFalse(game.is_over())
Beispiel #7
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)
Beispiel #8
0
def playback(game_history: GameHistory, player: Player, color: Color):
    game = LocalGame()

    opponent_name = game_history.get_white_player_name()
    if color == chess.WHITE:
        opponent_name = game_history.get_black_player_name()
    player.handle_game_start(color, game.board.copy(), opponent_name)
    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)
Beispiel #9
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