1 | # pylint: disable=R0902 |
||
0 ignored issues
–
show
|
|||
2 | # disabling too many instance attributes for now. |
||
3 | # once I implement enpassant and castling, |
||
4 | # I shouldn't need some of the FEN attributes. |
||
5 | 1 | import json |
|
6 | |||
7 | 1 | from .. import standard_chess_json |
|
8 | 1 | from .base import Board |
|
9 | 1 | from ..piece import Piece |
|
10 | |||
11 | 1 | from ..movement import get_all_potential_end_locations |
|
12 | 1 | from .. import movement |
|
13 | |||
14 | 1 | map_fen_to_piece_name = { |
|
15 | 'k': "king", |
||
16 | 'q': "queen", |
||
17 | 'n': "knight", |
||
18 | 'b': "bishop", |
||
19 | 'r': "rook", |
||
20 | 'p': "pawn" |
||
21 | } |
||
22 | |||
23 | |||
24 | 1 | class ChessBoard(Board): |
|
0 ignored issues
–
show
This class should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. ![]() |
|||
25 | |||
26 | 1 | def __init__(self, existing_board=None): |
|
27 | 1 | super().__init__(8, 8) |
|
28 | 1 | self.pieces = [] |
|
29 | 1 | self.players = {} |
|
30 | 1 | self.end_game = {} |
|
31 | |||
32 | 1 | self.standard_chess = standard_chess_json |
|
33 | |||
34 | 1 | if not existing_board: |
|
35 | 1 | existing_board = self.load_json() |
|
36 | |||
37 | 1 | self.initialize_board(existing_board) |
|
38 | if existing_board and existing_board['players']['current'] == "Player 1": |
||
39 | self.current_players_turn = "w" |
||
40 | 1 | else: |
|
41 | 1 | self.current_players_turn = "b" |
|
42 | 1 | ||
43 | 1 | # FEN data I should take into account |
|
44 | 1 | self.castling_opportunities = "KQkq" |
|
45 | self.en_passant_target_square = "-" |
||
46 | 1 | self.half_move_clock = 0 |
|
47 | 1 | self.full_move_number = 1 |
|
48 | |||
49 | 1 | def __getitem__(self, key): |
|
50 | 1 | return self.board[key] |
|
51 | |||
52 | 1 | def __setitem__(self, key, value): |
|
53 | 1 | self.board[key] = value |
|
54 | 1 | ||
55 | def __iter__(self): |
||
56 | 1 | for key in self.board: |
|
57 | 1 | yield key |
|
58 | |||
59 | 1 | def __len__(self): |
|
60 | return len(self.board) |
||
61 | 1 | ||
62 | def generate_fen(self): |
||
63 | 1 | """Generates a FEN representation of the board.""" |
|
64 | 1 | board = "" |
|
65 | 1 | # FEN notation starts in the top left |
|
66 | 1 | for row in range(self.rows - 1, -1, -1): |
|
67 | 1 | num_missing = 0 |
|
68 | for column in range(0, self.columns): |
||
69 | 1 | key = (row, column) |
|
70 | 1 | piece = self[key] |
|
71 | 1 | ||
72 | 1 | if piece: |
|
73 | 1 | prepend = '' |
|
74 | 1 | if num_missing: |
|
75 | prepend = str(num_missing) |
||
76 | 1 | board += prepend + repr(piece) |
|
77 | 1 | num_missing = 0 |
|
78 | 1 | else: |
|
79 | 1 | num_missing += 1 |
|
80 | if num_missing: |
||
81 | 1 | board += str(num_missing) |
|
82 | board += "/" |
||
83 | |||
84 | other_info = " {cpt} {co} {epts} {hmc} {fmn}".format(cpt=self.current_players_turn, |
||
85 | co=self.castling_opportunities, |
||
86 | 1 | epts=self.en_passant_target_square, |
|
87 | 1 | hmc=self.half_move_clock, |
|
88 | fmn=self.full_move_number) |
||
89 | 1 | fen = board[0:-1] + other_info |
|
90 | 1 | return fen |
|
91 | 1 | ||
92 | def import_fen_board(self, fen_board): |
||
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. ![]() |
|||
93 | json_data = self.load_json() |
||
94 | 1 | board_data, self.current_players_turn, self.castling_opportunities,\ |
|
95 | 1 | self.en_passant_target_square, self.half_move_clock,\ |
|
96 | 1 | self.full_move_number = fen_board.split(' ') |
|
97 | 1 | rows = board_data.split('/') |
|
98 | 1 | for row in range(self.rows - 1, -1, -1): |
|
99 | 1 | fen_row = rows[7 - row] |
|
100 | 1 | actual_column = 0 |
|
101 | 1 | for column in range(0, len(fen_row)): |
|
102 | 1 | try: |
|
103 | 1 | num_missing = int(fen_row[actual_column]) |
|
104 | 1 | for column in range(0, num_missing): |
|
105 | 1 | self[(row, actual_column)] = None |
|
106 | 1 | actual_column += 1 |
|
107 | 1 | except ValueError: |
|
108 | 1 | name = map_fen_to_piece_name[fen_row[actual_column].lower()] |
|
109 | 1 | color = "black" if fen_row[actual_column].islower() else "white" |
|
110 | moves = self.get_piece_moves(name, json_data) |
||
111 | 1 | self[(row, column)] = Piece(name, color, moves) |
|
112 | 1 | actual_column += 1 |
|
113 | 1 | ||
114 | 1 | def export(self): |
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. ![]() |
|||
115 | 1 | json_data = {} |
|
116 | json_data['pieces'] = {} |
||
117 | 1 | for piece in self.pieces: |
|
118 | 1 | json_data['pieces'][piece.kind] = {'moves': piece.moves} |
|
119 | 1 | ||
120 | json_data['players'] = self.players |
||
121 | if self.current_players_turn == 'w': |
||
122 | json_data['players']['current'] = "Player 1" |
||
123 | 1 | else: |
|
124 | 1 | json_data['players']['current'] = "Player 2" |
|
125 | 1 | ||
126 | 1 | map_color_to_name = {} |
|
127 | 1 | json_board = {} |
|
128 | 1 | for player in self.players: |
|
129 | if player != 'current': |
||
130 | 1 | map_color_to_name[self.players[player]['color']] = player |
|
131 | 1 | json_board[player] = {} |
|
132 | 1 | ||
133 | 1 | for location in self: |
|
134 | 1 | piece = self[location] |
|
135 | 1 | if piece: |
|
136 | player = map_color_to_name[piece.color] |
||
137 | 1 | if piece.kind in json_board[player]: |
|
138 | json_board[player][piece.kind].append(list(location)) |
||
139 | 1 | else: |
|
140 | json_board[player][piece.kind] = [list(location)] |
||
141 | 1 | ||
142 | json_data['board'] = json_board |
||
143 | 1 | ||
144 | 1 | json_data['end_game'] = self.end_game |
|
145 | 1 | ||
146 | print("export data is:") |
||
147 | 1 | print(json_data) |
|
148 | 1 | return json_data |
|
149 | |||
150 | 1 | def initialize_board(self, json_data): |
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. ![]() |
|||
151 | 1 | json_board = json_data['board'] |
|
152 | 1 | ||
153 | 1 | self.end_game = json_data['end_game'] |
|
154 | for player in ['Player 1', 'Player 2']: |
||
155 | 1 | players_data = json_data['players'] |
|
156 | color = players_data[player]['color'] |
||
157 | 1 | ||
158 | 1 | self.players[player] = players_data[player] |
|
159 | 1 | ||
160 | 1 | player_pieces = json_board[player] |
|
161 | 1 | for piece in player_pieces: |
|
162 | name = piece |
||
163 | 1 | moves = self.get_piece_moves(name, json_data) |
|
164 | a_piece = Piece(name, color, moves) |
||
165 | 1 | ||
166 | 1 | self.pieces.append(a_piece) |
|
167 | |||
168 | 1 | for location in player_pieces[piece]: |
|
169 | 1 | self[tuple(location)] = a_piece |
|
170 | |||
171 | if json_data['players']['current'] == "Player 1": |
||
172 | self.current_players_turn = 'w' |
||
173 | 1 | else: |
|
174 | 1 | self.current_players_turn = 'b' |
|
175 | 1 | ||
176 | def clear_board(self): |
||
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. ![]() |
|||
177 | 1 | for location in self: |
|
178 | self[location] = None |
||
179 | 1 | ||
180 | @staticmethod |
||
181 | 1 | def get_piece_moves(name, json_data): |
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. ![]() |
|||
182 | 1 | return json_data['pieces'][name]['moves'] |
|
183 | 1 | ||
184 | 1 | def load_json(self): |
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. ![]() |
|||
185 | 1 | filename = self.standard_chess |
|
186 | data = None |
||
187 | 1 | with open(filename) as data_file: |
|
188 | data = json.load(data_file) |
||
189 | 1 | ||
190 | 1 | return data |
|
191 | 1 | ||
192 | 1 | def end_locations_for_piece_at_location(self, start_location): |
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. ![]() |
|||
193 | 1 | piece = self[start_location] |
|
194 | 1 | if not piece: |
|
195 | 1 | return [] |
|
196 | player_direction = None |
||
197 | 1 | for player in self.players: |
|
198 | 1 | if piece.color == self.players[player]['color']: |
|
199 | 1 | player_direction = self.players[player]['direction'] |
|
200 | 1 | break |
|
201 | 1 | ||
202 | 1 | all_end_points = [] |
|
203 | 1 | for move in piece.moves: |
|
204 | 1 | directions = move['directions'] |
|
205 | 1 | conditions = [getattr(movement, condition) for condition in move['conditions'] if hasattr(movement, condition)] |
|
206 | 1 | ends = get_all_potential_end_locations(start_location, directions, self) |
|
207 | 1 | for condition in conditions: |
|
208 | # print("ends before condition: {} are: {}".format(condition, ends)) |
||
209 | 1 | ends = condition(self, start_location, directions, ends, player_direction) |
|
210 | 1 | # print("ends after condition: {} are: {}".format(condition, ends)) |
|
211 | 1 | all_end_points += ends |
|
212 | 1 | return all_end_points |
|
213 | |||
214 | 1 | def move(self, start_location, end_location): |
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. ![]() |
|||
215 | if self.is_valid_move(start_location, end_location): |
||
216 | if self.current_players_turn == 'w': |
||
217 | if self[start_location].color == 'black': |
||
218 | print('black trying to move, but whites turn') |
||
219 | return False |
||
220 | 1 | self.current_players_turn = 'b' |
|
221 | 1 | else: |
|
222 | 1 | if self[start_location].color == 'white': |
|
223 | 1 | print('white trying to move, but blacks turn') |
|
224 | 1 | return False |
|
225 | 1 | self.full_move_number += 1 |
|
226 | self.current_players_turn = 'w' |
||
227 | print("is valid move") |
||
228 | 1 | is_capture = self[end_location] is not None |
|
229 | 1 | self[end_location] = self[start_location] |
|
230 | self[start_location] = None |
||
231 | 1 | self[end_location].move_count += 1 |
|
232 | 1 | if self[end_location].kind != "pawn" and not is_capture: |
|
233 | 1 | self.half_move_clock += 1 |
|
234 | 1 | else: |
|
235 | 1 | self.half_move_clock = 0 |
|
236 | return True |
||
237 | 1 | print('is not valid move') |
|
238 | 1 | return False |
|
239 | |||
240 | 1 | def is_valid_move(self, start_location, end_location): |
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. ![]() |
|||
241 | possible_moves = self.valid_moves(start_location) |
||
242 | 1 | if end_location in possible_moves: |
|
243 | return True |
||
244 | return False |
||
245 | |||
246 | def valid_moves(self, start_location): |
||
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. ![]() |
|||
247 | return self.end_locations_for_piece_at_location(start_location) |
||
248 | |||
249 | @property |
||
250 | def board(self): |
||
251 | return self._board |
||
252 |
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.