def _get_heuristic(self) -> int: if not self.check_terminal_state(): return 0 if self.check_win(get_other_player(self.next_player)): return 30 if self.check_win(self.next_player): return -30 return 15
def _get_manhattan_distance_to_cell(self, cell: (int, int)) -> int: """ :return: Summary manhattan distance from cell to every opponent's cell """ opponent_cells = [ind for ind, val in enumerate(self.board) if val == get_other_player(self.next_player)] if len(opponent_cells) == 0: return 0 manh_sum = 0 for ind in opponent_cells: indices_2d = get_2d_indices(ind) manh_sum += abs(indices_2d[0] - cell[0]) + abs(indices_2d[1] - cell[1]) return manh_sum
def _simple_alg(self): """ Simple algorithm, based on If's :return: new State and Move to get new State """ # If can win -> do it for children, move in self._get_childrens(): if children.check_win(self.next_player)[0]: return children, get_2d_indices(move) # If can lose -> block it possible_moves = self.get_empty_indices() for ind in possible_moves: opp_state = self.make_move(get_2d_indices(ind), get_other_player(self.next_player)) if opp_state.check_win(get_other_player(self.next_player))[0]: block_state = self.make_move(get_2d_indices(ind)) return block_state, get_2d_indices(ind) # Check tricky opponent's combination (opposite corners used) cnt_xs = len([val for val in self.board if val == 1]) if cnt_xs == 2 and self.ai_num == 2 and ( self.board[0] == self.board[8] == 1 or self.board[2] == self.board[6] == 1): move = get_2d_indices(random.choice(self._moves_others)) return self.make_move(move), move # Sort corner cells by decreasing distance to opponent's cells if ai_num == 1. # Else sort by increasing distance. reverse = True if self.ai_num == 1 else False self._moves_corners = list(sorted(self._moves_corners, key=lambda index: self._get_manhattan_distance_to_cell(get_2d_indices(index)), reverse=reverse)) # Choosing best possible move resorted_moves = [move for move in self._best_moves() if move in possible_moves] if len(resorted_moves) == 0: return self, None return self.make_move(get_2d_indices(resorted_moves[0])), get_2d_indices(resorted_moves[0])
def make_move(self, cell: (int, int), num_player=None): """ :param cell: The cell to place player's label :param num_player: Player who needs to make a move :return: The new state if move is allowed, otherwise old state. """ if num_player is None: num_player = self.next_player index_1d = get_1d_index(cell[0], cell[1]) if self.board[index_1d] == 0: new_board = self.board.copy() new_board[index_1d] = num_player return State(new_board, get_other_player(num_player), ai_num=self.ai_num) else: return self
def _check_terminal_state(self): """ Update color of cells if terminal state """ if self.state.check_terminal_state(): is_win, cell1, cell2, cell3 = self.state.check_win(self.state.ai_num) if is_win: self._set_cells_win(get_2d_indices(cell1), get_2d_indices(cell2), get_2d_indices(cell3), Interface._cell_color_ai_win) is_win, cell1, cell2, cell3 = self.state.check_win(get_other_player(self.state.ai_num)) if is_win: self._set_cells_win(get_2d_indices(cell1), get_2d_indices(cell2), get_2d_indices(cell3), Interface._cell_color_human_win) if self.state.check_draw(): for cell in self.cells: cell.configure(bg=Interface._cell_color_draw) self.end_game = True
def check_game_over(board, valid_move, player_turn, turns): if not valid_move: print(player_turn + ' player wins. Illegal move.') return True if board.king_in_check(player_turn): available_moves = find_available_moves(board, player_turn) if not available_moves: print(utils.get_other_player(player_turn) + ' player wins. Checkmate.') return True else: print(player_turn + ' player is in check!') print('Available moves: ') for move in available_moves: print(move) if turns >= const.MAX_MOVES * 2: print('Tie game. Too many moves.') return True return False
def can_drop_piece(self, player_turn, piece, pos): ''' Return True if drop is possible. ''' piece_name = str(piece) if len(piece_name) > 1: piece_name = piece_name[1] # Cannot place Pawn in promotion zone or in same row as another Pawn. if piece_name.lower() == 'p': if ((player_turn == 'UPPER' and utils.get_coords(pos)[1] == 0) or \ (player_turn == 'lower' and utils.get_coords(pos)[1] == const.BOARD_SIZE - 1)): return False x, y = utils.get_coords(pos) for j in range(const.BOARD_SIZE): if isinstance(self.board[x][j], Pawn) and self.board[x][j].team == player_turn: return False board_obj = deepcopy(self) board_obj.drop_piece(player_turn, piece_name, pos) other_player = utils.get_other_player(player_turn) if board_obj.king_in_check( other_player) and not find_available_moves( board_obj, other_player): return False # Only drop pieces in empty spaces if self.get_piece_at_pos(pos) == '__' or self.get_piece_at_pos( pos).team == player_turn: if player_turn == 'UPPER': for i in range(len(self.upper_captures)): if self.upper_captures[i].lower() == piece_name.lower(): return True elif player_turn == 'lower': for i in range(len(self.lower_captures)): if self.lower_captures[i] == piece_name: return True return False