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
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())
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))
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
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())
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())
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())
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)
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())
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())
def test_forced_over(self): game = LocalGame() game.start() game.end() self.assertIsNone(game.get_winner_color()) self.assertIsNone(game.get_win_reason())
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())
def test_no_time_white(self): game = LocalGame() game.seconds_left_by_color[WHITE] = 0 game.start() self.assertTrue(game.is_over())
def test_no_time_black(self): game = LocalGame() game.seconds_left_by_color[BLACK] = 0 game.start() self.assertTrue(game.is_over())
def test_forced_over(self): game = LocalGame() game.start() self.assertFalse(game.is_over()) game.end() self.assertTrue(game.is_over())
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())
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_not_over(self): game = LocalGame() game.start() self.assertFalse(game.is_over())
def test_black_resign(self): game = LocalGame() game.start() game.end_turn() game.resign() self.assertTrue(game.is_over())
def setUp(self): self.game = LocalGame()
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)
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())
def test_no_time_both(self): game = LocalGame(seconds_per_player=0) game.start() self.assertTrue(game.is_over())
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
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)
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)
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())