def _add_correct_cells_by_ray(position, correct_cells, chess_board, figure_side, dx, dy, step_len=Board.COLUMN_SIZE, can_step_on_figure=True): delta = Vector2d(dx, dy) cur_step_len = 0 while cur_step_len < step_len and \ Board.ROW_SIZE > position.x + delta.x >= 0 and \ 0 <= position.y + delta.y < Board.COLUMN_SIZE and \ _is_none_or_enemy(chess_board, position + delta, figure_side): if _is_enemy(chess_board, position + delta, figure_side): if can_step_on_figure: correct_cells.append(position + delta) break else: break elif _is_enemy(chess_board, position + delta, Side.get_oposite(figure_side)): break correct_cells.append(position + delta) delta.x = delta.x + dx delta.y = delta.y + dy cur_step_len = cur_step_len + 1
def generate_moves(self, chess_board, its_my_turn=True): correct_cells = [] if its_my_turn is True: self.roque_right(chess_board, correct_cells) self.roque_left(chess_board, correct_cells) _add_correct_cells_by_ray(self.position, correct_cells, chess_board, self.side, 0, 1, 1) _add_correct_cells_by_ray(self.position, correct_cells, chess_board, self.side, 0, -1, 1) _add_correct_cells_by_ray(self.position, correct_cells, chess_board, self.side, 1, 1, 1) _add_correct_cells_by_ray(self.position, correct_cells, chess_board, self.side, -1, -1, 1) _add_correct_cells_by_ray(self.position, correct_cells, chess_board, self.side, 1, 0, 1) _add_correct_cells_by_ray(self.position, correct_cells, chess_board, self.side, -1, 0, 1) _add_correct_cells_by_ray(self.position, correct_cells, chess_board, self.side, 1, -1, 1) _add_correct_cells_by_ray(self.position, correct_cells, chess_board, self.side, -1, 1, 1) if its_my_turn is True: summary_attacked_cells = chess_board.summary_attacked_cells( Side.get_oposite(self.side)) for i in range(len(summary_attacked_cells)): try: correct_cells.remove(summary_attacked_cells[i]) except ValueError: pass return correct_cells
def roque_right(self, chess_board, correct_cells): # self does not move if self.was_moved is True: return # self not on check attack_cells = chess_board.summary_attacked_cells( Side.get_oposite(self.side)) if self.position in attack_cells: return if self.side == Side.WHITE: default_rook_right_pos = gb.GameBoard.default_white_rook_right_pos else: default_rook_right_pos = gb.GameBoard.default_black_rook_right_pos right_rook = chess_board.get(default_rook_right_pos) # rook does not move if not (right_rook is not None and isinstance(right_rook, Rook) and right_rook.was_moved is False): return # not on attack cell if self.position + Vector2d(1, 0) in attack_cells: return ray_to_rook = [] _add_correct_cells_by_ray(self.position, ray_to_rook, chess_board, Side.get_oposite(self.side), 1, 0) if len(ray_to_rook) == 0: return if chess_board.get(ray_to_rook[len(ray_to_rook) - 1]).position != default_rook_right_pos: return correct_cells.append(self.position + Vector2d(2, 0))
def is_that_mate(self, my_side): enemy_figures = self.get_figures_list(Side.get_oposite(my_side)) for i in range(len(enemy_figures)): cur_figure = enemy_figures[i] available_moves = cur_figure.generate_moves(self) for j in range(len(available_moves)): new_chess_board = copy.deepcopy(self) if new_chess_board.get(cur_figure.position) is None: print(cur_figure.position.x) print(cur_figure.position.y) new_chess_board.make_move(Move(cur_figure.position, available_moves[j])) if new_chess_board.is_that_check(my_side) is False: return False return True
def check_move(self, move, side): """ Check current position state function :param side: player current side :param move: move figure sructure (Vector2d) :param chess_board: chess board class (see ChessBoard.Board) :return: MoveResult """ result = MoveResult.INCORRECT figure_in_src = self.game_board.get(move.point_from) if figure_in_src is None: return result if figure_in_src.side != side: return result if figure_in_src is None: return result my_side = figure_in_src.side correct_moves = figure_in_src.generate_moves(self.game_board) if len(correct_moves) == 0: return result if move.point_to in correct_moves: result = MoveResult.DEFAULT if result == MoveResult.INCORRECT: return result new_game_board = copy.deepcopy(self.game_board) new_game_board.make_move(move) if new_game_board.is_that_check(Side.get_oposite(my_side)): result = MoveResult.INCORRECT if result == MoveResult.INCORRECT: return result if new_game_board.is_that_check(my_side): result = MoveResult.CHECK if new_game_board.is_that_mate(my_side): result = MoveResult.MATE else: if new_game_board.is_that_stalemate(my_side): result = MoveResult.STALEMATE return result
def check_board_res(self, side): result = MoveResult.DEFAULT new_game_board = copy.deepcopy(self.game_board) if new_game_board.is_that_check(Side.get_oposite(side)): result = MoveResult.INCORRECT if result == MoveResult.INCORRECT: return result if new_game_board.is_that_check(side): result = MoveResult.CHECK if new_game_board.is_that_mate(side): result = MoveResult.MATE else: if new_game_board.is_that_stalemate(side): result = MoveResult.STALEMATE return result
def calc_best_move(self, depth, game, player_color, alpha=-999999999, beta=999999999, is_maximizing_player=True): # Base case: evaluate board if depth == 0: value = game.game_board.evaluate(self.side) return value, None # Recursive case: search possible moves best_swaped_figure = None best_move = None # best move not set yet possible_moves = game.game_board.summary_moves(player_color) # Set random order for possible moves shuffle(possible_moves) # Set a default best move value if is_maximizing_player: best_move_value = -99999999 else: best_move_value = 99999999 # Search through all possible moves for i in range(len(possible_moves)): move_res = game.check_move(possible_moves[i], player_color) if move_res is not MoveResult.INCORRECT: move = possible_moves[i] # Make the move, but undo before exiting loop new_game = copy.deepcopy(game) new_game.update(possible_moves[i], player_color) # pawn swaped check expected_pawn = new_game.game_board.get(move.point_to) if isinstance(expected_pawn, Figures.Pawn): assert (self.pawn_swaped_latters is not None) if expected_pawn.side is Side.WHITE: if move.point_to.y == 0: for figure_lat in self.pawn_swaped_latters: new_game.swap_pawn(move.point_to, figure_lat) value, move_side_effect = self.calc_best_move( depth - 1, new_game, Side.get_oposite(player_color), alpha, beta, not is_maximizing_player) if is_maximizing_player: # Look for moves that maximize position if value > best_move_value: best_move_value = value best_move = move best_swaped_figure = figure_lat alpha = max(alpha, value) else: # Look for moves that minimize position if value < best_move_value: best_move_value = value best_move = move best_swaped_figure = figure_lat beta = min(beta, value) # Check for alpha beta pruning if beta <= alpha: # print('Prune', alpha, beta) return best_move_value, best_move else: # Recursively get the value from this move value, move_side_effect = self.calc_best_move( depth - 1, new_game, Side.get_oposite(player_color), alpha, beta, not is_maximizing_player) if is_maximizing_player: # Look for moves that maximize position if value > best_move_value: best_move_value = value best_move = move alpha = max(alpha, value) else: # Look for moves that minimize position if value < best_move_value: best_move_value = value best_move = move beta = min(beta, value) # Check for alpha beta pruning if beta <= alpha: # print('Prune', alpha, beta) return best_move_value, best_move if expected_pawn.side is Side.BLACK: if move.point_to.y == 7: for figure_lat in self.pawn_swaped_latters: new_game.swap_pawn(move.point_to, figure_lat) value, move_side_effect = self.calc_best_move( depth - 1, new_game, Side.get_oposite(player_color), alpha, beta, not is_maximizing_player) if is_maximizing_player: # Look for moves that maximize position if value > best_move_value: best_move_value = value best_move = move best_swaped_figure = figure_lat alpha = max(alpha, value) else: # Look for moves that minimize position if value < best_move_value: best_move_value = value best_move = move best_swaped_figure = figure_lat beta = min(beta, value) # Check for alpha beta pruning if beta <= alpha: # print('Prune', alpha, beta) return best_move_value, best_move else: # Recursively get the value from this move value, move_side_effect = self.calc_best_move( depth - 1, new_game, Side.get_oposite(player_color), alpha, beta, not is_maximizing_player) if is_maximizing_player: # Look for moves that maximize position if value > best_move_value: best_move_value = value best_move = move alpha = max(alpha, value) else: # Look for moves that minimize position if value < best_move_value: best_move_value = value best_move = move beta = min(beta, value) # Check for alpha beta pruning if beta <= alpha: # print('Prune', alpha, beta) return best_move_value, best_move else: # Recursively get the value from this move value, move_side_effect = self.calc_best_move( depth - 1, new_game, Side.get_oposite(player_color), alpha, beta, not is_maximizing_player) if is_maximizing_player: # Look for moves that maximize position if value > best_move_value: best_move_value = value best_move = move alpha = max(alpha, value) else: # Look for moves that minimize position if value < best_move_value: best_move_value = value best_move = move beta = min(beta, value) # Check for alpha beta pruning if beta <= alpha: # print('Prune', alpha, beta) return best_move_value, best_move if depth == self.depth: self.move = best_move self.value = best_move_value self.pawn_swaped_figure = best_swaped_figure return best_move_value, best_move
def update(self, move, side): figure = self.game_board.get(move.point_from) assert figure is not None self.game_board.make_move(move) self.game_board.delete_double_move(Side.get_oposite(side))
def is_that_check(self, my_side): attacked_cells = self.summary_attacked_cells(my_side) enemy_king_cell = self.get_king_cell(Side.get_oposite(my_side)) return enemy_king_cell in attacked_cells