예제 #1
0
def test_parse_moves_fools_mate():
    parser = Parser.from_fools_mate()

    stats = get_parser_stats(parser)
    total = stats['total']
    white_pieces = stats['white_pieces']
    white_destinations = stats['white_destinations']
    col_helpers = stats['col_helpers']
    row_helpers = stats['row_helpers']
    black_pieces = stats['black_pieces']
    black_destinations = stats['black_destinations']
    upgrades = stats['upgrades']
    en_passants = stats['en_passants']
    queensides = stats['queensides']
    kingsides = stats['kingsides']

    assert 2 == total
    assert (2 * total) - kingsides - queensides == sum(
        white_destinations.values()) + sum(black_destinations.values())

    assert 0 == en_passants
    assert 0 == kingsides
    assert 0 == queensides
    assert {} == upgrades
    assert {} == col_helpers
    assert {} == row_helpers

    assert dict(Pawn=2) == white_pieces
    assert 1 == white_destinations[Point(3, 6)]
    assert 2 == len(white_destinations)

    assert dict(Pawn=1, Queen=1) == black_pieces
    assert 1 == black_destinations[Point(4, 4)]
    assert 2 == len(black_destinations)
예제 #2
0
def test_parse_mecking_h_donner_1971():
    parser = Parser.from_pgn(get_input.get('mecking_h_donner_1971.pgn'))

    stats = get_parser_stats(parser)
    total = stats['total']
    white_pieces = stats['white_pieces']
    white_destinations = stats['white_destinations']
    col_helpers = stats['col_helpers']
    row_helpers = stats['row_helpers']
    black_pieces = stats['black_pieces']
    black_destinations = stats['black_destinations']
    upgrades = stats['upgrades']
    en_passants = stats['en_passants']
    queensides = stats['queensides']
    kingsides = stats['kingsides']

    assert len(parser.moves) == total
    assert (2 * total) - kingsides - queensides - 1 == sum(
        white_destinations.values()) + sum(black_destinations.values())

    assert 0 == en_passants
    assert 2 == kingsides
    assert 0 == queensides
    assert {} == upgrades
    assert dict(F=1) == col_helpers
    assert {} == row_helpers

    assert dict(Pawn=8, Rook=1, Knight=3, Bishop=2, Queen=2,
                King=1) == white_pieces
    assert 2 == white_destinations[Point(4, 2)]
    assert 15 == len(white_destinations)

    assert dict(Pawn=6, Knight=3, Bishop=5, Queen=1, King=1) == black_pieces
    assert 3 == black_destinations[Point(4, 2)]
    assert 11 == len(black_destinations)
예제 #3
0
    def _get_all_valid_moves(self) -> tp.List[Point]:
        moves = []

        x = self.pos.x
        y = self.pos.y

        for row, col in product(range(-1, 2), range(-1, 2)):
            move = Point(x + row, y + col)
            if self.is_valid_move(move):
                moves.append(move)

        # Check potential castle moves
        if self._is_first_move:
            row = 0 if self.color == Color.White else 7

            move_left = Point(row, 3)
            move_right = Point(row, 6)

            if self.is_valid_move(move_left):
                moves.append(move_left)

            if self.is_valid_move(move_right):
                moves.append(move_right)

        return moves
예제 #4
0
    def get_input(self, msg: str) -> Point:
        '''Prompts for input from the user. Parses input'''
        piece_location, move_to = '', ''

        while True:
            user_input = input(msg)

            if user_input in ('Quit', 'quit', 'q', 'Q'):
                raise UserQuitMidGameException

            if user_input == 'interact':
                breakpoint()

            for delim in self.INPUT_DELIMS:
                if delim in user_input:
                    try:
                        piece_location, move_to = user_input.split(delim)
                    except ValueError:
                        print(self.INVALID_INPUT_MSG)
                        continue

            if not piece_location or not move_to:
                print(self.INVALID_INPUT_MSG)
                continue

            piece_location = Point.from_str(piece_location)
            move_to = Point.from_str(move_to)

            if not self.validate_input(piece_location, move_to):
                continue
            break

        return piece_location, move_to
예제 #5
0
def test_equals_point():
    p = Point(1, 4)
    q = Point(2, 3)
    assert p != q

    q = Point(1, 4)
    assert p == q
예제 #6
0
def test_can_not_move_vertically_to_team_piece():
    b = Board()
    p = PieceTester(Color.White, b, Point(4, 4))

    assert not p._can_move_vertically_to(1)
    b.perform_move(b[0, 0], Point(5, 4))
    assert not p._can_move_vertically_to(5)
예제 #7
0
def test_can_move_vertically_to_enemy_piece():
    b = Board()
    p = PieceTester(Color.White, b, Point(4, 4))

    assert p._can_move_vertically_to(6)
    b.perform_move(b[7, 7], Point(2, 4))
    assert p._can_move_vertically_to(2)
예제 #8
0
def perform_move():
    piece = PieceTester(Color.White, None, Point(1, 1))
    en_passant = Ref(Point(1, 1))
    piece.perform_move(Point(3, 4), en_passant)

    assert not piece.is_first_move
    assert p.pos == Point(3, 4)
    assert en_passant() == Point()
예제 #9
0
def test_parse_length8848_5():

    parser = Parser.from_pgn(get_input.get('length8848.5.pgn'))

    stats = get_parser_stats(parser)
    total = stats['total']
    white_pieces = stats['white_pieces']
    white_destinations = stats['white_destinations']
    col_helpers = stats['col_helpers']
    row_helpers = stats['row_helpers']
    black_pieces = stats['black_pieces']
    black_destinations = stats['black_destinations']
    upgrades = stats['upgrades']
    en_passants = stats['en_passants']
    queensides = stats['queensides']
    kingsides = stats['kingsides']

    white_sum = sum(white_destinations.values())
    black_sum = sum(black_destinations.values())

    assert 8849 == total
    assert 1 == white_sum - black_sum
    assert (2 * total) - kingsides - queensides - 1 == white_sum + black_sum
    assert 0 == en_passants
    assert 0 == kingsides
    assert 0 == queensides
    assert dict(Queen=16) == upgrades

    assert dict(A=593, B=762, C=885, D=914, E=750, F=803, G=781,
                H=536) == col_helpers
    assert {
        1: 173,
        2: 158,
        3: 198,
        4: 183,
        5: 142,
        6: 126,
        7: 95,
        8: 81
    } == row_helpers

    assert dict(Pawn=48,
                Rook=962,
                Knight=1487,
                Bishop=716,
                Queen=4818,
                King=818) == white_pieces
    assert 144 == white_destinations[Point(3, 2)]
    assert 64 == len(white_destinations)

    assert dict(Pawn=48,
                Rook=1269,
                Knight=531,
                Bishop=701,
                Queen=5146,
                King=1153) == black_pieces
    assert 121 == black_destinations[Point(3, 2)]
    assert 64 == len(black_destinations)
예제 #10
0
def test_can_move_horizontally_to_enemy_piece():
    b = Board()
    p = PieceTester(Color.White, b, Point(4, 4))

    b.perform_move(b[6, 2], Point(4, 2))
    assert p._can_move_horizontally_to(2)

    b.perform_move(b[7, 7], Point(4, 7))
    assert p._can_move_horizontally_to(7)
예제 #11
0
def test_can_not_move_horizontally_to_team_piece():
    b = Board()
    p = PieceTester(Color.White, b, Point(4, 4))

    b.perform_move(b[1, 1], Point(4, 1))
    assert not p._can_move_horizontally_to(1)

    b.perform_move(b[1, 7], Point(4, 7))
    assert not p._can_move_horizontally_to(7)
예제 #12
0
    def perform_move(self, to: Point, en_passant: Ref[Point]):
        piece_x = self.pos.x
        to_x = to.x
        to_y = to.y

        # If double-step, any existing en passant was effectively ignored and a new en passant is in effect
        new_en_passant = Point()
        if abs(piece_x - to_x) == 2:
            direction = -1 if piece_x > to_x else 1

            new_en_passant = Point(piece_x + direction, to_y)

        super().perform_move(to, en_passant)
        en_passant.update(new_en_passant)
예제 #13
0
    def from_board(cls, board: 'Board') -> 'Screenshot':

        moves: tp.List[TeamMovePair] = []
        total_pieces = 0
        pawn_locations: tp.List[Point] = []

        for row, col in product(range(8), range(8)):
            piece: Piece = board[row, col]

            if piece is not None:

                valid_moves = piece.get_all_valid_moves()

                for move in valid_moves:
                    moves.append(
                        TeamMovePair(MovePair(Point(row, col), move),
                                     piece.color))

                total_pieces += 1

                if piece.piece_type == PieceType.Pawn:
                    pawn_locations.append(piece.pos)

        return cls(moves, board.white_score, board.black_score, pawn_locations,
                   total_pieces)
예제 #14
0
 def _get_all_valid_moves(self) -> tp.List[Point]:
     moves = []
     for row, col in product(range(8), range(8)):
         move = Point(row, col)
         if self.is_valid_move(move):
             moves.append(move)
     return moves
예제 #15
0
    def _get_all_valid_moves(self) -> tp.List[Point]:
        moves = []

        x = self.pos.x
        y = self.pos.y

        for i in range(8):
            v_move = Point(i, y)
            h_move = Point(x, i)

            if self.is_valid_move(v_move):
                moves.append(v_move)
            if self.is_valid_move(h_move):
                moves.append(h_move)

        return moves
예제 #16
0
    def _get_all_valid_moves(self) -> tp.List[Point]:
        moves = []
        x = self.pos.x
        y = self.pos.y
        direction = 1 if self.color == Color.White else -1

        possible_moves = [
            Point(x + direction, y),
            Point(x + 2 * direction, y),
            Point(x + direction, y - 1),
            Point(x + direction, y + 1)
        ]

        for move in possible_moves:
            if self.is_valid_move(move):
                moves.append(move)
        return moves
예제 #17
0
def test_can_move_horizontally_to_empty_space():
    b = Board()
    p = PieceTester(Color.White, b, Point(4, 4))

    assert p._can_move_horizontally_to(0)

    for i in range(1, 8):
        if i == 4:
            continue
        assert p._can_move_horizontally_to(i)
예제 #18
0
def test_is_valid():
    assert Point(0, 0).is_valid()
    assert Point(4, 4).is_valid()
    assert Point(7, 7).is_valid()

    assert not Point(-1, 0).is_valid()
    assert not Point(0, -1).is_valid()
    assert not Point(0, 8).is_valid()
    assert not Point(8, 0).is_valid()
예제 #19
0
    def perform_move(self, to: Point, en_passant: Ref[Point]):
        '''
        Updates piece's internal state to reflect move. Do before changing actual board!

        Callers must remember to reset en_passant
        '''
        if self._is_first_move:
            self._is_first_move = False
        self._pos = to

        en_passant.update(Point())
예제 #20
0
    def _gen_board(self):
        _board = np.full((8, 8), fill_value=None)

        for row, col in product(range(8), range(8)):
            color = Color.White if row <= 1 else Color.Black

            piece = None

            if row == 0 or row == 7:
                if col == 0 or col == 7:
                    piece = Rook(color, self, Point(row, col))
                elif col == 1 or col == 6:
                    piece = Knight(color, self, Point(row, col))
                elif col == 2 or col == 5:
                    piece = Bishop(color, self, Point(row, col))
                elif col == 3:
                    piece = Queen(color, self, Point(row, col))
                else:
                    piece = King(color, self, Point(row, col))
            elif row == 1 or row == 6:
                piece = Pawn(color, self, Point(row, col))

            if piece is not None:
                if piece.piece_type == PieceType.King:
                    self._kings[color] = piece
                else:
                    self._pieces[color][piece.piece_type].add(piece)

                _board[row, col] = piece

        return sf.Frame.from_records(_board, columns=tuple('ABCDEFGH'))
예제 #21
0
def can_move_vertically_to_empty_space():
    b = Board()
    p = PieceTester(Color.White, b, Point(4, 4))
    b.remove_piece((0, 4))
    b.remove_piece((1, 4))
    b.remove_piece((6, 4))
    b.remove_piece((7, 4))

    assert p._can_move_vertically_to(0)
    for i in range(1, 8):
        if i == 4:
            continue

        assert p._can_move_vertically_to(i)
예제 #22
0
def test_parse_fischer_spassky_1992():
    parser = Parser.from_pgn(get_input.get('fischer_spassky_1992.pgn'))

    stats = get_parser_stats(parser)
    total = stats['total']
    white_pieces = stats['white_pieces']
    white_destinations = stats['white_destinations']
    col_helpers = stats['col_helpers']
    row_helpers = stats['row_helpers']
    black_pieces = stats['black_pieces']
    black_destinations = stats['black_destinations']
    upgrades = stats['upgrades']
    en_passants = stats['en_passants']
    queensides = stats['queensides']
    kingsides = stats['kingsides']

    assert len(parser.moves) == total
    assert (2 * total) - kingsides - queensides - 1 == sum(
        white_destinations.values()) + sum(black_destinations.values())

    assert 0 == en_passants
    assert 2 == kingsides
    assert 0 == queensides
    assert {} == upgrades
    assert dict(A=1, B=2) == col_helpers
    assert {} == row_helpers

    assert dict(Pawn=14, Rook=7, Knight=7, Bishop=8, Queen=3,
                King=4) == white_pieces

    assert 3 == white_destinations[Point(0, 4)]
    assert 28 == len(white_destinations)

    assert dict(Pawn=12, Rook=3, Knight=12, Bishop=5, Queen=3,
                King=7) == black_pieces
    assert 3 == black_destinations[Point(4, 1)]
    assert 29 == len(black_destinations)
예제 #23
0
def test_parse_raphael_hiaves_2006():
    parser = Parser.from_pgn(get_input.get('raphael_hiaves_2006.pgn'))

    stats = get_parser_stats(parser)
    total = stats['total']
    white_pieces = stats['white_pieces']
    white_destinations = stats['white_destinations']
    col_helpers = stats['col_helpers']
    row_helpers = stats['row_helpers']
    black_pieces = stats['black_pieces']
    black_destinations = stats['black_destinations']
    upgrades = stats['upgrades']
    en_passants = stats['en_passants']
    queensides = stats['queensides']
    kingsides = stats['kingsides']

    assert len(parser.moves) == total
    assert (2 * total) - kingsides - queensides == sum(
        white_destinations.values()) + sum(black_destinations.values())

    assert 1 == en_passants
    assert 2 == kingsides
    assert 0 == queensides
    assert dict(Queen=1) == upgrades
    assert dict(A=2, C=1, F=2) == col_helpers
    assert {} == row_helpers

    assert dict(Pawn=6, Rook=3, Knight=5, Bishop=2, Queen=2,
                King=2) == white_pieces
    assert 3 == white_destinations[Point(4, 3)]
    assert 15 == len(white_destinations)

    assert dict(Pawn=10, Rook=2, Knight=3, Bishop=3, Queen=1,
                King=1) == black_pieces
    assert 4 == black_destinations[Point(4, 3)]
    assert 14 == len(black_destinations)
예제 #24
0
def test_parse_lucky_bardwick_1995():
    parser = Parser.from_pgn(get_input.get('lucky_bardwick_1995.pgn'))

    stats = get_parser_stats(parser)
    total = stats['total']
    white_pieces = stats['white_pieces']
    white_destinations = stats['white_destinations']
    col_helpers = stats['col_helpers']
    row_helpers = stats['row_helpers']
    black_pieces = stats['black_pieces']
    black_destinations = stats['black_destinations']
    upgrades = stats['upgrades']
    en_passants = stats['en_passants']
    queensides = stats['queensides']
    kingsides = stats['kingsides']

    assert len(parser.moves) == total
    assert (2 * total) - kingsides - queensides == sum(
        white_destinations.values()) + sum(black_destinations.values())

    assert 0 == en_passants
    assert 0 == kingsides
    assert 1 == queensides
    assert {} == upgrades
    assert dict(D=1, F=1) == col_helpers
    assert {} == row_helpers

    assert dict(Pawn=20, Rook=55, Knight=30, Bishop=3, Queen=8,
                King=27) == white_pieces
    assert 10 == white_destinations[Point(4, 4)]
    assert 49 == len(white_destinations)

    assert dict(Pawn=12, Rook=60, Knight=15, Bishop=8, Queen=3,
                King=45) == black_pieces
    assert 8 == black_destinations[Point(6, 3)]
    assert 51 == len(black_destinations)
예제 #25
0
    def __init__(self):
        self._enpassant_location: Ref[Point] = Ref(Point())

        self._kings: tp.Dict[Color, King] = {}

        self._pieces: tp.Dict[Color, tp.Dict[PieceType, tp.Set[Piece]]] = {}
        for color in Color:
            piece_collection: tp.Dict[PieceType, tp.Set[Piece]] = {}
            for piece_type in (pt for pt in PieceType if pt != PieceType.King):
                piece_collection[piece_type] = set()
            self._pieces[color] = piece_collection

        self._board: sf.Frame = self._gen_board()

        self.white_score: float = 0.0
        self.black_score: float = 0.0
예제 #26
0
    def parse_points_from_move(
            self,
            move: Move) -> tp.Tuple[Piece, Point, tp.Optional[PieceType]]:

        if move.piece == PieceType.King:
            king = self.get_king(move.color)

            if move.castle in (Castle.Queenside, Castle.Kingside):
                direction = 2 if Castle.Kingside else -2
                return king, Point(king.pos.x, king.pos.y + direction), None

            return king, move.destination, None

        else:
            target = self._find_target_piece(move)
            return target, move.destination, move.upgrade
예제 #27
0
    def _can_move_horizontally_to(self, to: int) -> bool:
        if self._check_illegal_move(Point(self._pos.x, to)):
            return False

        me_x = self._pos.x
        me_y = self._pos.y
        direction = 1 if to > me_y else -1  # 1 = right, -1 = left
        col = me_y + direction  # Move one space away as starting square

        # Keep advancing along empty spaces until end is hit
        while col != to:
            if self._board[me_x, col] is not None:
                return False
            col += direction

        return True
예제 #28
0
    def _can_move_vertically_to(self, to: int) -> bool:
        if self._check_illegal_move(Point(to, self._pos.y)):
            return False

        me_x = self._pos.x
        me_y = self._pos.y
        direction = 1 if to > me_x else -1  # 1 = down, -1 = up
        row = me_x + direction  # Move one space away as starting square

        # Keep advancing along empty spaces until end is hit
        while row != to:
            if self._board[row, me_y] is not None:
                return False
            row += direction

        return True
예제 #29
0
    def _check_illegal_move(self,
                            to: Point,
                            *,
                            ignore_color: bool = False) -> bool:
        # Cannot move outisde board or to same spot
        if not to.is_valid() or self._pos == to:
            return True

        if ignore_color:
            return False

        # Cannot move to teammate spot
        actual_piece = self._board[to]
        if actual_piece is not None and actual_piece.color == self.color:
            return True

        return False
예제 #30
0
    def _get_all_valid_moves(self) -> tp.List[Point]:
        moves = []
        x = self.pos.x
        y = self.pos.y

        possible_moves = [
            Point(x + 1, y + 2),
            Point(x + 1, y - 2),
            Point(x - 1, y + 2),
            Point(x - 1, y - 2),
            Point(x + 2, y + 1),
            Point(x + 2, y - 1),
            Point(x - 2, y + 1),
            Point(x - 2, y - 1)
        ]

        for move in possible_moves:
            if self.is_valid_move(move):
                moves.append(move)
        return moves