def point_estimation(board: SimpleGoBoard, color: int) -> int: """ a point estimation at search limit """ current_score = 0 opponent_score = 0 opponent_color = GoBoardUtil.opponent(color) for row in range(1, board.size + 1): for col in range(1, board.size + 1): c = _constrained_index_2d(board, row, col) if c == color: current_score += adjust_score(score_color[color][row][col]) elif c == opponent_color: opponent_score += adjust_score( score_color[opponent_color][row][col]) return current_score - opponent_score
def set_free_handicap(self, args): """ clear the board and set free handicap for the game Arguments --------- args[0] : str the move to handicap (e.g. B2) """ self.board.reset(self.board.size) for point in args: move = GoBoardUtil.move_to_coord(point, self.board.size) point = self.board._coord_to_point(*move) if not self.board.move(point, BLACK): self.debug_msg("Illegal Move: {}\nBoard:\n{}\n".format(move, str(self.board.get_twoD_board()))) self.respond()
def get_move(self, board, toplay): cboard = board.copy() emptyPoints = board.get_empty_points() moves = [] for p in emptyPoints: if not GoBoardUtil.filleye_filter(board, p, toplay): moves.append(p) if not moves: # pass move only, no need to simulate return None moves.append(None) # None for Pass moveWins = [] for move in moves: wins = self.simulateMove(board, cboard, move, toplay) moveWins.append(wins) #writeMoves(board, moves, moveWins, self.num_simulation) return select_best_move(board, moves, moveWins)
def simulate(self, board, toplay): """ Run a simulated game for a given starting move. """ res = game_result(board) simulation_moves = [] while (res is None): move = GoBoardUtil.generate_random_move(board, board.current_player) play_move(board, move, board.current_player) simulation_moves.append(move) res = game_result(board) for m in simulation_moves[::-1]: undo(board, m) result = 1.0 if res == toplay else 0.0 return result
def Score(self, color): board2D = GoBoardUtil.get_twoD_board(self.board) score = [[[0 for dirc in range(5)] for col in range(7)] for row in range(7)] for i in range(7): for j in range(7): if board2D[i][j] == 0: row = i col = j score = self.checkcol(color, row, col, board2D, score) score = self.checkrow(color, row, col, board2D, score) score = self.checkdig1(color, row, col, board2D, score) score = self.checkdig2(color, row, col, board2D, score) return score
def legal_moves_cmd(self, args): """ List legal moves for color args[0] in {'b','w'} """ board_color = args[0].lower() color = color_to_int(board_color) moves = GoBoardUtil.generate_legal_moves(self.board, color) gtp_moves = [] for move in moves: coords = point_to_coord(move, self.board.size) gtp_moves.append(format_point(coords)) if len(gtp_moves) > 0 and self.board.winner == None: sorted_moves = ' '.join(sort_moves_list(gtp_moves))#.upper() self.respond(sorted_moves) else: self.respond()
def move(self, point, color): """ Play a move on the board. Arguments: point Return: color """ move_inspection, msg = self._play_move(point, color) if not move_inspection: raise ValueError(msg) return False else: self.last_point.append(point) self.to_play = GoBoardUtil.opponent(color) return True
def is_eye(self, point, color): """ Check if point is a simple eye for color """ if not self._is_surrounded(point, color): return False # Eye-like shape. Check diagonals to detect false eye opp_color = GoBoardUtil.opponent(color) false_count = 0 at_edge = 0 for d in self._diag_neighbors(point): if self.board[d] == BORDER: at_edge = 1 elif self.board[d] == opp_color: false_count += 1 return false_count <= 1 - at_edge # 0 at edge, 1 in center
def generate_move_with_filter(board, use_pattern, check_selfatari): """ Arguments --------- check_selfatari: filter selfatari moves? Note that even if True, this filter only applies to pattern moves use_pattern: Use pattern policy? """ move = None if use_pattern: moves = PatternUtil.generate_pattern_moves(board) move = PatternUtil.filter_moves_and_generate(board, moves, check_selfatari) if move == None: move = GoBoardUtil.generate_random_move(board, board.current_player,True) return move
def get_move(self, board, toplay): moves = GoBoardUtil.probabilistic_policy(board, toplay) moves_with_max = [] max_prob = moves[0][1] for move, val in moves: if val == max_prob: moves_with_max.append((move, val)) else: break alphaList = [] for move, val in moves_with_max: alphaList.append((board.point_to_string(move), move)) return sorted(alphaList, key=lambda x: x[0])[0][1]
def move(self, point, color): """ Play a move on the board. Arguments: point Return: color """ move_inspection, msg = self._play_move(point, color) if not move_inspection: raise ValueError(msg) return False else: self.to_play = GoBoardUtil.opponent(color) # Assignment2 - 2.solver self.depth += 1 return True
def genmove_cmd(self, args): board_color = args[0].lower() color = GoBoardUtil.color_to_int(board_color) # Try to use the solver to solve the game perfectly winner, point = self.go_engine.solve(self.board, color) if winner == 'unknown' or winner != board_color: # If the solver cannot solve the game in 'timelimit' seconds, or toPlay is losing # then play the same move as the original Go2 super().genmove_cmd(args) else: if point == None or point == 'pass': self.respond("pass") return self.board.move(point, color) self.debug_msg("Move: {}\nBoard: \n{}\n".format(point, str(self.board.get_twoD_board()))) board_move = self._point_to_move(point) self.respond(board_move)
def negamaxBoolean(self): if self.get_winner() != None: return False, None empty_points = self.get_empty_positions(self.to_play) legal_moves = [] for point in empty_points: if self.check_legal(point, self.to_play): legal_moves.append(point) for m in legal_moves: self.board[m] = self.to_play self.to_play = GoBoardUtil.opponent(self.to_play) fail, move = self.negamaxBoolean() success = not fail self.board[m] = EMPTY if success: return True, m return False, -100
def get_move(self, board, color): """ Run one-ply MC simulations to get a move to play. """ cboard = board.copy() emptyPoints = board.get_empty_points() moves = GoBoardUtil.generate_legal_moves(cboard, color) if not moves: return None moves.append(None) best = None if self.move_selection == UCB: C = 0.4 # sqrt(2) is safe, this is more aggressive best = run_ucb(self, cboard, C, moves, color) elif self.move_selection == ROUND_ROBIN: best = round_robin(self, cboard, moves, color) return best
def update_dir(board: SimpleGoBoard, row, col, direction): current = _constrained_index_2d(board, row, col) m = coord_to_point(row, col, board.size) if current == EMPTY: board.board[m] = WHITE score_color[WHITE][row][col] = evaluate_point_dir( board, row, col, WHITE, direction) board.board[m] = BLACK score_color[BLACK][row][col] = evaluate_point_dir( board, row, col, BLACK, direction) board.board[m] = EMPTY elif current == BLACK or current == WHITE: oppponent = GoBoardUtil.opponent(current) score_color[current][row][col] = evaluate_point_dir( board, row, col, current, direction) score_color[oppponent][row][col] = 0 return
def play_move(self, point, color): """ Play a move of color on point Returns boolean: whether move was legal """ assert is_black_white(color) # Special cases ''' if point == PASS: self.ko_recapture = None self.current_player = GoBoardUtil.opponent(color) return True ''' if self.board[point] != EMPTY: return False ''' if point == self.ko_recapture: return False ''' # General case: deal with captures, suicide, and next ko point ''' oppColor = GoBoardUtil.opponent(color) in_enemy_eye = self._is_surrounded(point, oppColor) ''' self.board[point] = color ''' single_captures = [] neighbors = self._neighbors(point) for nb in neighbors: if self.board[nb] == oppColor: single_capture = self._detect_and_process_capture(nb) if single_capture != None: single_captures.append(single_capture) block = self._block_of(point) if not self._has_liberty(block): # undo suicide move self.board[point] = EMPTY return False self.ko_recapture = None if in_enemy_eye and len(single_captures) == 1: self.ko_recapture = single_captures[0] ''' self.current_player = GoBoardUtil.opponent(color) return True
def alphabetaDL(state, alpha, beta, depth, color): pt = None win = None check_end = state.check_game_end_gomoku() if check_end[0] or depth == 0 or len(state.get_empty_points())==0: ##print(">>>game end = {}, color = {}, winner = {}".format(check_end[0],color,check_end[1])) if not check_end[0]: return state.staticallyEvaluateForToPlay(color) ,pt , 0 else: #return state.staticallyEvaluateForToPlay(color) ,pt , check_end[1] if color == check_end[1]: return state.staticallyEvaluateForToPlay(color) ,pt , -1 else: return -state.staticallyEvaluateForToPlay(color) ,pt , 1 #check_end = state.check_game_end_gomoku() #print("game end = {}".format(check_end[0])) #if check_end[0] or depth == 0: #if check_end[1] == color: return 1000,0,1 #elif check_end[1] == GoBoardUtil.opponent(color): return -1000,0,-1 #else: return 1,0,0 ##print("\n-all empty points: {}".format(state.get_empty_points())) for m in state.get_empty_points(): ##print("take move m = {}, evaluate value, m_1 and win_1".format(m)) temp_state = state.copy() temp_state.play_move_gomoku(m,color) pt = m # alternate turn value, m_1, win_1 = alphabetaDL(temp_state, -beta, -alpha, depth - 1,GoBoardUtil.opponent(color)) value = -int(value) win = win_1 ##print("value = {}, m_1 = {}, win_1 = {}".format(value,m_1,win_1)) if value > alpha: alpha = value temp_state.undoMove(m) ##print("value = {}, beta = {}, pt={}".format(value,beta,pt)) if value > beta: return beta, m_1, win_1 elif value == beta: return beta, m_1, win_1 return alpha, pt, win
def find_all_features(board): """ Find all move's features on the board """ legal_moves = GoBoardUtil.generate_legal_moves(board, board.current_player) features = {} features["PASS"] = [] for m in legal_moves: features[m] = [] Feature.find_pass_features(features, board) Feature.find_full_board_features(features, board) Feature.find_dist_prev_move_features(features, board, legal_moves) Feature.find_line_pos_features(features, board, legal_moves) for m in legal_moves: Feature.find_pattern_feature(features, board, m) return features
def genmove_cmd(self, args): """ Modify this function for Assignment 1 """ """ generate a move for color args[0] in {'b','w'} """ board_color = args[0].lower() color = color_to_int(board_color) move = self.go_engine.get_move(self.board, color) move_coord = point_to_coord(move, self.board.size) move_as_string = format_point(move_coord) if move_as_string == "PASS": # if a player can only pass according to the move generator, self.respond('resign') return if self.board.is_legal(move, color): self.board.play_move(move, color) self.respond(move_as_string) self.board.current_player = GoBoardUtil.opponent(color) else: self.respond("Illegal move: {}".format(move_as_string))
def generate_move(board, use_pattern, table): """ Arguments --------- board: GoBoard use_pattern: Use pattern policy? """ move = None if use_pattern: moves = PatternUtil.generate_pattern_moves(board, table) mvs, vals = PatternUtil.calc_probabilities(board, moves) move = np.random.choice(mvs, len(mvs), vals) if move == None: move = GoBoardUtil.generate_random_move(board, board.current_player, True) return move
def play_move_gomoku(self, point, color): """ Play a move of color on point, for the game of gomoku Returns boolean: whether move was legal """ assert is_black_white(color) assert point != PASS if self.board[point] != EMPTY: return False self.board[point] = color row, col = self._point_to_2d_coord(point) # print("play_move_gomoku: row = {}, col = {}".format(row, col)) self.twoDBoard[row][col] = color # print("twoDBoard = {}".format(self.twoDBoard)) self.moves.append((point, color)) self.current_player = GoBoardUtil.opponent(color) return True
def policy_moves_cmd(self, args): if self.go_engine.random_simulation: #get legal moves first_moves = GoBoardUtil.generate_legal_moves( self.board, self.board.current_player) moves = [] #convert points to formated for move in first_moves: #convert to coords temp = point_to_coord(move, self.board.size) #format version temp = format_point(temp) moves.append(temp) moves.sort() #reverse it new_moves = [] column_letters = "ABCDEFGHJKLMNOPQRSTUVWXYZ" #put format to point for move in moves: temp = str(column_letters.find(move[0]) + 1) temp = coord_to_point(int(move[1]), int(temp), self.board.size) new_moves.append((temp)) movelist = new_moves p = [] for x in range(0, len(movelist)): p.append(round(float(1) / float(len(movelist)), 3)) else: movelist, p = PatternUtil.pattern(self.board) result = '' for move in movelist: temp = point_to_coord(move, self.board.size) temp = format_point(temp) result += temp.lower() + " " for i in p: result += str(i) + " " try: if args[0] == "1": return movelist, p except: self.respond(result)
def move(self, point, color): """ Play a move on the board. Arguments: point Return: color """ move_inspection, msg = self._play_move(point, color) if not move_inspection: return False else: self.current_player = GoBoardUtil.opponent(color) self.last2_move = self.last_move self.last_move = point self.moves.append(point) return True
def play_move(self, point, color): """ Play a move of color on point Returns boolean: whether move was legal """ assert is_black_white(color) if self.board[point] != EMPTY: return False if color != self.current_player: return False self.board[point] = color self.current_player = GoBoardUtil.opponent(color) self.last_move = point return True
def get_move(self, board, color): """ Run one-player MC simulations to get a move to play """ color = board.current_player cboard = board.copy() if self.random_simulation: moves = GoBoardUtil.generate_legal_moves_gomoku(board) else: _, moves = PatternUtil.generate_policy_moves(board) move_wins = [] for move in moves: wins = self.simulate_move(cboard, move, color) move_wins.append(wins) return select_best_move(board, moves, move_wins)
def play_cmd(self, args): """ play a move args[1] for given color args[0] in {'b','w'} """ try: # board_color => b / w # board_move => A1 board_color = args[0].lower() board_move = args[1] if board_color != "b" and board_color != "w": self.respond( "illegal move: \"{}\" wrong color".format(board_color)) return # 1 => black; 2 => white; color = color_to_int(board_color) if args[1].lower() == 'pass': self.board.play_move(PASS, color) self.board.current_player = GoBoardUtil.opponent(color) self.respond() return # tuple (x,y) => coord coord = move_to_coord(args[1], self.board.size) if coord: # int x => move move = coord_to_point(coord[0], coord[1], self.board.size) else: self.error("Error executing move {} converted from {}".format( move, args[1])) return if not self.board.play_move_gomoku(move, color): self.respond( "illegal move: \"{}\" occupied".format(board_move)) return else: self.debug_msg("Move: {}\nBoard:\n{}\n".format( board_move, self.board2d())) self.respond() except Exception as e: self.respond('{}'.format(str(e)))
def play_move(self, point, color): """ Play a move of color on point Returns boolean: whether move was legal, string: reason for illegal move """ assert is_black_white(color) # Special cases if point == PASS: return False, "" #self.ko_recapture = None #self.current_player = GoBoardUtil.opponent(color) elif self.board[point] != EMPTY: return False, "occupied" if point == self.ko_recapture: return False # General case: deal with captures, suicide, and next ko point opp_color = GoBoardUtil.opponent(color) in_enemy_eye = self._is_surrounded(point, opp_color) self.board[point] = color single_captures = [] neighbors = self._neighbors(point) for nb in neighbors: # captures if self.board[nb] == opp_color: if self._detect_capture(nb): self.board[point] = EMPTY return False, "capture" """ single_capture = self._detect_and_process_capture(nb) # call _detect_capture, if yes, undo move and raise an error. if single_capture != None: single_captures.append(single_capture) """ block = self._block_of(point) if not self._has_liberty(block): # undo suicide move self.board[point] = EMPTY return False, "suicide" """ self.ko_recapture = None if in_enemy_eye and len(single_captures) == 1: self.ko_recapture = single_captures[0] #self.current_player = GoBoardUtil.opponent(color) """ return True, ""
def play_cmd(self, args): """ Modify this function for Assignment 1 """ """ play a move args[1] for given color args[0] in {'b','w'} """ try: board_color = args[0].lower() board_move = args[1] if board_color != 'b' and board_color != 'w': # wrong color self.respond("illegal move: \"{}\"".format(board_color + ' ' + board_move) + " wrong color") color = color_to_int(board_color) if args[1].lower() == 'pass': self.board.play_move(PASS, color) #self.board.current_player = GoBoardUtil.opponent(color) self.respond("illegal move: \"{}\"".format(board_color + ' ' + board_move) + " wrong coordinate") return coord = move_to_coord(args[1], self.board.size) if coord: move = coord_to_point(coord[0],coord[1], self.board.size) else: # wrong coordinate self.respond("illegal move: \"{}\"".format(board_color + ' ' + board_move) + " wrong coordinate") #self.error("Error executing move {} converted from {}" # .format(move, args[1])) return if not self.board.play_move(move, color): neighbors = self.board.neighbors(move) for nb in neighbors: if self.board.board[nb] == GoBoardUtil.opponent(color): if not self.board.detect_capture(nb): # detect capture self.respond("illegal move: \"{}\"".format(board_color + ' ' + board_move) + " capture") self.board.board[move] = EMPTY return if self.board.board[move] != EMPTY: # detect occupied self.respond("illegal move: \"{}\"".format(board_color + ' ' + board_move) + " occupied") return self.respond("illegal move: \"{}\"".format(board_color + ' ' + board_move) + " suicide") # detect suicide #self.respond("Illegal Move: {}".format(board_move)) return else: self.debug_msg("Move: {}\nBoard:\n{}\n". format(board_move, self.board2d())) self.respond() except Exception as e: self.respond('Error: {}'.format(str(e)))
def _do_playout(self, board, color_to_play): res = game_result(board) simulation_moves = [] while (res is None): _, candidate_moves = self.policy_moves(board, board.current_player) playout_move = random.choice(candidate_moves) play_move(board, playout_move, board.current_player) simulation_moves.append(playout_move) res = game_result(board) for m in simulation_moves[::-1]: undo(board, m) if res == color_to_play: return 1.0 elif res == 'draw': return 0.0 else: assert (res == GoBoardUtil.opponent(color_to_play)) return -1.0
def save_states(self, state, value, move): key = state.copy() self.tree_cache[key] = (value, move) # We also solved rotations of the current board state. # print(self.get_twoD_board()) rotations = [ lambda y, x: (self.rotate(y, x, pi / 2)), # rotate 90 degree clockwise lambda y, x: (self.rotate(y, x, pi)), # rotate 180 degree clockwise lambda y, x: (self.rotate(y, x, 3 * pi / 2)) # rotate 270 degree clockwise ] coord = GoBoardUtil.move_to_coord(move, self.size) for T in rotations: keyT, moveT = state.transform(T, coord) self.tree_cache[keyT] = (value, moveT)