Exemple #1
0
    def update_game(self, request: dict) -> dict:
        """
        Update a certain game from source to target, and promotion role if occurred.
        :param request: A dict including session id, source coordinate, target coordinate,current logged in user and
        promotion role.
        :return: A dict including info about update validation, whether being checked, game status and turn color.
        """
        session_id = request["session_id"]
        username = request["user"]
        if self.sessions[session_id][1] == username:
            src = request["src"]
            tar = request["tar"]
            role = request["role"]
            src_coord = Utility.decode(src)
            tar_coord = Utility.decode(tar)
            game = self.sessions[session_id][0]
            valid = game.update(src_coord, tar_coord, role)

            if valid:
                self.update_history(session_id)
                self.update_current(session_id)
            is_being_checked = game.is_being_checked()
            status = game.check_game_status()
            turn = game.get_turn()
            # AI's turns
            if status == "Continue" and valid and self.modes[
                    session_id] != "pvp":
                if self.modes[session_id] == 'easy':
                    ai = SimpleAI(game)
                elif self.modes[session_id] == 'advanced':
                    ai = AdvancedAI(game)

                # noinspection PyUnboundLocalVariable
                src_row, src_col, tar_row, tar_col = ai.get_next_move()
                src = (src_row, src_col)
                tar = (tar_row, tar_col)
                valid = game.update(src, tar, "Queen")
                if valid:
                    self.update_history(session_id)
                    self.update_current(session_id)
                is_being_checked = game.is_being_checked()
                status = game.check_game_status()
                turn = game.get_turn()

            if status in ["WhiteLoss", "BlackLoss"
                          ] and valid and self.modes[session_id] != "pvp":
                self.update_score(session_id, username, status)

            return {
                "valid": valid,
                "is_being_checked": is_being_checked,
                "game_status": status,
                "turn": turn,
                "validSession": True
            }

        return {"valid": False, "validSession": False}
    def update(self, src: tuple, tar: tuple, role: str, is_ai=False) -> bool:
        """
        Game parameter information will be updated after a valid movement and return True. If the movement is not valid,
        nothing will be updated, and return False.
        :param src: the position of the piece move from
        :param tar: the position of the piece move to
        :param role: promotion role while the pawn reaches the eighth rank to be replaced by.
        :param is_ai: promotion role while the pawn reaches the eighth rank to be replaced by.
        :return: A boolean value which show the movement is valid or not. If the movement is valid, all game parameters
        are updated, otherwise no change.
        """

        # If the game status is not 'Continue", then return False and nothing updated.
        if not is_ai and self.check_game_status() != "Continue":
            return False
        # If not in for the source piece turn, or the target movement position is not in the source piece movement list,
        # then then return False and nothing updated.
        src_row, src_col = src
        tar_row, tar_col = tar
        src_piece = self.board[src_row][src_col]
        if not is_ai and self.board[src_row][src_col].color != self.turn:
            return False
        if not is_ai and tar not in src_piece.get_checked_moves()["moves"]:
            return False
        # Implement en_passant
        self.update_en_passant(src, tar)
        # Reset en_passant notation
        self.en_passant_target_notation = '-'
        # Update Rook and King firstMove.
        if type(src_piece) in [King, Rook]:
            src_piece.firstMove = False
        # Update castling notation
        self.castling_notation = self.get_castling_notation()
        # Update en_passant target square notation
        self.update_en_passant_notation(src, tar)
        # Implement Castle
        self.update_castle(src, tar)
        # Update movement clock counts
        self.update_movement_clock(src, tar)
        # If the Pawn reached the button, then it would be promoted as promotion piece which passed through argument.
        self.update_promotion(src, tar, role)

        self.movement = {
            "src": Utility.encode(src_row, src_col),
            "tar": Utility.encode(tar_row, tar_col)
        }
        self.fen = self.get_fen()
        self.history.append({"fen": self.fen, "movement": self.movement})
        return True
Exemple #3
0
    def get_next_move(self) -> tuple:
        """
        AI will brute force all valid moves and choose the one with the biggest value from get_value()
        :return: A four tuple indicates AI's move
        """
        board = copy.deepcopy(self.game.board)
        src_row, src_col, tar_row, tar_col = 0, 0, 0, 0
        max_score = -10000
        for row in range(8):
            for col in range(8):
                moves = self.game.get_checked_moves((row, col))["moves"]
                for coordinate in moves:
                    r1, c1 = Utility.decode(coordinate)
                    src_piece = board[row][col]
                    tar_piece = board[r1][c1]
                    board[r1][c1] = src_piece
                    board[row][col] = self.game.empty_cell
                    ret = self.get_value(board)
                    if ret > max_score:
                        src_row, src_col, tar_row, tar_col = row, col, r1, c1
                        max_score = ret
                    board[row][col] = src_piece
                    board[r1][c1] = tar_piece

        return src_row, src_col, tar_row, tar_col
Exemple #4
0
 def test_replay_a_session(self):
     db_url = os.path.join('sqlite:///' + os.getcwd(), 'game.db')
     api = ChessAPI(db_url=db_url)
     session_id = api.create_game("hu4396", "pvp")["session_id"]
     api.update_game({"session_id": session_id, "src": Utility.encode(1, 0), "tar": Utility.encode(3, 0),
                      "role": "Pawn", "user": "******"})
     ret = api.replay("hu4396", session_id, 1)
     self.assertEqual(ret["history"], {'src': 'a2', 'tar': 'a4'})
Exemple #5
0
    def test_get_checked_moves(self):
        coord = Utility.encode(1, 1)
        db_url = os.path.join('sqlite:///' + os.getcwd(), 'game.db')
        api = ChessAPI(db_url=db_url)

        session_id = api.create_game("hu4396", "pvp")["session_id"]
        checked = api.get_checked_moves({"session_id": session_id, "coordinate": coord}, "hu4396")
        self.assertEqual(checked, {'moves': ['b3', 'b4'], 'valid': True})
        ChessAPITestCase.remove_db_file()
 def update_en_passant_notation(self, src: tuple, tar: tuple) -> None:
     """
     Update en_passant target square notation
     :param: src: Coordinate, tar: Coordinate
     :return: None
     """
     src_row, src_col = src
     src_piece = self.board[src_row][src_col]
     tar_row, tar_col = tar
     if type(src_piece) == Pawn:
         step = tar_row - src_row
         if abs(step) == 2 and src_col == tar_col:
             if step > 0:
                 self.en_passant_target_notation = Utility.encode(
                     tar_row - 1, tar_col)
             else:
                 self.en_passant_target_notation = Utility.encode(
                     tar_row + 1, tar_col)
     return None
Exemple #7
0
 def test_update_game(self):
     db_url = os.path.join('sqlite:///' + os.getcwd(), 'game.db')
     api = ChessAPI(db_url=db_url)
     conn = api.engine.connect()
     session_id = api.create_game("hu4396", "pvp")["session_id"]
     api.update_game({"session_id": session_id, "src": Utility.encode(1, 0), "tar": Utility.encode(3, 0),
                      "role": "Pawn", "user": "******"})
     ret = conn.execute(api.history.select().where(api.history.c.session_id == session_id))
     updated_src = ret.fetchall()[0]["src"]
     conn.close()
     self.assertEqual("a2", updated_src)
     ChessAPITestCase.remove_db_file()
 def get_checked_moves(self, coordinate: tuple) -> dict:
     """
     While checkmate, each current turn piece available movements which can release the checkmate.
     :param coordinate: piece position
     :return: A dictionary with key "moves", and value is a array list which includes the available movements while
     checkmate.
     """
     row, col = coordinate
     piece = self.board[row][col]
     if piece.color != self.turn or self.check_game_status() != "Continue":
         return {"moves": []}
     ret = piece.get_checked_moves()["moves"]
     ret = Utility.encode_list(ret)
     return {"moves": ret}
Exemple #9
0
 def get_checked_moves(self, request: dict, username: str) -> dict:
     """
     Get all valid moves which won't let you be checked in certain game for a coordinate.
     :param request: A dict including session id and piece coordinate
     :param username: logged in user
     :return: A dict which including all valid moves which won't let you be checked in certain game for a coordinate.
     """
     session_id = request["session_id"]
     if session_id in self.sessions and self.sessions[session_id][
             1] == username:
         coordinate = request["coordinate"]
         coordinate = Utility.decode(coordinate)
         game = self.sessions[session_id][0]
         ret = game.get_checked_moves(coordinate)
         ret["valid"] = True
         return ret
     return {"valid": False}
Exemple #10
0
 def update_en_passant(self, src: tuple, tar: tuple) -> None:
     """
     Implement en_passant
     :param: src: Coordinate, tar: Coordinate
     :return: None
     """
     src_row, src_col = src
     src_piece = self.board[src_row][src_col]
     tar_row, tar_col = tar
     tar_piece = self.board[tar_row][tar_col]
     if type(
             src_piece
     ) == Pawn and src_col != tar_col and tar_piece == self.empty_cell:
         last_pawn_row, last_pawn_col = Utility.decode(
             self.history[-1]["movement"]["tar"])
         self.board[last_pawn_row][last_pawn_col] = self.empty_cell
     return None
Exemple #11
0
 def test_encode(self):
     self.assertEqual(Utility.encode(1, 2), "c2")
     self.assertEqual(Utility.encode(2, 2), "c3")
     self.assertEqual(Utility.encode(5, 3), "d6")
     self.assertEqual(Utility.encode(0, 0), "a1")
     self.assertEqual(Utility.encode(7, 7), "h8")
Exemple #12
0
 def test_encode_list(self):
     input_list = [(1, 3), (3, 7), (6, 6)]
     actual = Utility.encode_list(input_list)
     expected = ["d2", "h4", "g7"]
     self.assertEqual(actual, expected)
Exemple #13
0
 def test_decode(self):
     self.assertEqual(Utility.decode("c2"), (1, 2))
     self.assertEqual(Utility.decode("c3"), (2, 2))
     self.assertEqual(Utility.decode("d6"), (5, 3))
     self.assertEqual(Utility.decode("a1"), (0, 0))
     self.assertEqual(Utility.decode("h8"), (7, 7))