|
3 | 3 |
|
4 | 4 | """ |
5 | 5 |
|
6 | | -import logging |
7 | | -from typing import List, Tuple |
8 | | - |
9 | | -logger = logging.getLogger(__name__) |
10 | | - |
11 | | - |
12 | | -class Piece: |
13 | | - """Chess piece model |
14 | | -
|
15 | | - :ivar name: the name of a piece (e.g. "king", "pawn") |
16 | | - :type name: str |
17 | | - :ivar position: the position on a chess board |
18 | | - :type position: tuple |
19 | | - :ivar is_white: a flag indicating if a chess piece is white |
20 | | - :type is_white: bool |
21 | | -
|
22 | | - """ |
23 | | - |
24 | | - name: str = "piece" |
25 | | - |
26 | | - def __init__(self, |
27 | | - is_white: bool = True, |
28 | | - position: Tuple[int, int] = (0, 0)) -> None: |
29 | | - """Initialize instance |
30 | | -
|
31 | | - :param is_white: indicating if a piece is white. Defaults to True. |
32 | | - :type is_white: bool |
33 | | - :param position: initial piece position. Defaults to (0, 0). |
34 | | - :type position: tuple |
35 | | -
|
36 | | - """ |
37 | | - |
38 | | - self.is_white = is_white |
39 | | - self.position = position |
40 | | - |
41 | | - def __repr__(self) -> str: |
42 | | - """Return a string representation of an instance""" |
43 | | - |
44 | | - return f"{self.__class__.__name__}({self.is_white}, {self.position})" |
45 | | - |
46 | | - def __str__(self) -> str: |
47 | | - """Return a string version of an instance""" |
48 | | - |
49 | | - color = "white" if self.is_white else "black" |
50 | | - |
51 | | - return f"{color} {self.name} at {self.position}" |
52 | | - |
53 | | - def swap_color(self) -> None: |
54 | | - """Change the piece color to the opposite one""" |
55 | | - |
56 | | - self.is_white = not self.is_white |
57 | | - |
58 | | - def set_position(self, position: Tuple[int, int]) -> None: |
59 | | - """Change piece position to a specified one |
60 | | -
|
61 | | - :param position: new position for a piece |
62 | | - :type position: tuple |
63 | | -
|
64 | | - """ |
65 | | - |
66 | | - if within_board(position): |
67 | | - self.position = position |
68 | | - return |
69 | | - |
70 | | - logger.warning("Position %s is outside the board", position) |
71 | | - |
72 | | - def can_move(self, position: Tuple[int, int]) -> bool: |
73 | | - """Check if a move to a specified position is valid |
74 | | -
|
75 | | - :param position: a position to check |
76 | | - :type position: tuple |
77 | | -
|
78 | | - :return: True if move is valid, otherwise False |
79 | | - :rtype: bool |
80 | | -
|
81 | | - """ |
82 | | - |
83 | | - raise NotImplementedError |
84 | | - |
85 | | - def get_delta(self, position: Tuple[int, int]) -> Tuple[int, int]: |
86 | | - """Return the deltas between current position and the specified one |
87 | | -
|
88 | | - :param position: a position to calculate delta with |
89 | | - :type position: tuple |
90 | | - :return: a pair of delta x and delta y values |
91 | | - :rtype: tuple |
92 | | -
|
93 | | - """ |
94 | | - |
95 | | - position_x, position_y = position |
96 | | - current_x, current_y = self.position |
97 | | - |
98 | | - return position_x - current_x, position_y - current_y |
99 | | - |
100 | | - |
101 | | -class King(Piece): # pylint: disable=C0115 |
102 | | - name = "king" |
103 | | - |
104 | | - def can_move(self, position: Tuple[int, int]) -> bool: |
105 | | - delta_x, delta_y = self.get_delta(position) |
106 | | - if not -1 <= delta_x <= 1 or not -1 <= delta_y <= 1: |
107 | | - return False |
108 | | - |
109 | | - return within_board(position) |
110 | | - |
111 | | - |
112 | | -class Queen(Piece): # pylint: disable=C0115 |
113 | | - name = "queen" |
114 | | - |
115 | | - def can_move(self, position: Tuple[int, int]) -> bool: |
116 | | - delta_x, delta_y = self.get_delta(position) |
117 | | - if abs(delta_x) != abs(delta_y) and delta_x != 0 and delta_y != 0: |
118 | | - return False |
119 | | - |
120 | | - return within_board(position) |
121 | | - |
122 | | - |
123 | | -class Bishop(Piece): # pylint: disable=C0115 |
124 | | - name = "bishop" |
125 | | - |
126 | | - def can_move(self, position: Tuple[int, int]) -> bool: |
127 | | - delta_x, delta_y = self.get_delta(position) |
128 | | - if abs(delta_x) != abs(delta_y): |
129 | | - return False |
130 | | - |
131 | | - return within_board(position) |
132 | | - |
133 | | - |
134 | | -class Knight(Piece): # pylint: disable=C0115 |
135 | | - name = "knight" |
136 | | - |
137 | | - def can_move(self, position: Tuple[int, int]) -> bool: |
138 | | - delta_x, delta_y = self.get_delta(position) |
139 | | - if (abs(delta_x), abs(delta_y)) not in ((2, 1), (1, 2)): |
140 | | - return False |
141 | | - |
142 | | - return within_board(position) |
143 | | - |
144 | | - |
145 | | -class Rook(Piece): # pylint: disable=C0115 |
146 | | - name = "rook" |
147 | | - |
148 | | - def can_move(self, position: Tuple[int, int]) -> bool: |
149 | | - delta_x, delta_y = self.get_delta(position) |
150 | | - if delta_x != 0 and delta_y != 0: |
151 | | - return False |
152 | | - |
153 | | - return within_board(position) |
154 | | - |
155 | | - |
156 | | -class Pawn(Piece): # pylint: disable=C0115 |
157 | | - name = "pawn" |
158 | | - |
159 | | - def can_move(self, position: Tuple[int, int]) -> bool: |
160 | | - delta_x, delta_y = self.get_delta(position) |
161 | | - if delta_x != 0: |
162 | | - return False |
163 | | - if self.is_white and delta_y != 1: |
164 | | - return False |
165 | | - if not self.is_white and delta_y != -1: |
166 | | - return False |
167 | | - |
168 | | - return within_board(position) |
169 | | - |
170 | | - |
171 | | -def within_board(position: Tuple[int, int]) -> bool: |
172 | | - """Check if position is within a chess board |
173 | | -
|
174 | | - :param position: a position to check |
175 | | - :type position: tuple |
176 | | -
|
177 | | - :return: True if position is within a chess board, otherwise False |
178 | | - :rtype: bool |
179 | | -
|
180 | | - """ |
181 | | - |
182 | | - position_x, position_y = position |
183 | | - |
184 | | - return 0 <= position_x <= 7 and 0 <= position_y <= 7 |
185 | | - |
186 | | - |
187 | | -def filter_can_move(pieces: List[Piece], |
188 | | - position: Tuple[int, int]) -> List[Piece]: |
189 | | - """Filter the list of chess piece |
190 | | -
|
191 | | - :param pieces: a list of chess pieces |
192 | | - :type pieces: list |
193 | | - :param position: a position to check piece move |
194 | | - :type position: tuple |
195 | | -
|
196 | | - :return: a list of pieces that can move to specified position |
197 | | - :rtype: list |
198 | | -
|
199 | | - """ |
200 | | - |
201 | | - return [piece for piece in pieces if piece.can_move(position)] |
| 6 | +__author__ = "Serhii Horodilov <sgorodil@gmail.com>" |
| 7 | +__all__ = [ |
| 8 | + "filter_can_move", |
| 9 | + "within_board", |
| 10 | + "Piece", |
| 11 | + "King", |
| 12 | + "Queen", |
| 13 | + "Bishop", |
| 14 | + "Knight", |
| 15 | + "Rook", |
| 16 | + "Pawn", |
| 17 | +] |
| 18 | + |
| 19 | +from chess.func import filter_can_move, within_board |
| 20 | +from chess.piece import Bishop, King, Knight, Pawn, Piece, Queen, Rook |
0 commit comments