def score_minimizer(board, player, alpha, beta) -> int: """ Minimizing Score Function """ # setup enemy = 1 - player esign = -1 if enemy else 1 score = 10000 # searching all valid nodes for idx in range(len(board)): # skip invalid moves if board[idx] * esign < 0: continue # prune immediately if game over cboard = board[:] if engine.interact_inplace(cboard, idx, enemy): return -10000 # get child score cscore = board_score(cboard, player) # update score = min(score, cscore) beta = min(beta, score) # alpha-beta pruning if alpha >= beta: return score return score
def load_scores(board, player, depth) -> list: """ Get the scores of all moves of board """ # setup alpha = -10000 psign = -1 if player else 1 score_list = [0] * len(board) # searching all nodes (conditional return inside) for idx in range(len(board)): # mark invalid moves if board[idx] * psign < 0: score_list[idx] = -20000 continue # interact with board cboard = board[:] game_over = engine.interact_inplace(cboard, idx, player) # mark winning move (no use of other scores) if game_over: score_list[idx] = 10000 return score_list # store score and update alpha score = pruned_minimizer(cboard, player, alpha, 10000, depth - 1) score_list[idx] = score alpha = max(alpha, score) return score_list
def pruned_maximizer(board, player, alpha, beta, depth) -> int: """ Maximizing Tree Search Function """ # setup score = -10000 psign = -1 if player else 1 # searching all nodes for idx in range(len(board)): # skip invalid moves if board[idx] * psign < 0: continue # prune immediately if game over cboard = board[:] if engine.interact_inplace(cboard, idx, player): return 10000 # update score and beta score = max( score, pruned_minimizer(cboard, player, alpha, beta, depth - 1) ) alpha = max(alpha, score) # alpha-beta pruning if alpha >= beta: return score return score
def expand(self): """ Construct child node from an untried action """ # select one action action = self.unvisited.pop() # perform action and get state and game over next_state = self.state[:] game_over = engine.interact_inplace(next_state, action, self.player) next_state = None if game_over else next_state # construct child node and add to children child = MCTSVisitedNode(next_state, self, action, 1 - self.player) self.children.append(child) return child
def forward_roll_once(state, player) -> tuple: """ Choose one action randomly and return next state tuple If the action leads to game over, return None and winner """ # rollout policy: random valid_moves = engine.valid_board_moves(state, player) chosen_move = random.choice(valid_moves) # interact with env next_state = state[:] game_over = engine.interact_inplace(next_state, chosen_move, player) if game_over: return (None, player) else: return (next_state, 1 - player)