async def make_move(self, game: Game, move: str) -> Game: """ Makes a move in given game, if valid :param game: Game to be played :type game: Game :param move: Chess move in SAN or UCI notation :type move: str :return: Updated game :rtype: Game """ chess_move = self._parse_str_move(game, move) if not chess_move: raise InvalidMove() game.board.push(chess_move) game.current_player = game.player1 if game.current_player == game.player2 else game.player2 if self.is_pve_game(game) and not self.is_game_over(game): stockfish_result = await self._play_move(game) game.board.push(stockfish_result.move) game.current_player = game.player1 if self.is_game_over(game): game.result = game.board.result(claim_draw=True) self.games.remove(game) await game.save() return game
def test_make_move_legal_move_pve(self): board = chess.Board( 'rn2kb1r/pp1qpppp/2ppbn2/1B6/3PP3/2N2N2/PPP2PPP/R1BQK2R w KQkq - 0 6' ) game = Game() game.board = board game.player1 = FakeDiscordUser(id=1) game.player2 = FakeDiscordUser(id=2) game.current_player = game.player1 game.cpu_level = 0 chess_bot = Chess() chess_bot.games.append(game) chess_bot.stockfish_limit['time'] = 1 result = asyncio.run(chess_bot.make_move(game, 'b5d3')) self.assertIsInstance(result, Game) if chess_bot.is_stockfish_enabled(): self.assertEqual(len(result.board.move_stack), 2) self.assertEqual(result.current_player, game.player1) updated_chess_game = self.db_session.query(ChessGame).filter_by( player1_id=result.player1.id).first() updated_game_from_db = Game.from_chess_game_model(updated_chess_game) self.assertEqual(updated_game_from_db.board.move_stack, result.board.move_stack)
def test_make_move_draw_by_threefold_repetition(self): board = chess.Board() board.push_san("Nf3") board.push_san("Nf6") board.push_san("Ng1") board.push_san("Ng8") board.push_san("Nf3") board.push_san("Nf6") board.push_san("Ng1") game = Game() game.board = board game.player1 = FakeDiscordUser(id=1) game.player2 = FakeDiscordUser(id=2) game.current_player = game.player2 chess_bot = Chess() chess_bot.games.append(game) self.assertFalse(chess_bot.is_game_over(game)) result = asyncio.run(chess_bot.make_move(game, 'Ng8')) self.assertIsInstance(result, Game) self.assertEqual(len(chess_bot.games), 0) self.assertEqual( self.db_session.query(ChessGame).filter_by(result=0).count(), 1) self.assertTrue(chess_bot.is_game_over(result)) self.assertEqual(result.result, '1/2-1/2')
def test_find_current_game_other_player_not_found(self): chess_bot = Chess() board = chess.Board() board.push_san("e4") board.push_san("e5") game1 = Game() game1.board = board game1.player1 = FakeDiscordUser(id=1) game1.player2 = FakeDiscordUser(id=2) game1.current_player = game1.player1 chess_bot.games.append(game1) game2 = Game() game2.board = board game2.player1 = FakeDiscordUser(id=1) game2.player2 = FakeDiscordUser(id=3) game2.current_player = game2.player1 chess_bot.games.append(game2) with self.assertRaises(Exception) as e: chess_bot.find_current_game(user=FakeDiscordUser(id=14)) self.assertIn("Partida não encontrada", str(e))
def test_find_current_game_player_playing_themselves_and_others(self): chess_bot = Chess() board = chess.Board() board.push_san("e4") board.push_san("e5") game1 = Game() game1.board = board game1.player1 = FakeDiscordUser(id=1) game1.player2 = FakeDiscordUser(id=2) game1.current_player = game1.player1 chess_bot.games.append(game1) game2 = Game() game2.board = board game2.player1 = FakeDiscordUser(id=1) game2.player2 = FakeDiscordUser(id=1) game2.current_player = game2.player1 chess_bot.games.append(game2) result = chess_bot.find_current_game(user=game2.player1, other_user=game2.player2) self.assertEqual(result, game2)
def test_find_current_game_in_players_turn_amibiguity_solved(self): chess_bot = Chess() board = chess.Board() board.push_san("e4") board.push_san("e5") game1 = Game() game1.board = board game1.player1 = FakeDiscordUser(id=1) game1.player2 = FakeDiscordUser(id=2) game1.current_player = game1.player1 chess_bot.games.append(game1) game2 = Game() game2.board = board game2.player1 = FakeDiscordUser(id=1) game2.player2 = FakeDiscordUser(id=3) game2.current_player = game2.player1 chess_bot.games.append(game2) result = chess_bot.find_current_game(user=game1.player1, other_user=game1.player2) self.assertEqual(result, game1)
def test_find_current_game_in_players_turn_with_amibiguity(self): chess_bot = Chess() board = chess.Board() board.push_san("e4") board.push_san("e5") game1 = Game() game1.board = board game1.player1 = FakeDiscordUser(id=1) game1.player2 = FakeDiscordUser(id=2) game1.current_player = game1.player1 chess_bot.games.append(game1) game2 = Game() game2.board = board game2.player1 = FakeDiscordUser(id=1) game2.player2 = FakeDiscordUser(id=3) game2.current_player = game2.player1 chess_bot.games.append(game2) with self.assertRaises(Exception) as e: chess_bot.find_current_game(user=game1.player1) self.assertIn("Informe contra qual jogador", str(e))
def test_find_current_game_in_players_turn_no_ambiguity(self): board = chess.Board() board.push_san("e4") board.push_san("e5") game = Game() game.board = board game.player1 = FakeDiscordUser(id=1) game.player2 = FakeDiscordUser(id=2) game.current_player = game.player1 chess_bot = Chess() chess_bot.games.append(game) result = chess_bot.find_current_game(user=game.player1) self.assertEqual(result, game)
def test_resign_game_found(self): board = chess.Board() board.push_san("e4") board.push_san("e5") board.push_san("Nf3") game = Game() game.board = board game.player1 = FakeDiscordUser(id=1) game.player2 = FakeDiscordUser(id=2) game.current_player = game.player1 chess_bot = Chess() chess_bot.games.append(game) result = asyncio.run(chess_bot.resign(game)) self.assertEqual(len(chess_bot.games), 0) self.assertEqual( self.db_session.query(ChessGame).filter_by(result=1).count(), 1)
def test_make_move_illegal_move_in_players_turn(self): board = chess.Board() board.push_san("e4") board.push_san("e5") game = Game() game.board = board game.player1 = FakeDiscordUser(id=1) game.player2 = FakeDiscordUser(id=2) game.current_player = game.player1 chess_bot = Chess() chess_bot.games.append(game) with self.assertRaises(InvalidMove) as e: asyncio.run(chess_bot.make_move(game, 'invalid')) self.assertEqual(len(game.board.move_stack), 2) self.assertEqual(game.current_player, game.player1)
def test_eval_last_move_no_blunder_no_mate(self): board = chess.Board() board.push_san("g4") board.push_san("e5") game = Game() game.board = board game.player1 = FakeDiscordUser(id=1) game.player2 = FakeDiscordUser(id=2) game.current_player = game.player1 game.last_eval = Cp(0) chess_bot = Chess() chess_bot.games.append(game) chess_bot.stockfish_limit["time"] = 2 result = asyncio.run(chess_bot.eval_last_move(game)) self.assertFalse(result["blunder"]) self.assertIsNone(result["mate_in"])
def test_generate_pgn(self): board = chess.Board() board.push_san("g4") board.push_san("e5") board.push_san("f4") game = Game() game.board = board game.player1 = FakeDiscordUser(id=1, name='Player1') game.player2 = FakeDiscordUser(id=2, name='Player2') game.current_player = game.player1 game.result = game.board.result() chess_bot = Chess() chess_bot.games.append(game) result = chess_bot.generate_pgn(game) self.assertIn('[White "Player1"]', result) self.assertIn('[Black "Player2"]', result) self.assertIn('1. g4 e5 2. f4 *', result)
def test_eval_last_move_no_blunder_mate_in_two(self): board = chess.Board( "Q2r4/1p1k4/1P3ppp/1Kp1r3/4p2b/1B3P2/2P2q2/8 w - - 6 44") game = Game() game.board = board game.player1 = FakeDiscordUser(id=1) game.player2 = FakeDiscordUser(id=2) game.current_player = game.player1 game.last_eval = Mate(2) chess_bot = Chess() chess_bot.games.append(game) result = asyncio.run(chess_bot.eval_last_move(game)) self.assertFalse(result["blunder"]) if chess_bot.is_stockfish_enabled(): self.assertEqual(result["mate_in"], 2) else: self.assertIsNone(result["mate_in"])
def new_game(self, user1, user2, color_schema=None, cpu_level=None): player1, player2 = convert_users_to_players(user1, user2) current_players_pairs = map(lambda x: [x.player1, x.player2], self.games) given_players_pairs = [player1, player2] if given_players_pairs in current_players_pairs: raise GameAlreadyInProgress() game = Game() game.board = chess.Board() game.player1 = player1 game.player2 = player2 game.current_player = player1 game.result = game.board.result() game.color_schema = color_schema game.cpu_level = cpu_level self.games.append(game) return game
def test_eval_last_move_lost_position_blunders_mate(self): board = chess.Board( "Q1kr4/1p6/1P3ppp/1Kp1r3/4p2b/1B3P2/2P2q2/8 b - - 5 43") game = Game() game.board = board game.player1 = FakeDiscordUser(id=1) game.player2 = FakeDiscordUser(id=2) game.current_player = game.player1 game.last_eval = Cp(1000) chess_bot = Chess() chess_bot.games.append(game) result = asyncio.run(chess_bot.eval_last_move(game)) if chess_bot.is_stockfish_enabled(): self.assertTrue(result["blunder"]) self.assertEqual(result["mate_in"], -2) else: self.assertFalse(result["blunder"]) self.assertIsNone(result["mate_in"])
def test_make_move_finish_game(self): board = chess.Board() board.push_san("g4") board.push_san("e5") board.push_san("f4") game = Game() game.board = board game.player1 = FakeDiscordUser(id=1) game.player2 = FakeDiscordUser(id=2) game.current_player = game.player1 chess_bot = Chess() chess_bot.games.append(game) result = asyncio.run(chess_bot.make_move(game, 'd8h4')) self.assertIsInstance(result, Game) self.assertEqual(len(chess_bot.games), 0) self.assertEqual( self.db_session.query(ChessGame).filter_by(result=-1).count(), 1) self.assertTrue(chess_bot.is_game_over(result)) self.assertEqual(result.result, '0-1')
def test_eval_last_move_last_move_blunder_mate_in_one(self): board = chess.Board() board.push_san("g4") board.push_san("e5") board.push_san("f4") game = Game() game.board = board game.player1 = FakeDiscordUser(id=1) game.player2 = FakeDiscordUser(id=2) game.current_player = game.player1 game.last_eval = Cp(0) chess_bot = Chess() chess_bot.games.append(game) result = asyncio.run(chess_bot.eval_last_move(game)) if chess_bot.is_stockfish_enabled(): self.assertTrue(result["blunder"]) self.assertEqual(result["mate_in"], 1) else: self.assertFalse(result["blunder"]) self.assertIsNone(result["mate_in"])
def test_make_move_legal_san_move_in_players_turn(self): board = chess.Board() board.push_san("e4") board.push_san("e5") game = Game() game.board = board game.player1 = FakeDiscordUser(id=1) game.player2 = FakeDiscordUser(id=2) game.current_player = game.player1 chess_bot = Chess() chess_bot.games.append(game) result = asyncio.run(chess_bot.make_move(game, 'Nf3')) self.assertIsInstance(result, Game) self.assertEqual(len(result.board.move_stack), 3) self.assertEqual(result.current_player, game.player2) updated_chess_game = self.db_session.query(ChessGame).filter_by( player1_id=result.player1.id).first() updated_game_from_db = Game.from_chess_game_model(updated_chess_game) self.assertEqual(updated_game_from_db.board.move_stack, result.board.move_stack)