Beispiel #1
0
def player_move(game: Game) -> None:
    """
    loop to wait for move from player = eventdetected from reed switch matrix. The loop is finished when a valid move has been made.
    """
    State.set(States.PLAYER_TURN)
    LOG.info('player turn')
    epaper_screen.update_frame(button_panel,
                               epaper.game_player_turn(button_panel))
    epaper_screen.update_frame(button_panel,
                               epaper.game_engine_info(
                                   player_turn=True, engine=game.setup.engine),
                               important=False)
    epaper_screen.update_frame(button_panel,
                               epaper.game_player_turn(
                                   button_panel=button_panel,
                                   content=epaper.PLAYER_WAIT,
                                   partial_frame=True),
                               important=False)

    legal_moves = game.board.legal_moves
    legal_move_from = {move.from_square for move in game.board.legal_moves}
    while State.is_set(States.PLAYER_TURN):
        if game.piece_up is None:
            legal_squares = legal_move_from
        else:
            legal_squares = {
                move.to_square
                for move in legal_moves if move.from_square == game.piece_up
            }

        LOG.debug('waiting for move...')
        button_panel.wait_for_move()
        if state.is_set(States.MAIN):
            return

        incoming = serial_arduino.new_detected_move()
        if game.hint:
            erase_hint = epaper.PartialFrame(name='erase_hint',
                                             width=200,
                                             height=40,
                                             pos=(200, 165),
                                             important=False)
            epaper_screen.update_frame(button_panel, erase_hint)
            game.hint = False

        new_move = validate_player_move(game, incoming, legal_squares)
        if isinstance(new_move, chess.Move):
            break

        if game.setup.wait_to_confirm:
            epaper_screen.update_frame(button_panel, epaper.PLAYER_CONFIRM)
            while not confirm_move(game):
                pass

        new_move = chess.Move(game.piece_up, incoming)
        push_move(game, new_move)
        State.set(States.GAME)
Beispiel #2
0
def undo(game: Game) -> None:
    """
    wait for correct reversed move.
    show player 2 reversed moves (1 computer, 1 player)
    remove moves from GAME.board.movestack but keep a copy in the GAME.move_stack_copy
    keep the old movestack until a new move/confirmation computer move has been made (in case of "redo" call)
    :return:
    """
    LOG.debug('BUTTON_EVENT undo')
    # (led indicators) make frame show computer move in reverse
    move1 = game.board.pop()  # pop function from chess.Board
    move2 = game.board.pop()
    # copy the move stack fir when the redo function is called
    game.move_stack_copy.append(move1)
    game.move_stack_copy.append(move2)

    # reverse moves
    move1 = chess.Move(move1.to_square, move1.from_square)
    move2 = chess.Move(move2.to_square, move2.from_square)

    text0 = epaper.FrameText(pos=(214, 15),
                             content='Undo move:',
                             fill=config.WHITE)
    text1 = epaper.FrameText(pos=(30, 40),
                             content=''.join([str(move2),
                                              str(move1)]),
                             font=config.FONT_BIG)
    epaper_screen.update_frame(button_panel,
                               epaper.game_player_turn(
                                   button_panel=button_panel,
                                   content=(text0, text1),
                                   partial_frame=True),
                               important=False)
    # Interrupt active on buttons  'undo' 'redo'
    # Undo 1 computer move
    while True:
        button_panel.wait_for_move()
        if validate_computer_move(game, move1):
            break

    # Undo 1 player move
    while True:
        button_panel.wait_for_move()
        if validate_computer_move(game, move2):
            break

    epaper_screen.update_frame(
        button_panel, epaper.game_player_turn(button_panel=button_panel))
    epaper_screen.update_frame(button_panel,
                               epaper.game_player_turn(
                                   button_panel=button_panel,
                                   content=epaper.PLAYER_WAIT,
                                   partial_frame=True),
                               important=False)
Beispiel #3
0
def invalid_move(game: Game) -> None:
    """Handle invalid moves"""
    if game.piece_up is None:
        message = 'This piece cannot be moved'
    else:
        message = 'Invalid move'

    validate_board(game, message=message)
    epaper_screen.update_frame(
        button_panel, epaper.game_player_turn(button_panel=button_panel))
    epaper_screen.update_frame(button_panel,
                               epaper.game_player_turn(
                                   button_panel=button_panel,
                                   content=epaper.PLAYER_WAIT,
                                   partial_frame=True),
                               important=False)
Beispiel #4
0
def redo(game: Game) -> None:
    """
    redo undone move(s).
    Show player 2 moves. (1 computer, 1 player).
    Remove moves from GAME.move_stack_copy and push them on the GAME.board
    :return:
    """
    LOG.debug('BUTTON_EVENT redo')
    if game.move_stack_copy == 0:
        message = epaper.FrameText(content='This is the last move',
                                   pos=(15, 6))
        epaper_screen.update_frame(
            button_panel,
            epaper.game_player_turn(button_panel=button_panel,
                                    content=message,
                                    partial_frame=True))
        return

    # led indicators
    # Get 2 moves from the movestack copy
    move1 = game.move_stack_copy.pop()
    move2 = game.move_stack_copy.pop()

    text = epaper.FrameText(pos=(15, 6),
                            content=''.join([str(move2),
                                             str(move1)]),
                            fill=config.WHITE,
                            font=config.FONT_BIG)
    epaper_screen.update_frame(
        button_panel,
        epaper.game_player_turn(button_panel=button_panel,
                                content=text,
                                partial_frame=True))

    while True:
        button_panel.wait_for_move()
        if validate_computer_move(game, move1):
            game.board.push(move1)
            break

    while True:
        button_panel.wait_for_move()
        if validate_computer_move(game, move2):
            game.board.push(move2)
            break
Beispiel #5
0
def back_to_game(game: Game) -> None:
    """
    go back to previous GAME menu:
    - Validate board    OR
    - player turn       OR
    - Computer turn
    """
    LOG.debug('BUTTON_EVENT back to GAME')
    if state.is_set(States.BOARD_INVALID):  # redraw the 'validate board' frame
        current_board = get_board_square_set(game.board)
        incoming_board = chess.SquareSet(squares=serial_arduino.ask_board())
        frame = epaper.game_validate_board(button_panel, "board invalid",
                                           current_board, incoming_board,
                                           game.board)
        epaper_screen.update_frame(button_panel, frame, important=True)
        serial_arduino.trigger_arduino_int()  # wait again for a reed interrupt

    elif state.is_set(States.PLAYER_TURN):
        engine_info = epaper.game_engine_info(player_turn=True,
                                              engine=game.setup.engine)
        epaper_screen.update_frame(button_panel,
                                   epaper.game_player_turn(button_panel))
        epaper_screen.update_frame(button_panel, engine_info, important=False)

    elif state.is_set(States.COMPUTER_TURN):
        engine_info = epaper.game_engine_info(player_turn=False,
                                              engine=game.setup.engine)
        epaper_screen.update_frame(
            button_panel, epaper.game_computer_turn(button_panel=button_panel))
        epaper_screen.update_frame(button_panel, engine_info, important=False)
        if game.computer_move.move:
            new_move = game.computer_move.move
            epaper_screen.update_frame(button_panel, epaper.COMPUTER_CONFIRM)
            epaper_screen.update_frame(
                button_panel,
                epaper.game_computer_turn(button_panel=button_panel,
                                          move_text=epaper.get_move_text(
                                              new_move, game.board),
                                          partial_frame=True))

        else:
            epaper_screen.update_frame(
                button_panel,
                epaper.game_computer_turn(
                    button_panel=button_panel,
                    move_text=epaper.game_computer_thinking(game.setup),
                    partial_frame=True),
                important=False)
            # Waiting for player to make computer move
            button_panel.toggle_alarm(active=False)
Beispiel #6
0
def push_move(game: Game, move: chess.Move) -> None:
    """
    Push move to board.move_stack
    :param game: Game
    :param move: chess.Move
    :return:
    """
    if game.setup.color.value == game.board.turn:
        epaper_screen.update_frame(
            button_panel,
            epaper.game_player_turn(button_panel=button_panel,
                                    content=epaper.PLAYER_MOVE_CONFIRMED,
                                    partial_frame=True))

    game.board.push(move)
    game.piece_up = -1
    LOG.info('move pushed')
Beispiel #7
0
def give_hint(game: Game) -> None:
    """Write ponder move on the frame --> frame_player_turn"""
    LOG.debug('BUTTON_EVENT give hint')
    epaper_screen.update_frame(button_panel, epaper.PLAYER_HINT)
    if game.computer_move.ponder is not None:
        text = epaper.get_move_text(game.computer_move.ponder, game.board)
    else:
        text = epaper.FrameText(content='No hint available',
                                pos=(75, 25),
                                fill=config.WHITE,
                                font=config.FONT_BIGGER,
                                align=config.CENTER)

    epaper_screen.update_frame(
        button_panel,
        epaper.game_player_turn(button_panel=button_panel,
                                content=text,
                                partial_frame=True))
    game.hint = True
Beispiel #8
0
def validate_player_move(game: Game, move: int,
                         legal_moves: Set[chess.Move]) -> chess.Move:
    """
    validations:    - can the piece make any move (black and white)?
                    - did the piece made a valid move?
                    - is the move a capture?
                    - detects special moves: castling, promotion, en passant
                    - did the player put a piece back on it"s original square (Which is against some chess rule...)?
    if any kind of move appears to be invalid the program will get stuck in a loop from the "indicate_missing_pieces"
    function until all pieces are putted back to the original position (at the beginning of the turn)
    :returns the valid chess.Move or None in case of a wrong move
    """
    result = None
    LOG.debug('validate new player move')

    legal_squares_up = set(move.from_square for move in legal_moves)
    legal_squares_down = set(move.to_square for move in legal_moves)

    # INVALID MOVE
    if move not in legal_squares_up.union(legal_squares_down):
        LOG.info('invalid move!')
        invalid_move(game)

    # VALID MOVE
    elif move in legal_squares_up:
        # 1: Put piece back
        # 2: Piece up
        # put piece back on same square (not always valid by the chess rules :-)
        if move == game.piece_up:
            LOG.info('piece putted back')
            game.piece_up = None
            epaper_screen.update_frame(button_panel,
                                       epaper.game_player_turn(
                                           button_panel=button_panel,
                                           content=epaper.PLAYER_WAIT,
                                           partial_frame=True),
                                       important=False)
        # Piece up
        else:
            game.piece_up = move
            LOG.info('piece up: %s square_nr:%s', chess.square_name(move),
                     move)
            epaper_screen.update_frame(
                button_panel,
                epaper.game_player_turn(button_panel=button_panel,
                                        content=epaper.get_half_move_text(
                                            move, game.board),
                                        partial_frame=True))

    else:
        new_move = chess.Move(game.piece_up, move)
        LOG.info('new move: %s', new_move.uci())

        # 1: En passant?
        # 2: Castling?
        # 3: Promotion?
        # 4: normal move

        # en passant, capture or castling
        if validate_en_passant(game, new_move) or validate_caputure(
                game, new_move) or validate_castling(game, new_move):
            text = epaper.get_move_text(new_move, game.board)

        # promotion
        elif game.board.piece_type_at(
                game.piece_up) == chess.PAWN and chess.square_rank(move) in [
                    0, 7
                ] and validate_promotion(new_move):
            text = epaper.get_move_text(new_move, game.board)
            LOG.info('promotion succesfull!')

        # normal move
        else:
            LOG.info('move is valid')
            text = epaper.get_move_text(new_move, game.board)

        epaper_screen.update_frame(
            button_panel,
            epaper.game_player_turn(button_panel=button_panel,
                                    content=text,
                                    partial_frame=True))
        result = new_move

    return result