Ejemplo n.º 1
0
    def test_distance(self):
        h8 = Position(Rank.EIGHT, File.H)
        h7 = Position(Rank.SEVEN, File.H)
        h1 = Position(Rank.ONE, File.H)
        a8 = Position(Rank.EIGHT, File.A)
        a1 = Position(Rank.ONE, File.A)

        self.assertEqual(h8.dist(h7), 1)
        self.assertEqual(h8.dist(h1), 7)
        self.assertEqual(h8.dist(a8), 7)
        self.assertEqual(a8.dist(h8), 7)

        self.assertEqual(a1.dist(h8), 7)
Ejemplo n.º 2
0
    def en_passant_handler(board, *, from_pos: Position, to_pos: Position):
        board_move_func(board, from_pos=from_pos, to_pos=to_pos)

        square = board[to_pos.rank][to_pos.file]
        if to_pos == board.en_passant_pos:  # capture(delete) the pawn
            assert isinstance(square, Pawn)
            board[from_pos.rank][to_pos.file] = None

        board.en_passant_pos = None
        if hasattr(square, 'figure_type') and square.figure_type is Type.PAWN and from_pos.dist(to_pos) == 2:
            direction = square.color.forward_direction
            board.en_passant_pos = Position(to_pos.rank - direction, to_pos.file)
Ejemplo n.º 3
0
    def maybe_castle_wrapper(board, *, from_pos: Position, to_pos: Position):
        board_move_func(board, from_pos=from_pos, to_pos=to_pos)

        square = board[to_pos.rank][to_pos.file]
        if getattr(square, 'figure_type', None) is Type.KING:
            board.castling_perms[square.color] = CastlingPerm.NONE

            if from_pos.dist(to_pos) == 2:  # Castling -> Move rook
                direction = from_pos.relative_direction_towards_position(to_pos)

                old_file, new_file = ('a', 'd') if direction is Direction.LEFT else ('h', 'f')
                rank = '1' if square.color is Color.WHITE else '8'

                board.move(from_pos=P(f'{old_file}{rank}'), to_pos=P(f'{new_file}{rank}'))
Ejemplo n.º 4
0
    def get_attackers(
            self,
            start_pos: Position,
            color: Color
    ) -> Generator[Position, None, None]:
        all_directions = list(Diagonal) + list(Direction)

        positions_by_dir = self.get_positions_in_direction(start_pos, *all_directions)
        positions_by_dir['Knight'] = filter(self.is_in_bounds, Knight.possible_positions(start_pos))
        diagonals = [d.name for d in Diagonal]  # TODO(yavor): cleanup from bug fix
        directions = [d.name for d in Direction]

        for direction, positions in positions_by_dir.items():
            direction = getattr(direction, 'name', direction)  # TODO(yavor): cleanup bug fix
            for position in positions:
                if not self.is_empty(position) and self.are_enemies(color, position):
                    enemy = self[position.rank][position.file]
                    enemy_type = enemy.figure_type

                    if direction == 'Knight' and enemy_type is Type.KNIGHT:
                        yield position

                    if direction in diagonals and enemy_type in [Type.BISHOP, Type.QUEEN]:
                        yield position

                    elif direction in directions and enemy_type in [Type.ROOK, Type.QUEEN]:
                        yield position

                    elif enemy_type is Type.KING and start_pos.dist(position) == 1:
                        yield position

                    elif enemy_type is Type.PAWN:
                        direction = Direction.DOWN if enemy.color == Color.WHITE else Direction.UP
                        pawn_positions = {
                            Position(rank=start_pos.rank + direction, file=start_pos.file + Direction.RIGHT),
                            Position(rank=start_pos.rank + direction, file=start_pos.file + Direction.LEFT)
                        }
                        if position in pawn_positions:
                            yield position

                elif not self.is_empty(position) and direction != 'Knight':
                    # every other piece is blockable so we can stop going further
                    break