def __init__(self): self._board = Reversi.Board(10) self._mycolor = None self._opening_book = OpeningBook.OpeningBook() self._OB_active = True self._move_history = [] self._hash_table = TranspositionTable() self._table_usage = 0
def main(self): chances = [ 1, .9, .8, .7, .6, .5, .4, .35, .33, .30, .27, .24, .22, .20, .18, .16, .15, .14, .13, .12, .11 ] board = Board() win = GraphWin('board', 500, 500) win.setCoords(0.0, 0.0, 8.0, 8.0) win.setBackground("green") # Draw tile on board def placepiece(player, x, y, radius=0.5): if player is 1: color = "white" else: color = "black" circle = Circle(Point(x, y), radius) circle.setFill(color) circle.draw(win) # draw grid for i in range(1, 8): line = Line(Point(i, 0), Point(i, 8)) line.draw(win) line = Line(Point(0, i), Point(8, i)) line.draw(win) # draw grid decorations decorations = (("black", 2, 2), ("black", 6, 2), ("black", 2, 6), ("black", 6, 6)) for color, x, y in decorations: placepiece(color, x, y, 0.05) # draw pieces pieces = ((0, 4.5, 4.5), (0, 3.5, 3.5), (1, 3.5, 4.5), (1, 4.5, 3.5)) for color, x, y in pieces: placepiece(color, x, y) p1 = Player2(2, True) # Black p2 = Player2(3, False) # White ZH = ZobristHash(board.board) TT = TranspositionTable() while (True): piece = board.numMoves % 2 if (piece == 0): move = p1.findMove(board, TT, ZH) else: move = p2.findMove(board, TT, ZH) row = move[0] column = move[1] valid = board.isValidMove(row, column, piece) if (valid is False): continue board.makeMove(row, column) placepiece(piece, column + .5, row + .5) randNum = random.random() chance = chances[len(valid) - 1] if randNum <= chance: for tup in valid: board.board[tup[0]][tup[1]] = piece placepiece(piece, tup[1] + .5, tup[0] + .5) ZH.hash = ZH.modifyHash(ZH.hash, piece, valid, [move]) else: ZH.hash = ZH.modifyHash(ZH.hash, piece, [], [move]) message = Text(Point(4, 4), "Tiles not flipped!") message.setTextColor("red") message.setSize(21) message.draw(win) #TODO time.sleep(1.5) message.undraw() hasValid0 = board.hasValidMove(0) hasValid1 = board.hasValidMove(1) background = Rectangle(Point(1.5, 2.5), Point(6.5, 5.5)) if (hasValid0 is False and hasValid1 is False): # Game over score = board.getScore() if score[0] > score[1]: message = Text(Point(4, 3.5), "Black Wins!") background.setFill("black") background.setOutline("white") elif score[1] > score[0]: message = Text(Point(4, 3.5), "White Wins!") background.setFill("white") background.setOutline("black") else: message = Text(Point(4, 3.5), "Tie Game!") background.setFill("gray") background.setOutline("gray") scores = Text( Point(4, 4.5), "Black: " + str(score[0]) + "\nWhite: " + str(score[1])) message.setTextColor("red") scores.setTextColor("red") scores.setSize(21) message.setSize(30) background.draw(win) message.draw(win) scores.draw(win) win.getMouse() break elif (hasValid0 is False and board.numMoves % 2 is 0): # No moves for black board.numMoves += 1 message = Text(Point(4, 4), "Black has no moves,\nturn skipped") message.setTextColor("red") message.setSize(21) background.setFill("black") background.setOutline("white") background.draw(win) message.draw(win) #TODO time.sleep(3) message.undraw() background.undraw() elif (hasValid1 is False and board.numMoves % 2 is 1): # No moves for white board.numMoves += 1 message = Text(Point(4, 4), "White has no moves,\nturn skipped") message.setTextColor("red") message.setSize(21) background.setFill("white") background.setOutline("black") background.draw(win) message.draw(win) #TODO time.sleep(3) message.undraw() background.undraw() win.close()
class processPlayerV2(PlayerInterface): def __init__(self): self._board = Reversi.Board(10) self._mycolor = None self._opening_book = OpeningBook.OpeningBook() self._OB_active = True self._move_history = [] self._hash_table = TranspositionTable() self._table_usage = 0 def getPlayerName(self): return "Entei" def getPlayerMove(self): if self._board.is_game_over(): print("Referee told me to play but the game is over!") return (-1, -1) # Compute player move move = self._play() self._board.push(move) print("I am playing ", move) (c, x, y) = move assert (c == self._mycolor) print("My current board :") print(self._board) self._move_history.append(move) # Add player's move to history return (x, y) def playOpponentMove(self, x, y): assert (self._board.is_valid_move(self._opponent, x, y)) print("Opponent played ", (x, y)) self._move_history.append([self._opponent, x, y]) # Add opponent's move to history self._board.push([self._opponent, x, y]) def newGame(self, color): self._mycolor = color self._opponent = 1 if color == 2 else 2 self._opening_book.init(self._board.get_board_size()) def endGame(self, winner): if self._mycolor == winner: print("I won!!!") else: print("I lost :(!!") print("Used table %d times" % self._table_usage) def _play(self): # Killer move detection # # Corner max_value = -sys.maxsize - 1 best_move = None corners = [[0, 0], [0, self._board.get_board_size() - 1], [self._board.get_board_size() - 1, 0], [ self._board.get_board_size() - 1, self._board.get_board_size() - 1 ]] for m in self._board.legal_moves(): self._board.push(m) (_, x, y) = m if [x, y] in corners: max_value = max(max_value, EvaluatorPBS.eval(self._board, self._mycolor)) best_move = m self._board.pop() if best_move is not None: return best_move # # Blocking move max_value = -sys.maxsize - 1 best_move = None for m in self._board.legal_moves(): self._board.push(m) if not self._board.at_least_one_legal_move(self._opponent): max_value = max(max_value, EvaluatorPBS.eval(self._board, self._mycolor)) best_move = m self._board.pop() if best_move is not None: return best_move # Opening move if self._OB_active: move = self._opening_book.get_following_move(self._move_history) if move is not None: return move # Else self._OB_active = False # minimax return self._start_negamax(3) def _get_result(self): (nb_whites, nb_blacks) = self._board.get_nb_pieces() if nb_whites > nb_blacks: return 1000 if self._mycolor == 1 else -1000 elif nb_blacks > nb_whites: return 1000 if self._mycolor == 2 else -1000 else: return 0 def _start_negamax(self, depth): if self._board.is_game_over(): return None maxx = -sys.maxsize - 1 best_move = None queue = multiprocessing.Queue() threads = [] cpt = 0 for m in self._board.legal_moves(): self._board.push(m) # value = -self._negamax(depth - 1, self._opponent, -sys.maxsize - 1, sys.maxsize) b = copy.deepcopy(self._board) process = multiprocessing.Process( target=self._negaThread, args=(b, (depth - 1), self._opponent, (-sys.maxsize - 1), sys.maxsize, queue, m, cpt)) threads.append(process) threads[cpt].start() cpt += 1 self._board.pop() for i in range(len(self._board.legal_moves())): # Wait for all threads threads[i].join() # Search for the best move (value, m) = queue.get() if value > maxx: maxx = value best_move = m return best_move def _negaThread(self, board, depth, player, alpha, beta, queue, move, num): value = -self._negamax(board, depth, player, alpha, beta) queue.put([value, move]) def _negamax(self, board, depth, player, alpha, beta): alpha_origin = alpha self._table_usage += 1 # Transposition table lookup current_hash = self._get_board_hash(board) tt_entry = self._hash_table.get_table_entry(current_hash) # Check in table whether or not we have to compute the best move if tt_entry is not None and tt_entry.depth >= depth: if tt_entry.flag == self._hash_table._EXACT: return tt_entry.value elif tt_entry.flag == self._hash_table._LOWERBOUND: alpha = max(alpha, tt_entry.value) else: # tt_entry.flag == self._hash_table._UPPERBOUND: beta = min(beta, tt_entry.value) if alpha >= beta: return tt_entry.value self._table_usage -= 1 # If game is over or depth limit reached if depth == 0 or board.is_game_over(): return EvaluatorPBS.eval( board, self._mycolor) * (-1 if player != self._mycolor else 1) color = board._flip(player) # If player cannot move, opponent turn if not board.at_least_one_legal_move(player): return -self._negamax(board, depth - 1, color, -beta, -alpha) value = -sys.maxsize - 1 for m in board.legal_moves(): board.push(m) value = max(value, -self._negamax(board, depth - 1, color, -beta, -alpha)) board.pop() alpha = max(alpha, value) if alpha >= beta: break # Cutoff # Store in transposition table tt_entry = TableEntry() tt_entry.value = value if value <= alpha_origin: tt_entry.flag = self._hash_table._UPPERBOUND elif value >= beta: tt_entry.flag = self._hash_table._LOWERBOUND else: tt_entry.flag = self._hash_table._EXACT tt_entry.depth = depth lock.acquire() self._hash_table.store(current_hash, tt_entry) lock.release() return value @staticmethod def _get_board_hash(board): return hash(tuple([tuple(c) for c in board._board]))
level_name = "level2.txt" cwd = os.getcwd() path = os.path.join(cwd, "level", level_name) level = open(path, "r").read() game_map = GameMap.Map(level) game_map.mapProduction() game_map.mapPrinting() start = time.time() assignment = AssignmentAlgorithms.AssignmentAlgorithms( game_map.width, game_map.height, game_map.getTargetsArray(), game_map.getClearedMap()) # states = StateTree.StateTree(game_map.getBoxArray(), game_map.getPlayerPosition(), assignment) table = TranspositionTable.TranspositionTable(game_map.width, game_map.height, game_map.getBoxCount()) table.insert(game_map.getBoxArray(), game_map.getPlayerPosition()) root = Node(game_map.getBoxArray(), game_map.getPlayerPosition(), None, None, assignment.greedyAssignment(game_map.getBoxArray())) execution = Execution(table, game_map) end = time.time() print("Preparation time: ", end - start) start = time.time() solution = execution.execute(root) end = time.time() print("Execution time: ", end - start) result = [] res = ""