Exemplo n.º 1
0
    def check_game_over(
        self,
        message: Dict[str, str],
        bot_handler: Any,
        new_board: chess.Board
    ) -> bool:
        """Checks if a game is over due to
         - checkmate,
         - stalemate,
         - insufficient material,
         - 50 moves without a capture or pawn move, or
         - 3-fold repetition.
        Replies to the bot handler if it is game over.

        Parameters:
             - message: The Zulip Bots message object.
             - bot_handler: The Zulip Bots bot handler object.
             - new_board: The board object.

        Returns: True if it is game over, false if it's not.
        """
        # This assumes that the players will claim a draw after 3-fold
        # repetition or 50 moves go by without a capture or pawn move.
        # According to the official rules, the game is only guaranteed to
        # be over if it's  *5*-fold or *75* moves, but if either player
        # wants the game to be a draw, after 3 or 75 it a draw. For now,
        # just assume that the players would want the draw.
        if new_board.is_game_over(True):
            game_over_output = ''

            if new_board.is_checkmate():
                game_over_output = make_loss_response(
                    new_board,
                    'was checkmated'
                )
            elif new_board.is_stalemate():
                game_over_output = make_draw_response('stalemate')
            elif new_board.is_insufficient_material():
                game_over_output = make_draw_response(
                    'insufficient material'
                )
            elif new_board.can_claim_fifty_moves():
                game_over_output = make_draw_response(
                    '50 moves without a capture or pawn move'
                )
            elif new_board.can_claim_threefold_repetition():
                game_over_output = make_draw_response('3-fold repetition')

            bot_handler.send_reply(
                message,
                game_over_output
            )

            return True

        return False
Exemplo n.º 2
0
    def write_json(self, board: chess.Board):
        """
        Writes all of the board info in json
        """

        best_move = self.get_best_move(board)

        output = OrderedDict([
            ('fen', board.fen()),
            ('fullmoveNumber', board.fullmove_number),
            ('result', board.result()),
            ('isGameOver', board.is_game_over()),
            ('isCheckmate', board.is_checkmate()),
            ('isStalemate', board.is_stalemate()),
            ('isInsufficientMaterial', board.is_insufficient_material()),
            ('isSeventyfiveMoves', board.is_seventyfive_moves()),
            ('isFivefoldRepetition', board.is_fivefold_repetition()),
            ('white',
             OrderedDict([
                 ('hasKingsideCastlingRights',
                  board.has_kingside_castling_rights(chess.WHITE)),
                 ('hasQueensideCastlingRights',
                  board.has_queenside_castling_rights(chess.WHITE)),
             ])),
            ('black',
             OrderedDict([
                 ('hasKingsideCastlingRights',
                  board.has_kingside_castling_rights(chess.BLACK)),
                 ('hasQueensideCastlingRights',
                  board.has_queenside_castling_rights(chess.BLACK)),
             ])),
            ('turn',
             OrderedDict([
                 ('color', 'white' if board.turn is chess.WHITE else 'black'),
                 ('isInCheck', board.is_check()),
                 ('bestMove', best_move),
                 ('legalMoves', [move.uci() for move in board.legal_moves]),
                 ('canClaimDraw', board.can_claim_draw()),
                 ('canClaimFiftyMoves', board.can_claim_fifty_moves()),
                 ('canClaimThreefoldRepetition',
                  board.can_claim_threefold_repetition()),
             ])),
        ])

        self.finish(output)
Exemplo n.º 3
0
def get_game_over_reason(board: chess.Board,
                         claim_draw: bool = False,
                         both_agreed: bool = False) -> str:
    if claim_draw and both_agreed:
        return "Both opponents agreed to a draw"

    reasons = [
        "Checkmate",
        "Stalemate",
        "Insufficient material",
        "Draw by the seventyfive-move rule",
        "Draw by the fivefold repetition rule",
    ]
    checks = [
        board.is_checkmate(),
        board.is_stalemate(),
        board.is_insufficient_material(),
        board.is_seventyfive_moves(),
        board.is_fivefold_repetition(),
    ]

    if claim_draw:
        reasons = [
            *reasons,
            *[
                "Draw by the fifty-move rule",
                "Draw by the threefold repetition rule"
            ],
        ]
        checks = [
            *checks,
            *[
                board.can_claim_fifty_moves(),
                board.can_claim_threefold_repetition()
            ],
        ]

    possible = [reason for reason, check in zip(reasons, checks) if check]

    if len(possible) > 0:
        return possible[0]
    else:
        raise RuntimeError("No possible game over reason")
Exemplo n.º 4
0
def get_best_move(board: chess.Board) -> chess.Move:

    my_color = board.turn
    global_max_score = -sys.maxsize
    best_moves = []

    # attacked_pieces = get_attacked_pieces(board, my_color)
    # print(attacked_pieces)

    for my_candidate_move in list(board.legal_moves):

        board.push(my_candidate_move)

        bonus = 0

        if board.is_checkmate():
            return my_candidate_move

        if board.is_stalemate():
            bonus = +500

        if board.can_claim_threefold_repetition():
            current_score = __get_board_total_score(board, my_color)
            if current_score > 0:
                bonus = +1
            else:
                bonus = -1

        is_my_candidate_move_attacked = __is_attacked(board, my_candidate_move.to_square)

        candidate_min_score = sys.maxsize

        for opponent_candidate_move in list(board.legal_moves):

            board.push(opponent_candidate_move)

            if board.is_checkmate():
                current_score = -9999
            else:
                current_score = __get_board_total_score(board, my_color) + bonus
                if is_my_candidate_move_attacked:
                    current_score = current_score + 1

            candidate_min_score = min(current_score, candidate_min_score)

            board.pop()

        if candidate_min_score > global_max_score:
            global_max_score = candidate_min_score
            best_moves = [my_candidate_move]

        elif candidate_min_score == global_max_score:
            best_moves.append(my_candidate_move)

        board.pop()

    best_move = random.choice(best_moves)

    # Always promote to queen.
    if best_move.uci()[-1].isalpha():
        best_move.promotion = chess.QUEEN

    return best_move