def test_parse_move_path(tui): assert tui._parse_move_path("a8", "b2") == MovePath(Position(x=0, y=7), Position(x=1, y=1)) assert tui._parse_move_path("a8", "b8") == MovePath(Position(x=0, y=7), Position(x=1, y=7)) try: tui._parse_move_path("a9", "b2") except MovePathParseError: ... else: assert False try: tui._parse_move_path("a9", "b9") except MovePathParseError: ... else: assert False try: tui._parse_move_path("u8", "b2") except MovePathParseError: ... else: assert False try: tui._parse_move_path("u8", "q2") except MovePathParseError: ... else: assert False
def test_are_enemies_should_be_negative(self): piece1_pos = Position(Rank.ONE, File.A) piece2_pos = Position(Rank.ONE, File.B) piece1_mock = MagicMock() piece2_mock = MagicMock() self.board[piece1_pos.rank][piece1_pos.file] = piece1_mock self.board[piece2_pos.rank][piece2_pos.file] = piece2_mock with self.subTest('Positional arguments are both Position instances'): with self.subTest('Both are white'): piece1_mock.color = piece2_mock.color = Color.WHITE self.assertFalse(self.board.are_enemies( piece1_pos, piece2_pos)) with self.subTest('Both are black'): piece1_mock.color = piece2_mock.color = Color.BLACK self.assertFalse(self.board.are_enemies( piece1_pos, piece2_pos)) with self.subTest('Type of first positional argument is Color'): with self.subTest('Both are white'): piece1_mock.color = Color.WHITE self.assertFalse( self.board.are_enemies(Color.WHITE, piece1_pos)) with self.subTest('Both are black'): piece1_mock.color = Color.BLACK self.assertFalse( self.board.are_enemies(Color.BLACK, piece1_pos))
def test_promotion_callback_should_be_called(self): board = Board.from_strings([ # bcdefgh '........', # 8 '.P......', # 7 '........', # 6 '........', # 5 '........', # 4 '........', # 3 '.p......', # 2 '........' # 1 ]) board.promotion_cb = unittest.mock.Mock() mock_piece = board.promotion_cb.return_value with self.subTest('white'): f, t = Position(Rank.SEVEN, File.B), Position(Rank.EIGHT, File.B) board.move(from_pos=f, to_pos=t) board.promotion_cb.assert_called_once() mock_piece.assert_called_once_with(Color.WHITE) board.promotion_cb.reset_mock() mock_piece = board.promotion_cb.return_value with self.subTest('black'): f, t = Position(Rank.TWO, File.B), Position(Rank.ONE, File.B) board.move(from_pos=f, to_pos=t) board.promotion_cb.assert_called_once() mock_piece.assert_called_once_with(Color.BLACK)
def target_board(positions): """ >>> positions = target_board([ ... # bcdefgh ... '........', # 8 ... '........', # 7 ... '........', # 6 ... 'X...X...', # 5 ... '.x.x....', # 4 ... '..T.....', # 3 ... '.x.x....', # 2 ... 'X...X...' # 1 ... ]); ('C3' in str(positions.keys()), all(p in str(positions.values()) for p in {"A1", "D2", "B2", "A5", "E1", "B4", "D4", "E5"})) (True, True) The example above is so contrived because it needs to work around the way doctest verifies The output will be the following dict - {C3: {A1, A5, D2, E1, B4, B2, E5, D4}} T - target - maps to a key of the dict of type chess.position.Position x - expected move == X """ wanted_moves = set() target = None for row, cur_rank in zip(positions, reversed(Rank)): for col, cur_file in zip(row, File): if col == 'T': target = Position(cur_rank, cur_file) elif col in ['x', 'X']: wanted_moves.add(Position(cur_rank, cur_file)) return {target: wanted_moves}
def _get_position_in_single_direction( self, start_pos: Position, direction: Union[Direction, Diagonal] ) -> Generator[Position, None, None]: rank, file = start_pos.rank, start_pos.file delta_rank = delta_file = None if direction in [Direction.UP, Direction.DOWN]: delta_rank, delta_file = direction, 0 if direction in [Direction.RIGHT, Direction.LEFT]: delta_rank, delta_file = 0, direction if isinstance(direction, Diagonal): delta_rank, delta_file = direction.composites() curr_pos = Position(rank + delta_rank, file + delta_file) while self.is_in_bounds(curr_pos): yield Position(curr_pos.rank, curr_pos.file) curr_pos.rank += delta_rank curr_pos.file += delta_file
def test_vertical_move_rule_is_valid_path(): rule = VerticalMoveRule(7) assert rule.is_valid_path(Position(x=0, y=0), Position(x=0, y=4)) assert rule.is_valid_path(Position(x=3, y=2), Position(x=3, y=0)) assert not rule.is_valid_path(Position(x=0, y=0), Position(x=2, y=4)) assert not rule.is_valid_path(Position(x=0, y=0), Position( x=0, y=0)) # not move assert not rule.is_valid_path(Position(x=0, y=0), Position(x=0, y=10)) # length
def get_possible_positions(self, position): rank, file = position.rank, position.file forward = Direction.UP if self.is_white else Direction.DOWN return { 'one_forward': Position(rank + forward, file), 'two_forward': Position(rank + 2 * forward, file), 'attack_right': Position(rank + forward, file + Direction.RIGHT), 'attack_left': Position(rank + forward, file + Direction.LEFT), }
def test_horizontal_move_rule_is_valid_path(): rule = HorizontalMoveRule(7) # is_valid_path assert rule.is_valid_path(Position(x=0, y=0), Position(x=2, y=0)) assert rule.is_valid_path(Position(x=3, y=3), Position(x=0, y=3)) assert not rule.is_valid_path(Position(x=0, y=0), Position(x=2, y=1)) assert not rule.is_valid_path(Position(x=0, y=0), Position( x=0, y=0)) # not move assert not rule.is_valid_path(Position(x=0, y=0), Position(x=10, y=0)) # length
def test_hash_values(self): h8_1 = Position(Rank.EIGHT, File.H) h8_2 = Position(Rank.EIGHT, File.H) a1_1 = Position(Rank.ONE, File.A) a1_2 = Position(Rank.ONE, File.A) self.assertEqual(h8_1, h8_2) self.assertEqual(a1_1, a1_2) self.assertEqual(hash(h8_1), hash(h8_2)) self.assertEqual(hash(a1_1), hash(a1_2))
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)
def test_create_vertical_roadmap(board): assert [ cell.pos for cell in board.create_vertical_roadmap( Position(x=5, y=3), Position(x=5, y=6)) ] == [Position(x=5, y=4), Position(x=5, y=5), Position(x=5, y=6)] assert [ cell.pos for cell in board.create_vertical_roadmap( Position(x=5, y=3), Position(x=5, y=0)) ] == [Position(x=5, y=2), Position(x=5, y=1), Position(x=5, y=0)]
def test_filter_by_valid_positions(): assert filter_by_valid_positions([ Position(x=1, y=1), Position(x=-1, y=2), Position(x=-1, y=-1), Position(x=3, y=7), Position(x=5, y=10), Position(x=20, y=1), Position(x=20, y=10) ]) == [Position(x=1, y=1), Position(x=3, y=7)]
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}'))
def test_create_horizontal_roadmap(board): assert [ cell.pos for cell in board.create_horizontal_roadmap( Position(x=5, y=3), Position(x=3, y=3)) ] == [Position(x=4, y=3), Position(x=3, y=3)] assert [ cell.pos for cell in board.create_horizontal_roadmap( Position(x=3, y=3), Position(x=6, y=3)) ] == [Position(x=4, y=3), Position(x=5, y=3), Position(x=6, y=3)]
def generate_moves(self, board, king_pos: Position = None): normal_moves = seq(self.possible_positions(king_pos))\ .filter(board.is_in_bounds)\ .filter(lambda p: self.__can_step(board, king_pos, p))\ .filter(lambda p: not self.is_in_check(board, p, ignore=[king_pos]))\ .list() castling_moves = [] if board.is_able_to_castle(self.color, CastlingPerm.QUEEN_SIDE): castling_moves.append(Position(king_pos.rank, File.C)) if board.is_able_to_castle(self.color, CastlingPerm.KING_SIDE): castling_moves.append(Position(king_pos.rank, File.G)) return seq(normal_moves, castling_moves).flatten().to_list()
def test_when_king_is_in_check_he_should_be_aware_of_his_own_position( self): test_table = [ *self.all_board_rotations_of({ 'comment': ''' when a possible position is evaluated, the code should not consider it's old position as a blocker of an attacker In this situation: v a b c d e f g h 1 . Q . k . . . . 1 F1(marked with `v`) should not be a valid move ''', 'board': Board.from_strings([ # bcdefgh 'R..k....', # 8 '........', # 7 '........', # 6 '........', # 5 '........', # 4 '........', # 3 '........', # 2 'r..K....' # 1 ]), 'want': { 'white': { 'assert': self.assertNotIn, Position(Rank.ONE, File.D): Position(Rank.ONE, File.E), }, 'black': { 'assert': self.assertNotIn, Position(Rank.EIGHT, File.D): Position( Rank.EIGHT, File.E), }, }, 'name': '', }), ] for test_case in test_table: self.runMoveGenerationTest(test_case)
def test_is_at_starting_rank_correctness(self): with self.subTest('white'): wp = Pawn(Color.WHITE) for file in File: self.assertTrue(wp.is_at_starting_pos(Position(Rank.TWO, file))) self.assertFalse( wp.is_at_starting_pos(Position(Rank.SEVEN, File.G))) with self.subTest('black'): bp = Pawn(Color.BLACK) for file in File: self.assertTrue( bp.is_at_starting_pos(Position(Rank.SEVEN, file))) self.assertFalse(bp.is_at_starting_pos(Position(Rank.TWO, File.G)))
def aiMove(self): self.setWindowTitle("Chess: AI") # parse move = "" for p in self.lastMove: move += chr(p['x'] + ord('a')) + str(8 - p['y']) print(f"player move: {move}") self.ai.hist.append(self.ai.hist[-1].move( (self.ai.parse(move[:2]), self.ai.parse(move[2:])))) self.ai.print_pos(self.ai.hist[-1].rotate()) # search start = time.time() for _, move, _ in self.ai.searcher.search(self.ai.hist[-1], self.ai.hist): if time.time() - start > self.ai.time: break # move self.ai.hist.append(self.ai.hist[-1].move(move)) move = self.ai.render(119 - move[0]) + self.ai.render(119 - move[1]) print(f"ai move: {move}") x1, y1, x2, y2 = ord(move[0]) - ord('a'), 8 - int(move[1]), ord( move[2]) - ord('a'), 8 - int(move[3]) self.ai.print_pos(self.ai.hist[-1]) if self.chessBoard[y1][x1].getType() == "Pawn": piece = self.chessBoard[y1][x1] _, promotion = piece.move(Position(x2, y2), self.chessBoard) if promotion: self.chessBoard[y2][x2] = Queen(piece.pos, piece.team) elif self.chessBoard[y1][x1].getType() == "King": self.chessBoard[y1][x1].move(Position(x2, y2), self.chessBoard, self.blackCheckBoard) else: self.chessBoard[y1][x1].move(Position(x2, y2), self.chessBoard) # refresh CheckBoard self.whiteCheckBoard, self.whiteCheck = fillCheckBoard( self.chessBoard, Team.WHITE) self.blackCheckBoard, self.BlackCheck = fillCheckBoard( self.chessBoard, Team.BLACK) self.turn = Team.WHITE
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
def test_last_rank_should_be_with_changed_piece_type(self): board = Board.from_strings([ # bcdefgh '........', # 8 '.P......', # 7 '........', # 6 '........', # 5 '........', # 4 '........', # 3 '........', # 2 '........' # 1 ]) f, t = Position(Rank.SEVEN, File.B), Position(Rank.EIGHT, File.B) board.promotion_cb = unittest.mock.Mock() piece_cls_mock = board.promotion_cb.return_value board.move(from_pos=f, to_pos=t) self.assertEqual(board[t.rank][t.file], piece_cls_mock.return_value)
def test_are_enemies_should_be_affirmative(self): with self.subTest('Positional arguments are both Position instances'): piece1_pos = Position(Rank.ONE, File.A) piece2_pos = Position(Rank.ONE, File.B) self.board[piece1_pos.rank][piece1_pos.file] = MagicMock( color=Color.BLACK) self.board[piece2_pos.rank][piece2_pos.file] = MagicMock( color=Color.WHITE) self.assertTrue(self.board.are_enemies(piece1_pos, piece2_pos)) self.assertTrue(self.board.are_enemies(piece2_pos, piece1_pos)) with self.subTest('Type of first positional argument is Color'): piece_pos = Position(Rank.ONE, File.A) self.board[piece_pos.rank][piece_pos.file] = MagicMock( color=Color.BLACK) self.assertTrue(self.board.are_enemies(Color.WHITE, piece_pos))
def setUp(self): self.b=[bR,bN,bB,bQ,bK,bB,bN,bR, #00..07 bP,bP,bP,bP,bP,bP,bP,bP, #08..15 xx,xx,xx,xx,xx,xx,xx,xx, #16..23 xx,xx,xx,xx,xx,xx,xx,xx, #24..31 xx,xx,xx,xx,wP,xx,xx,xx, #32..39 xx,xx,xx,xx,xx,xx,xx,xx, #40..47 wP,wP,wP,wP,xx,wP,wP,wP, #48..55 wR,wN,wB,wQ,wK,wB,wN,wR #56..63 ] self.pos=Position(self.b,True,True,True,True,None,BLACK,0,1)
def _cursor_to_position(self, coordinates=None): # WARN: bool((0, 0)) == False, # therefore coordinates or self.cursor == self.cursor y, x = coordinates or self.cursor col, row = (x - self.top_x) // self.step_x, (y - self.top_y) // self.step_y rank = chr(7 - row + ord('0') + 1) file = chr(col + ord('a')) return Position.from_str(file + rank)
def possible_positions(cls, position): rank, file = position.rank, position.file return [ Position(rank + cls._two_up, file + cls._one_right), Position(rank + cls._one_up, file + cls._two_right), Position(rank + cls._one_down, file + cls._two_right), Position(rank + cls._two_down, file + cls._one_right), Position(rank + cls._two_down, file + cls._one_left), Position(rank + cls._one_down, file + cls._two_left), Position(rank + cls._one_up, file + cls._two_left), Position(rank + cls._two_up, file + cls._one_left), ]
def from_fen(cls, fen: str): fen_board, active_side, castling, en_passant, _, _ = fen.split() board = cls() board.player = Color.WHITE if active_side.lower() == 'w' else Color.BLACK board.enemy = Color.BLACK if active_side.lower() == 'w' else Color.WHITE for rank, row in zip(reversed(Rank), fen_board.split('/')): col_i = 0 for char in row: if char.upper() in cls.fen_lookup_table: piece_class = cls.fen_lookup_table[char.upper()] color = Color.WHITE if char.isupper() else Color.BLACK p_file = File.from_str(chr(col_i + ord('a'))) piece = piece_class(color) board[rank][p_file] = piece if char.upper() == 'K': board.kings[color] = Position(rank, p_file) col_i += 1 else: count_empty = int(char) col_i += count_empty board.castling_perms[Color.WHITE] = CastlingPerm.NONE board.castling_perms[Color.BLACK] = CastlingPerm.NONE board.castling_perms[Color.WHITE] |= int('K' in castling) << int(math.log2(CastlingPerm.KING_SIDE)) board.castling_perms[Color.WHITE] |= int('Q' in castling) << int(math.log2(CastlingPerm.QUEEN_SIDE)) board.castling_perms[Color.BLACK] |= int('k' in castling) << int(math.log2(CastlingPerm.KING_SIDE)) board.castling_perms[Color.BLACK] |= int('q' in castling) << int(math.log2(CastlingPerm.QUEEN_SIDE)) if en_passant != '-': board.en_passant_pos = Position.from_str(en_passant) return board
def standard_configuration(cls): board = cls() padding = 2 main_rank = seq(Rook, Knight, Bishop, Queen, King, Bishop, Knight, Rook) board[Rank.ONE][padding:-padding] = main_rank.map(lambda kls: kls(Color.WHITE)).list() board[Rank.EIGHT][padding:-padding] = main_rank.map(lambda kls: kls(Color.BLACK)).list() board[Rank.TWO][padding:-padding] = main_rank.map(lambda _: Pawn(Color.WHITE)).list() board[Rank.SEVEN][padding:-padding] = main_rank.map(lambda _: Pawn(Color.BLACK)).list() board.kings = { Color.BLACK: Position(Rank.EIGHT, File.E), Color.WHITE: Position(Rank.ONE, File.E), } board.player, board.enemy = Color.WHITE, Color.BLACK board.castling_perms[Color.WHITE] = CastlingPerm.ALL board.castling_perms[Color.BLACK] = CastlingPerm.ALL return board
def test_en_passant_square_is_set_on_the_board_object(self): board = Board.from_strings([ # bcdefgh '........', # 8 '.p......', # 7 '........', # 6 '........', # 5 '........', # 4 '........', # 3 '.P......', # 2 '........' # 1 ]) with self.subTest('white'): en_passant_want = Position(Rank.THREE, File.B) f, t = Position(Rank.TWO, File.B), Position(Rank.FOUR, File.B) board.move(from_pos=f, to_pos=t) self.assertEqual(board.en_passant_pos, en_passant_want) with self.subTest('black'): en_passant_want = Position(Rank.SIX, File.B) f, t = Position(Rank.SEVEN, File.B), Position(Rank.FIVE, File.B) board.move(from_pos=f, to_pos=t) self.assertEqual(board.en_passant_pos, en_passant_want)
def generate_moves(self, board, knight_position: Position = None): knight_position = knight_position or Position(self.rank, self.file) possible_positions = self.possible_positions(knight_position) moves = [] for position in possible_positions: if (board.is_in_bounds(position) and (board.is_empty(position) or board.are_enemies(knight_position, position))): moves.append(position) return moves
def test_is_free_roadmap(board): roadmap = board.create_horizontal_roadmap(Position(x=5, y=3), Position(x=3, y=3)) assert board.is_free_roadmap(roadmap[:-1]) board = Board() board[3][4].put_piece(Knight(Color.BLACK, Position(x=4, y=3))) roadmap = board.create_horizontal_roadmap(Position(x=5, y=3), Position(x=3, y=3)) assert not board.is_free_roadmap(roadmap[:-1]) board = Board() board[3][3].put_piece(Knight(Color.BLACK, Position(x=3, y=3))) roadmap = board.create_horizontal_roadmap(Position(x=5, y=3), Position(x=3, y=3)) assert board.is_free_roadmap(roadmap[:-1])
def rotate_position(position: Position, times=1): new_pos = deepcopy(position) for _ in range(times): rank, file = new_pos.coordinates new_rank, new_file = 7 - rank, file new_rank, new_file = new_file, new_rank # new_rank, new_file = 7 - file, rank # new_rank = 7 - new_rank new_rank, new_file = chr(7 - new_rank + ord('1')), chr(new_file + ord('a')) new_pos = Position.from_str(new_file + new_rank) return new_pos
def test_king_should_not_be_able_to_step_on_attacked_square(self): test_table = [ *self.all_board_rotations_of({ 'name': 'should_not_be_able_to_step_on_attacked_squares', 'board': Board.from_strings([ # bcdefgh '...k....', # 8 'R.......', # 7 '........', # 6 '........', # 5 '........', # 4 '........', # 3 'r.......', # 2 '...K....' # 1 ]), 'want': { 'white': { Position(Rank.ONE, File.D): { Position(Rank.TWO, File.C), Position(Rank.TWO, File.D), Position(Rank.TWO, File.E), }, 'assert': lambda want, actual, **_: [self.assertNotIn(p, actual) for p in want] }, 'black': { Position(Rank.EIGHT, File.D): { Position(Rank.SEVEN, File.C), Position(Rank.SEVEN, File.D), Position(Rank.SEVEN, File.E), }, 'assert': lambda want, actual, **_: [self.assertNotIn(p, actual) for p in want] }, } }) ] for test_case in test_table: self.runMoveGenerationTest(test_case)
class Test_Position_PosInicial(unittest.TestCase): #class Test_Position_PosInicial(dummyTest): def setUp(self): self.pos=Position() self.b=[bR,bN,bB,bQ,bK,bB,bN,bR, #00..07 bP,bP,bP,bP,bP,bP,bP,bP, #08..15 xx,xx,xx,xx,xx,xx,xx,xx, #16..23 xx,xx,xx,xx,xx,xx,xx,xx, #24..31 xx,xx,xx,xx,xx,xx,xx,xx, #32..39 xx,xx,xx,xx,xx,xx,xx,xx, #40..47 wP,wP,wP,wP,wP,wP,wP,wP, #48..55 wR,wN,wB,wQ,wK,wB,wN,wR #56..63 ] def test_initial_values(self): for i,p in enumerate(self.pos): self.assertEqual(p,self.b[i]) self.assertEqual(self.pos.w_castle_qs,True) self.assertEqual(self.pos.w_castle_ks,True) self.assertEqual(self.pos.b_castle_qs,True) self.assertEqual(self.pos.b_castle_ks,True) self.assertEqual(self.pos.ep_sq,None) self.assertEqual(self.pos.turn,WHITE) self.assertEqual(self.pos.check,False) self.assertEqual(self.pos.pieces[xx],set(range(16,48))) def test_set_get_squares_out_of_range(self): self.assertRaises(AssertionError,self.pos.set_square,-1,wB) self.assertRaises(AssertionError,self.pos.set_square,64,wB) self.assertRaises(AssertionError,self.pos.set_square,0,-1) self.assertRaises(AssertionError,self.pos.set_square,0,1000) self.assertRaises(AssertionError,self.pos.get_square,-1) self.assertRaises(AssertionError,self.pos.get_square,64) def test_set_get_square(self): self.assertEqual(self.pos.get_square(48),wP) self.pos.set_square(48,xx) self.pos.set_square(40,wP) self.assertEqual(self.pos.get_square(48),xx) self.assertEqual(self.pos.get_square(40),wP) self.assertEqual(self.pos.get_square(8),bP) self.pos.set_square(8,xx) self.pos.set_square(16,wP) self.assertEqual(self.pos.get_square(8),xx) self.assertEqual(self.pos.get_square(16),wP) self.assertEqual(self.pos.get_square(63),wR) self.pos.set_square(63,xx) self.assertEqual(self.pos.get_square(63),xx) def test_get_row_col_out_of_range(self): self.assertRaises(AssertionError,self.pos.get_row_col,-1) self.assertRaises(AssertionError,self.pos.get_row_col,-2) self.assertRaises(AssertionError,self.pos.get_row_col,64) self.assertRaises(AssertionError,self.pos.get_row_col,65) def test_get_row_col(self): f,c = self.pos.get_row_col(0) self.assertEqual(f,7) self.assertEqual(c,0) f,c = self.pos.get_row_col(3) self.assertEqual(f,7) self.assertEqual(c,3) f,c = self.pos.get_row_col(56) self.assertEqual(f,0) self.assertEqual(c,0) f,c = self.pos.get_row_col(63) self.assertEqual(f,0) self.assertEqual(c,7) f,c = self.pos.get_row_col(50) self.assertEqual(f,1) self.assertEqual(c,2) def test_get_row_col_value_out_of_range(self): self.assertRaises(AssertionError,self.pos.get_row_col_value,-2,0) self.assertRaises(AssertionError,self.pos.get_row_col_value,-1,0) self.assertRaises(AssertionError,self.pos.get_row_col_value,0,-1) self.assertRaises(AssertionError,self.pos.get_row_col_value,0,-2) self.assertRaises(AssertionError,self.pos.get_row_col_value,8,0) self.assertRaises(AssertionError,self.pos.get_row_col_value,9,0) self.assertRaises(AssertionError,self.pos.get_row_col_value,0,8) self.assertRaises(AssertionError,self.pos.get_row_col_value,0,9) def test_get_row_col_value(self): self.assertEqual(self.pos.get_row_col_value(0,0),wR) self.assertEqual(self.pos.get_row_col_value(0,1),wN) self.assertEqual(self.pos.get_row_col_value(0,2),wB) self.assertEqual(self.pos.get_row_col_value(0,3),wQ) self.assertEqual(self.pos.get_row_col_value(0,4),wK) self.assertEqual(self.pos.get_row_col_value(0,7),wR) self.assertEqual(self.pos.get_row_col_value(0,6),wN) self.assertEqual(self.pos.get_row_col_value(0,5),wB) self.assertEqual(self.pos.get_row_col_value(1,0),wP) self.assertEqual(self.pos.get_row_col_value(1,1),wP) self.assertEqual(self.pos.get_row_col_value(1,2),wP) self.assertEqual(self.pos.get_row_col_value(1,3),wP) self.assertEqual(self.pos.get_row_col_value(1,4),wP) self.assertEqual(self.pos.get_row_col_value(1,7),wP) self.assertEqual(self.pos.get_row_col_value(1,6),wP) self.assertEqual(self.pos.get_row_col_value(1,5),wP) self.assertEqual(self.pos.get_row_col_value(7,0),bR) self.assertEqual(self.pos.get_row_col_value(7,1),bN) self.assertEqual(self.pos.get_row_col_value(7,2),bB) self.assertEqual(self.pos.get_row_col_value(7,3),bQ) self.assertEqual(self.pos.get_row_col_value(7,4),bK) self.assertEqual(self.pos.get_row_col_value(7,7),bR) self.assertEqual(self.pos.get_row_col_value(7,6),bN) self.assertEqual(self.pos.get_row_col_value(7,5),bB) self.assertEqual(self.pos.get_row_col_value(6,0),bP) self.assertEqual(self.pos.get_row_col_value(6,1),bP) self.assertEqual(self.pos.get_row_col_value(6,2),bP) self.assertEqual(self.pos.get_row_col_value(6,3),bP) self.assertEqual(self.pos.get_row_col_value(6,4),bP) self.assertEqual(self.pos.get_row_col_value(6,7),bP) self.assertEqual(self.pos.get_row_col_value(6,6),bP) self.assertEqual(self.pos.get_row_col_value(6,5),bP) for i in range(2,6): for j in range(2,6): self.assertEqual(self.pos.get_row_col_value(i,j),xx) def test_set_row_col_value_out_of_range(self): self.assertRaises(AssertionError,self.pos.set_row_col_value,-2,0,xx) self.assertRaises(AssertionError,self.pos.set_row_col_value,-1,0,wB) self.assertRaises(AssertionError,self.pos.set_row_col_value,0,-1,bB) self.assertRaises(AssertionError,self.pos.set_row_col_value,0,-2,wK) self.assertRaises(AssertionError,self.pos.set_row_col_value,8,0,bK) self.assertRaises(AssertionError,self.pos.set_row_col_value,9,0,wQ) self.assertRaises(AssertionError,self.pos.set_row_col_value,0,8,bQ) self.assertRaises(AssertionError,self.pos.set_row_col_value,0,9,bP) self.assertRaises(AssertionError,self.pos.set_row_col_value,7,0,-4) self.assertRaises(AssertionError,self.pos.set_row_col_value,7,7,-1) self.assertRaises(AssertionError,self.pos.set_row_col_value,0,7,-2) self.assertRaises(AssertionError,self.pos.set_row_col_value,5,6,-3) self.assertRaises(AssertionError,self.pos.set_row_col_value,7,0,0) self.assertRaises(AssertionError,self.pos.set_row_col_value,7,0,14) self.assertRaises(AssertionError,self.pos.set_row_col_value,0,7,-1) self.assertRaises(AssertionError,self.pos.set_row_col_value,0,7,14) def test_set_row_col_value(self): self.pos.set_row_col_value(0,0,xx) self.assertEqual(self.pos.get_row_col_value(0,0),xx) self.assertEqual(self.pos.get_square(56),xx) self.pos.set_row_col_value(0,7,wK) self.assertEqual(self.pos.get_row_col_value(0,7),wK) self.assertEqual(self.pos.get_square(63),wK) self.pos.set_row_col_value(1,7,wQ) self.assertEqual(self.pos.get_row_col_value(1,7),wQ) self.assertEqual(self.pos.get_square(55),wQ) self.pos.set_row_col_value(1,3,wB) self.assertEqual(self.pos.get_row_col_value(1,3),wB) self.assertEqual(self.pos.get_square(51),wB) self.pos.set_row_col_value(7,7,xx) self.assertEqual(self.pos.get_row_col_value(7,7),xx) self.assertEqual(self.pos.get_square(7),xx) self.pos.set_row_col_value(6,7,bK) self.assertEqual(self.pos.get_row_col_value(6,7),bK) self.assertEqual(self.pos.get_square(15),bK) self.pos.set_row_col_value(6,0,bQ) self.assertEqual(self.pos.get_row_col_value(6,0),bQ) self.assertEqual(self.pos.get_square(8),bQ) self.pos.set_row_col_value(6,3,bB) self.assertEqual(self.pos.get_row_col_value(6,3),bB) self.assertEqual(self.pos.get_square(11),bB) def test_get_index_row_col(self): self.assertRaises(AssertionError,self.pos.get_index_row_col,-1,0) self.assertRaises(AssertionError,self.pos.get_index_row_col,0,-1) self.assertRaises(AssertionError,self.pos.get_index_row_col,-2,0) self.assertRaises(AssertionError,self.pos.get_index_row_col,0,-2) self.assertRaises(AssertionError,self.pos.get_index_row_col,8,0) self.assertRaises(AssertionError,self.pos.get_index_row_col,0,8) self.assertRaises(AssertionError,self.pos.get_index_row_col,9,0) self.assertRaises(AssertionError,self.pos.get_index_row_col,0,9) self.assertEqual(self.pos.get_index_row_col(7,0),0) self.assertEqual(self.pos.get_index_row_col(7,7),7) self.assertEqual(self.pos.get_index_row_col(0,0),56) self.assertEqual(self.pos.get_index_row_col(0,7),63) self.assertEqual(self.pos.get_index_row_col(5,0),16) def test_piece_sets(self): initial_empty=set(range(16,48)) self.assertEqual(self.pos.pieces[xx],initial_empty) self.assertEqual(self.pos.pieces[bR],set([0,7])) self.assertEqual(self.pos.pieces[bN],set([1,6])) self.assertEqual(self.pos.pieces[bB],set([2,5])) self.assertEqual(self.pos.pieces[bQ],set([3])) self.assertEqual(self.pos.pieces[bK],set([4])) self.assertEqual(self.pos.pieces[bP],set(range(8,16))) self.assertEqual(self.pos.pieces[wR],set([56,63])) self.assertEqual(self.pos.pieces[wN],set([57,62])) self.assertEqual(self.pos.pieces[wB],set([58,61])) self.assertEqual(self.pos.pieces[wQ],set([59])) self.assertEqual(self.pos.pieces[wK],set([60])) initial_wP=set(range(48,56)) self.assertEqual(self.pos.pieces[wP],initial_wP) self.pos.set_square(36,wP) self.pos.set_square(52,xx) self.assertEqual(self.pos.pieces[xx],(initial_empty-set([36]))|set([52])) self.assertEqual(self.pos.pieces[wP],(initial_wP-set([52]))|set([36])) self.pos.set_square(16,bR) self.assertEqual(self.pos.pieces[xx],(initial_empty-set([36])-set([16]))|set([52])) self.assertEqual(self.pos.pieces[bR],set([0,7,16]))
class Test_Position_PosInicial_NoDefault(Test_Position_PosInicial): def setUp(self): self.b=[bR,bN,bB,bQ,bK,bB,bN,bR, #00..07 bP,bP,bP,bP,bP,bP,bP,bP, #08..15 xx,xx,xx,xx,xx,xx,xx,xx, #16..23 xx,xx,xx,xx,xx,xx,xx,xx, #24..31 xx,xx,xx,xx,wP,xx,xx,xx, #32..39 xx,xx,xx,xx,xx,xx,xx,xx, #40..47 wP,wP,wP,wP,xx,wP,wP,wP, #48..55 wR,wN,wB,wQ,wK,wB,wN,wR #56..63 ] self.pos=Position(self.b,True,True,True,True,None,BLACK,0,1) def test_initial_values(self): for i,p in enumerate(self.pos): self.assertEqual(p,self.b[i]) self.assertEqual(self.pos.w_castle_qs,True) self.assertEqual(self.pos.w_castle_ks,True) self.assertEqual(self.pos.b_castle_qs,True) self.assertEqual(self.pos.b_castle_ks,True) self.assertEqual(self.pos.ep_sq,None) self.assertEqual(self.pos.turn,BLACK) self.assertEqual(self.pos.check,False) self.assertEqual(self.pos.pieces[xx],(set(range(16,48))-set([36]))|set([52])) def test_get_row_col_value(self): self.assertEqual(self.pos.get_row_col_value(0,0),wR) self.assertEqual(self.pos.get_row_col_value(0,1),wN) self.assertEqual(self.pos.get_row_col_value(0,2),wB) self.assertEqual(self.pos.get_row_col_value(0,3),wQ) self.assertEqual(self.pos.get_row_col_value(0,4),wK) self.assertEqual(self.pos.get_row_col_value(0,7),wR) self.assertEqual(self.pos.get_row_col_value(0,6),wN) self.assertEqual(self.pos.get_row_col_value(0,5),wB) self.assertEqual(self.pos.get_row_col_value(1,0),wP) self.assertEqual(self.pos.get_row_col_value(1,1),wP) self.assertEqual(self.pos.get_row_col_value(1,2),wP) self.assertEqual(self.pos.get_row_col_value(1,3),wP) self.assertEqual(self.pos.get_row_col_value(1,4),xx) self.assertEqual(self.pos.get_row_col_value(3,4),wP) self.assertEqual(self.pos.get_row_col_value(1,7),wP) self.assertEqual(self.pos.get_row_col_value(1,6),wP) self.assertEqual(self.pos.get_row_col_value(1,5),wP) self.assertEqual(self.pos.get_row_col_value(7,0),bR) self.assertEqual(self.pos.get_row_col_value(7,1),bN) self.assertEqual(self.pos.get_row_col_value(7,2),bB) self.assertEqual(self.pos.get_row_col_value(7,3),bQ) self.assertEqual(self.pos.get_row_col_value(7,4),bK) self.assertEqual(self.pos.get_row_col_value(7,7),bR) self.assertEqual(self.pos.get_row_col_value(7,6),bN) self.assertEqual(self.pos.get_row_col_value(7,5),bB) self.assertEqual(self.pos.get_row_col_value(6,0),bP) self.assertEqual(self.pos.get_row_col_value(6,1),bP) self.assertEqual(self.pos.get_row_col_value(6,2),bP) self.assertEqual(self.pos.get_row_col_value(6,3),bP) self.assertEqual(self.pos.get_row_col_value(6,4),bP) self.assertEqual(self.pos.get_row_col_value(6,7),bP) self.assertEqual(self.pos.get_row_col_value(6,6),bP) self.assertEqual(self.pos.get_row_col_value(6,5),bP) for i in range(2,6): for j in range(2,6): if i!=3 or j!=4: self.assertEqual(self.pos.get_row_col_value(i,j),xx) else: self.assertEqual(self.pos.get_row_col_value(i,j),wP) def test_piece_sets(self): initial_empty=(set(range(16,48)) - set([36]))|set([52]) self.assertEqual(self.pos.pieces[xx],initial_empty) self.assertEqual(self.pos.pieces[bR],set([0,7])) self.assertEqual(self.pos.pieces[bN],set([1,6])) self.assertEqual(self.pos.pieces[bB],set([2,5])) self.assertEqual(self.pos.pieces[bQ],set([3])) self.assertEqual(self.pos.pieces[bK],set([4])) self.assertEqual(self.pos.pieces[bP],set(range(8,16))) self.assertEqual(self.pos.pieces[wR],set([56,63])) self.assertEqual(self.pos.pieces[wN],set([57,62])) self.assertEqual(self.pos.pieces[wB],set([58,61])) self.assertEqual(self.pos.pieces[wQ],set([59])) self.assertEqual(self.pos.pieces[wK],set([60])) initial_wP=(set(range(48,56))-set([52]))|set([36]) self.assertEqual(self.pos.pieces[wP],initial_wP) self.pos.set_square(35,wP) self.pos.set_square(51,xx) self.assertEqual(self.pos.pieces[xx],(initial_empty-set([35]))|set([51])) self.assertEqual(self.pos.pieces[wP],(initial_wP-set([51]))|set([35])) self.pos.set_square(16,bR) self.assertEqual(self.pos.pieces[xx],(initial_empty-set([35])-set([16]))|set([51])) self.assertEqual(self.pos.pieces[bR],set([0,7,16]))
def setUp(self): self.pos=Position() self.movegen=MoveGeneratorBoard(self.pos)
class TestMoveGenBoard(unittest.TestCase): def setUp(self): self.pos=Position() self.movegen=MoveGeneratorBoard(self.pos) def test_move_column(self): for i in range(8): for j in range(8): mgsq=self.movegen.squares[self.pos.get_index_row_col(i,j)] self.assertEqual(len(mgsq.column_moves1),7-i) self.assertEqual(len(mgsq.column_moves2),i) self.assertEqual(mgsq.row,i) self.assertEqual(mgsq.column,j) q=i+1 for m in mgsq.column_moves1: self.assertEqual(m.column,mgsq.column) self.assertEqual(m.row,q) q+=1 q=i-1 for m in mgsq.column_moves2: self.assertEqual(m.column,mgsq.column) self.assertEqual(m.row,q) q-=1 def test_move_row(self): for i in range(8): for j in range(8): mgsq=self.movegen.squares[self.pos.get_index_row_col(i,j)] self.assertEqual(len(mgsq.row_moves1),7-j) self.assertEqual(len(mgsq.row_moves2),j) self.assertEqual(mgsq.row,i) self.assertEqual(mgsq.column,j) q=j+1 for m in mgsq.row_moves1: self.assertEqual(m.column,q) self.assertEqual(m.row,mgsq.row) q+=1 q=j-1 for m in mgsq.row_moves2: self.assertEqual(m.column,q) self.assertEqual(m.row,mgsq.row) q-=1 def test_move_diag(self): for i in range(8): for j in range(8): mgsq=self.movegen.squares[self.pos.get_index_row_col(i,j)] self.assertEqual(len(mgsq.diag_moves1),min(7-i,7-j)) self.assertEqual(len(mgsq.diag_moves2),min(i,7-j)) self.assertEqual(len(mgsq.diag_moves3),min(7-i,j)) self.assertEqual(len(mgsq.diag_moves4),min(i,j)) self.assertEqual(mgsq.row,i) self.assertEqual(mgsq.column,j) r=i+1 q=j+1 for m in mgsq.diag_moves1: self.assertEqual(m.column,q) self.assertEqual(m.row,r) r+=1 q+=1 r=i-1 q=j+1 for m in mgsq.diag_moves2: self.assertEqual(m.column,q) self.assertEqual(m.row,r) r-=1 q+=1 r=i+1 q=j-1 for m in mgsq.diag_moves3: self.assertEqual(m.column,q) self.assertEqual(m.row,r) r+=1 q-=1 r=i-1 q=j-1 for m in mgsq.diag_moves4: self.assertEqual(m.column,q) self.assertEqual(m.row,r) r-=1 q-=1 def test_move_knights(self): for i in range(8): for j in range(8): mgsq=self.movegen.squares[self.pos.get_index_row_col(i,j)] candidates=[x for x in self.movegen.knight_deltas if 0<=(i+x[0])<=7 and 0<=(j+x[1])<=7] self.assertEqual(len(mgsq.knight_moves),len(candidates)) self.assertEqual(mgsq.row,i) self.assertEqual(mgsq.column,j) for q,s in enumerate(mgsq.knight_moves): self.assertEqual(s.row,i+candidates[q][0]) self.assertEqual(s.column,j+candidates[q][1]) def test_move_king(self): for i in range(8): for j in range(8): mgsq=self.movegen.squares[self.pos.get_index_row_col(i,j)] candidates=[x for x in self.movegen.king_deltas if 0<=(i+x[0])<=7 and 0<=(j+x[1])<=7] self.assertEqual(len(mgsq.king_moves),len(candidates)) self.assertEqual(mgsq.row,i) self.assertEqual(mgsq.column,j) for q,s in enumerate(mgsq.king_moves): self.assertEqual(s.row,i+candidates[q][0]) self.assertEqual(s.column,j+candidates[q][1]) def test_pawn_advances(self): for i in range(8): for j in range(8): mgsq=self.movegen.squares[self.pos.get_index_row_col(i,j)] if i!=2: self.assertLess(len(mgsq.pawn_advance_white),2) else: self.assertEqual(mgsq.pawn_advance_white[1].row,i+2) self.assertEqual(mgsq.pawn_advance_white[1].column,j) if i!=7: self.assertLess(len(mgsq.pawn_advance_black),2) else: self.assertEqual(mgsq.pawn_advance_black[1].row,i-2) self.assertEqual(mgsq.pawn_advance_black[1].column,j) if i==7: self.assertEqual(len(mgsq.pawn_advance_white),0) else: self.assertEqual(mgsq.pawn_advance_white[0].row,i+1) self.assertEqual(mgsq.pawn_advance_white[0].column,j) if i==0: self.assertEqual(len(mgsq.pawn_advance_black),0) else: self.assertEqual(mgsq.pawn_advance_black[0].row,i-1) self.assertEqual(mgsq.pawn_advance_black[0].column,j) def test_pawn_captures(self): for i in range(8): for j in range(8): mgsq=self.movegen.squares[self.pos.get_index_row_col(i,j)] if i == 0: self.assertEqual(len(mgsq.pawn_captures_black),0) if j==0: self.assertEqual(len(mgsq.pawn_captures_white),1) for q in mgsq.pawn_captures_white: self.assertEqual(q.row,i+1) self.assertEqual(q.column,j+1) elif j<7: self.assertEqual(len(mgsq.pawn_captures_white),2) s=set() for q in mgsq.pawn_captures_white: self.assertEqual(q.row,i+1) s.add(q.column) self.assertEqual(s,set([j+1,j-1])) else: self.assertEqual(len(mgsq.pawn_captures_white),1) for q in mgsq.pawn_captures_white: self.assertEqual(q.row,i+1) self.assertEqual(q.column,j-1) elif i < 7: if j==0: self.assertEqual(len(mgsq.pawn_captures_black),1) for q in mgsq.pawn_captures_black: self.assertEqual(q.row,i-1) self.assertEqual(q.column,j+1) self.assertEqual(len(mgsq.pawn_captures_white),1) for q in mgsq.pawn_captures_white: self.assertEqual(q.row,i+1) self.assertEqual(q.column,j+1) elif j<7: self.assertEqual(len(mgsq.pawn_captures_black),2) s=set() for q in mgsq.pawn_captures_black: self.assertEqual(q.row,i-1) s.add(q.column) self.assertEqual(s,set([j+1,j-1])) self.assertEqual(len(mgsq.pawn_captures_white),2) s=set() for q in mgsq.pawn_captures_white: self.assertEqual(q.row,i+1) s.add(q.column) self.assertEqual(s,set([j+1,j-1])) else: self.assertEqual(len(mgsq.pawn_captures_black),1) for q in mgsq.pawn_captures_black: self.assertEqual(q.row,i-1) self.assertEqual(q.column,j-1) self.assertEqual(len(mgsq.pawn_captures_white),1) for q in mgsq.pawn_captures_white: self.assertEqual(q.row,i+1) self.assertEqual(q.column,j-1) else: self.assertEqual(len(mgsq.pawn_captures_white),0) if j==0: self.assertEqual(len(mgsq.pawn_captures_black),1) for q in mgsq.pawn_captures_black: self.assertEqual(q.row,i-1) self.assertEqual(q.column,j+1) elif j<7: self.assertEqual(len(mgsq.pawn_captures_black),2) s=set() for q in mgsq.pawn_captures_black: self.assertEqual(q.row,i-1) s.add(q.column) self.assertEqual(s,set([j+1,j-1])) else: self.assertEqual(len(mgsq.pawn_captures_black),1) for q in mgsq.pawn_captures_black: self.assertEqual(q.row,i-1) self.assertEqual(q.column,j-1) def test_move_sets(self): move_types=['column_moves1', 'column_moves2', 'row_moves1', 'row_moves2', 'diag_moves1', 'diag_moves2', 'diag_moves3', 'diag_moves4', 'knight_moves', 'king_moves', 'pawn_advance_white', 'pawn_advance_black', 'pawn_captures_white', 'pawn_captures_black', ] for i in range(63): sq=self.movegen.squares[i] for t in move_types: print t self.assertEqual(set([x.square for x in getattr(sq,t)]),getattr(sq,'set_'+t))