def computeNextGameMoveInParallel(params: tuple): thread_index = params[0] asyncResultNodesQueue: Queue = params[1] gameState: GameState = params[2] # generate the search tree. searchTree = GameProcess.generateSearchTreeInParallel(params) # start the timer. timer = Timer().start() # algorithm # algorithm = MinMaxAlgorithm() algorithm = AlphaBetaCutAlgorithm() # extract the best node. nodeToReach: GameNode = algorithm.getMorePromisingNode( searchTree, gameState) # DebugUtils.info("[{}] >> (AlphaBetaCutAlgorithm) ended in {} seconds", [thread_index, timer.get_elapsed_time()]) # DebugUtils.info(" BEST MOVE {}",[nodeToReach.moves]) # stop the timer. timer.stop() # return nodeToReach asyncResultNodesQueue.put(nodeToReach)
def movePawnFromTo(self, starting_coord, ending_coord): # change the board moving the pawn replace = self.state[starting_coord] if replace not in {"WHITE", "BLACK", "KING"}: DebugUtils.error("I'm not taking a pawn", []) return self if starting_coord == (4, 4): self.state[starting_coord] = "THRONE" else: self.state[starting_coord] = "EMPTY" if self.state[ending_coord] == "EMPTY" or self.state[ ending_coord] == "THRONE": self.state[ending_coord] = replace else: DebugUtils.error("I'm moving a pawn on another pawn", []) # print("MovePawnFromTo: From ",starting_coord,"to: ",ending_coord,". It's a ",replace," pawn") # print(starting_coord," -> ",self.state[starting_coord],"\n",ending_coord," -> ",self.state[ending_coord],"\n")#,self.state,"\n") if replace == "KING": self.King = ending_coord if replace == "WHITE": self.WhiteList.remove(starting_coord) self.WhiteList.append(ending_coord) if replace == "BLACK": self.BlackList.remove(starting_coord) self.BlackList.append(ending_coord) return self
def __loadGameState(self, stateFromServer: dict): self.gameState = GameState() self.gameState.createFromServerState(stateFromServer) DebugUtils.info("BLACKS: {} WHITES: {} KING: {}", [ self.gameState.BlackNumber, self.gameState.WhiteNumber, self.gameState.King ])
def __showGame(self, board): B = list(board) row_str = "" OKBLUE = '\033[94m' OKCYAN = '\033[96m' OKGREEN = '\033[92m' WARNING = '\033[93m' FAIL = '\033[91m' ENDC = '\033[0m' DebugUtils.space() for i in range(9): DebugUtils.info( "{}----- ----- ----- ----- ----- ----- ----- ----- -----{}", [OKGREEN, ENDC]) row_str = "" for j in range(9): row_str += "" + OKGREEN + "| " + ENDC if B[i][j] == "WHITE": row_str += "W" elif B[i][j] == "BLACK": row_str += "" + WARNING + "B" + ENDC elif B[i][j] == "THRONE": row_str += "" + OKBLUE + "T" + ENDC elif B[i][j] == "KING": row_str += "" + FAIL + "K" + ENDC else: row_str += " " row_str += "" + OKGREEN + " | " + ENDC DebugUtils.info(row_str, []) DebugUtils.info( "{}----- ----- ----- ----- ----- ----- ----- ----- -----{}", [OKGREEN, ENDC]) DebugUtils.space()
def __initialize(self): self.__connect() DebugUtils.info("connection with server estabilished.", []) self.__send_raw(CONFIGS._PLAYER_NAME) DebugUtils.info("name sent successfully.", []) # initial_state = self.read_json() return initial_state
def start(self): DebugUtils.space() initial_state = self.SocketManager.initialize() # try to play (if I'm the white player ...). self.play(initial_state) while not self.__is_finished(): self.SocketManager.listen(self)
def __listen(self, gameInstance): DebugUtils.info("Socket: listening ...", []) # while self.__is_connected(): message = self.read_json() gameInstance.play(message) # DebugUtils.info("Socket: disconnecting ...", []) self.__disconnect()
def __handler(self, callback: callable): try: return callback() except ConnectionRefusedError as e: DebugUtils.error("ConnectionRefusedError -> {}", [str(e)]) self.__disconnect() except Exception as e: DebugUtils.error("Exception -> {}", [str(e)]) self.__disconnect()
def __parse_args(): parser = argparse.ArgumentParser(description='Fpm AI Tablut Player') parser.add_argument( '--role', dest='role', choices={CONFIGS._PLAYER_ROLE_BLACK_ID, CONFIGS._PLAYER_ROLE_WHITE_ID}, help='player role' ) parser.add_argument( '--timeout', dest='timeout', action='store', help='move timeout', default=CONFIGS.GAME_MOVE_TIMEOUT ) parser.add_argument( '--server', dest='server', action='store', help='server ip address', default=CONFIGS.SERVER_HOST ) arguments = parser.parse_args() if not arguments.role: parser.print_help() sys.exit() if arguments.server: CONFIGS.SERVER_HOST = str(arguments.server) if arguments.timeout: timeout = float(arguments.timeout) if timeout >= 10: CONFIGS.GAME_MOVE_TIMEOUT = timeout else: raise Exception("Timeout argument must be at least {:} seconds".format(10)) computationTimeNotAvailablePercentage = float(CONFIGS._APP_COMPUTATION_TIME_NEEDED_PERCENTAGE) CONFIGS.GAME_TREE_GENERATION_TIMEOUT = 1 - computationTimeNotAvailablePercentage CONFIGS.GAME_TREE_GENERATION_TIMEOUT *= float(CONFIGS.GAME_MOVE_TIMEOUT) CONFIGS.APP_ROLE = str(arguments.role) if CONFIGS.APP_ROLE == CONFIGS._PLAYER_ROLE_BLACK_ID: CONFIGS.SERVER_PORT = CONFIGS._SOCKET_BLACK_PLAYER_PORT else: CONFIGS.SERVER_PORT = CONFIGS._SOCKET_WHITE_PLAYER_PORT DebugUtils.space() DebugUtils.info("ROLE = {}", [CONFIGS.APP_ROLE]) DebugUtils.info("SERVER_PORT = {}", [CONFIGS.SERVER_PORT]) DebugUtils.info("CPU_COUNT = {}", [multiprocessing.cpu_count()]) DebugUtils.space()
def assignValuefake(initialState: GameState, node: GameNode): board = [ [ "EMPTY", "BLACK", "EMPTY", "WHITE", "BLACK", "EMPTY", "EMPTY", "EMPTY", "EMPTY" ], [ "EMPTY", "EMPTY", "WHITE", "EMPTY", "BLACK", "EMPTY", "EMPTY", "EMPTY", "EMPTY" ], [ "EMPTY", "EMPTY", "EMPTY", "EMPTY", "WHITE", "EMPTY", "EMPTY", "EMPTY", "EMPTY" ], [ "BLACK", "EMPTY", "EMPTY", "EMPTY", "WHITE", "EMPTY", "EMPTY", "EMPTY", "BLACK" ], [ "EMPTY", "EMPTY", "BLACK", "KING", "THRONE", "BLACK", "EMPTY", "BLACK", "BLACK" ], [ "BLACK", "EMPTY", "EMPTY", "EMPTY", "WHITE", "WHITE", "EMPTY", "EMPTY", "BLACK" ], [ "EMPTY", "EMPTY", "EMPTY", "EMPTY", "WHITE", "EMPTY", "EMPTY", "EMPTY", "EMPTY" ], [ "EMPTY", "EMPTY", "EMPTY", "EMPTY", "BLACK", "EMPTY", "EMPTY", "EMPTY", "EMPTY" ], [ "EMPTY", "EMPTY", "EMPTY", "BLACK", "BLACK", "BLACK", "EMPTY", "EMPTY", "EMPTY" ], ] initialServerState = {"board": board, "turn": "WHITE"} node.moves = [{'from': (8, 8), 'to': (7, 8)}] initialGameState = GameState().createFromServerState( initialServerState) currentState = GameState().createFromMoves(initialGameState, node.moves) CustomHeuristic.__showGame(currentState.state) currentState.turn = "white" value = CustomHeuristic.__computeForWhite(currentState, node) DebugUtils.info("HEURISTIC VALUE: {}", [value])
def getMorePromisingNode(self, tree_with_heuristics: GameTree, initialState: GameState) -> GameNode: root = tree_with_heuristics.root children = GameTree.getChildren(tree_with_heuristics.graph, root, False) if len(children) == 0: return None self.__elaborateNodeValues(tree_with_heuristics, initialState) bestNode = None heuristicValue = None #DebugUtils.info(" This root has {} children",[len(children)]) DebugUtils.info("MinMaxAlogorithm", []) for node in children: DebugUtils.info(" next possible move {} value {}", [str(node.moves), node.heuristic]) if heuristicValue is None: heuristicValue = node.heuristic bestNode = node elif root.turn == self.max and node.heuristic > heuristicValue: heuristicValue = node.heuristic bestNode = node elif root.turn == self.min and node.heuristic < heuristicValue: heuristicValue = node.heuristic bestNode = node DebugUtils.info(" Best move is {}", [str(bestNode.moves)]) DebugUtils.space() return bestNode
def __elaborateNodeValues(self, tree_with_heuristics: GameTree, initialState: GameState): node = tree_with_heuristics.root L = [node] # Log=[0] while len(L) > 0: x = L[-1] if x == node and x.heuristic is not None: #DebugUtils.info("last node I have finished",[]) L.pop() # Log.pop() elif x.heuristic is not None: #DebugUtils.info("current node has a value",[]) alpha = None beta = None if x.parent.turn == self.min: # parent is min node #DebugUtils.info(" parent is a min node => status",[]) beta = x.parent.heuristic if (beta is None) or (x.heuristic < beta): beta = x.heuristic # beta o la prima volta che vine ne inizializzato o trova un volore migliore if x.parent.parent is not None: alpha = x.parent.parent.heuristic #DebugUtils.info(" alpha: {} beta: {}",[alpha,beta]) x.parent.heuristic = beta if alpha is not None and alpha >= beta: #DebugUtils.info("parent is min => cancello a partire da {}",[(x.debugIndex+1)]) if len(L) <= x.parent.numberChildren: DebugUtils.info("MIN CASE L {} CHILDREN {}", [len(L), x.parent.numberChildren]) while x.parent.numberChildren > 0: # remove all x.parent children L.pop() # Log.pop() x.parent.numberChildren -= 1 else: # if len(L)<= x.parent.numberChildren: # DebugUtils.info("MIN POP FUORI DAL WHILE L {} CH {}",[len(L),x.parent.numberChildren]) x.parent.numberChildren -= 1 L.pop() # Log.pop() ################################################################## else: # parent is a max node #DebugUtils.info(" parent is a max node",[]) alpha = x.parent.heuristic if (alpha is None) or (x.heuristic > alpha): alpha = x.heuristic # alpha o la prima volta che vine ne inizializzato o trova un volore migliore if x.parent.parent is not None: beta = x.parent.parent.heuristic #DebugUtils.info(" alpha: {} beta: {}",[alpha,beta]) x.parent.heuristic = alpha if beta is not None and alpha >= beta: #DebugUtils.info("parent is max => cancello a partire da {}",[x.debugIndex]) if len(L) <= x.parent.numberChildren: DebugUtils.info("MAX CASE L {} CHILDREN {}", [len(L), x.parent.numberChildren]) while x.parent.numberChildren > 0: # remove all x.parent children L.pop() x.parent.numberChildren -= 1 else: # if len(L)<= x.parent.numberChildren: # DebugUtils.info("MAX POP FUORI DAL WHILE L {} CH {}",[len(L),x.parent.numberChildren]) x.parent.numberChildren -= 1 L.pop() # Log.pop() ################################################################## else: #DebugUtils.info("non terminal node => adding children",[]) children = GameTree.getChildren(tree_with_heuristics.graph, x, True) x.numberChildren = len(children) if len(children) > 0: L = L + children # for child in children: # Log=Log +[child.debugIndex] else: # leaf without heurisitc CustomHeuristic.assignValue(initialState, x)
def getTheMostNear(self, point_coord) -> object: # return, giving a real pawn coordinate, the first (x,y) in each # direction where he can't go PointList = self.isPoint(point_coord) if PointList == False: # print("The point considered: ",point_coord," is not a pawn") DebugUtils.error("The point considered: {} is not a pawn", [point_coord]) return False else: PointList = PointList + THRONE_CELLS if point_coord not in CAMP_CELLS: # the black paws in the camp can move in the camp tull they are in the camp PointList = PointList + CAMP_CELLS ovest, est, nord, sud = 100, 100, 100, 100 x = point_coord[0] y = point_coord[1] nord_coord, sud_coord, est_coord, ovest_coord = None, None, None, None for e in PointList: if e[0] == x and e[1] != y: # se la x uguale e non la y sono tutti i punti sulla x diversi da se stesso # DebugUtils.info("point_coord: {} una pedina sull'asse x: {} è uguale la x",[(x,y),e]) if e[1] < y: # punto sulla x prima di coord ovest_find = y - e[1] ovest = (min(ovest, ovest_find)) if e[1] > y: est_find = e[1] - y est = (min(est, est_find)) if e[1] == y and e[0] != x: # se la x uguale e non la x sono tutti i punti sulla x diversi da se stesso # DebugUtils.info("point_coord: {} una pedina sull'asse y: {} è uguale la y",[(x,y),e]) if e[0] < x: # punto sulla x prima di coord nord_find = x - e[0] nord = (min(nord, nord_find)) if e[0] > x: sud_find = e[0] - x sud = (min(sud, sud_find)) if nord == 100: nord = -1 nord_coord = (-1, y) else: nord_coord = (x - nord, y) if est == 100: est = -1 est_coord = (x, 9) else: est_coord = (x, y + est) if sud == 100: sud = -1 sud_coord = (9, y) else: sud_coord = (sud + x, y) if ovest == 100: ovest = -1 ovest_coord = (x, -1) else: ovest_coord = (x, y - ovest) # DebugUtils.info("\nDISTANZE: -> NORD: {} SUD: {} OVEST: {} EST: {}",[nord,sud,ovest,est]) # DebugUtils.info("TUPLA POS : ->NORD: {} SUD: {} OVEST: {} EST: {}\n",[nord_coord,sud_coord,ovest_coord,est_coord]) point = { "point_coord": (x, y), "est": est_coord, # massima distanza percorribile "ovest": ovest_coord, # massima distanza percorribile "nord": nord_coord, # massima distanza percorribile "sud": sud_coord, # massima distanza percorribile} } point_dist = { "point_coord": (x, y), "est": est, # massima distanza percorribile "ovest": ovest, # massima distanza percorribile "nord": nord, # massima distanza percorribile "sud": sud, # massima distanza percorribile} } return point, point_dist return None
def __computeKill(self, move): self.FinalDeaths = [] # print("computekill: ",self.turn.upper()," turn") starting_coord = move["from"] ending_coord = move["to"] self.movePawnFromTo(starting_coord, ending_coord) # print("\ndopo che mi sono mosso\n",self.state) if self.__get_color_of_pawn_at(ending_coord) != self.turn.lower(): # TODO: [@contimatteo] why this ? DebugUtils.error("Error on moving a pawn of the enemy lead", []) # TODO: [@contimatteo -> @primiano] why the code below will raise an error ? return self enemy = self.__enemy(self.turn) # print("computekill change turn : ",self.turn.upper()," turn") dic = self.getDist1(ending_coord) # print("dic ->",dic) DictOfNeighbour = dic[0] DictOfNeighbourDist = dic[1] # if ending_coord==DictOfNeighbourDist["point_coord"]: # print("it's working") CanBeKilled = [] if DictOfNeighbourDist["nord"] == 1 and self.state[( DictOfNeighbour["nord"])] in enemy: CanBeKilled.append(DictOfNeighbour["nord"]) if DictOfNeighbourDist["sud"] == 1 and self.state[( DictOfNeighbour["sud"])] in enemy: CanBeKilled.append(DictOfNeighbour["sud"]) if DictOfNeighbourDist["ovest"] == 1 and self.state[( DictOfNeighbour["ovest"])] in enemy: CanBeKilled.append(DictOfNeighbour["ovest"]) if DictOfNeighbourDist["est"] == 1 and self.state[( DictOfNeighbour["est"])] in enemy: CanBeKilled.append(DictOfNeighbour["est"]) # print("\nnord of ending_coord -> ",self.state[(DictOfNeighbour["nord"])],"\nsud of ending_coord -> ",self.state[(DictOfNeighbour["sud"])],"\novest of ending_coord -> ",self.state[(DictOfNeighbour["ovest"])],"\nest of ending_coord -> ",self.state[(DictOfNeighbour["est"])]) killed_nord, killed_est, killed_ovest, killed_sud = [], [], [], [] # print("befor killing ",killed_nord,killed_est,killed_ovest,killed_sud) for e in CanBeKilled: # nemici nell'intorno di distanza 1 # print("\nfrom: ",ending_coord,"CanBeKilled List: ",e) # check if e die if ending_coord[0] == e[0]: # x # print("initial coordingate x",ending_coord,"pawn to check kill",e) if e[1] > ending_coord[1]: # print("est initial coordingate x:",ending_coord," -> ",e,"\n") killed_est = self.__killed(e, enemy, "est") else: # print("ovest initial coordingate x:",ending_coord," -> ",e,"\n") killed_ovest = self.__killed(e, enemy, "ovest") elif ending_coord[1] == e[1]: # nord sud # print("initial coordingate y:nord or sud:",ending_coord,"pawn to check kill",e) if e[0] > ending_coord[0]: # print("sud initial coordingate y:",ending_coord," -> ",e,"\n") killed_sud = self.__killed(e, enemy, "sud") else: # print("nord initial coordingate y:",ending_coord," -> ",e,"\n") killed_nord = self.__killed(e, enemy, "nord") # print("after killing",killed_nord,killed_est,killed_ovest,killed_sud) FinalDeaths = killed_nord + killed_est + killed_ovest + killed_sud self.changeTurn() self.FinalDeaths = FinalDeaths # print("FINALDEATH: ",self.FinalDeaths) # print("\ndopo che ho ucciso\n",self.state,"\n") return self
def __killed(self, coord, pawn_color, pos) -> list: if self.state[coord] in pawn_color: # {"WHITE,"KING"} {"BLACK"} MustBeKilled = [] pawn_considered = self.state[coord] if pawn_considered == "KING" and coord == (4, 4): King = coord dic = self.getDist1(coord)[0] nord = [self.state[(dic["nord"])]] est = [self.state[(dic["est"])]] ovest = [self.state[(dic["ovest"])]] sud = [self.state[(dic["sud"])]] list_King = [] list_King = nord + est + ovest + sud count = 0 for e in list_King: if e == "BLACK": count = count + 1 if count == 4: self.deletePawn(coord) MustBeKilled.append(King) elif pawn_considered == "KING" and coord in {(4, 3), (3, 4), (4, 5), (5, 4)}: King = coord dic = self.getDist1(coord)[0] nord = [self.state[(dic["nord"])]] est = [self.state[(dic["est"])]] ovest = [self.state[(dic["ovest"])]] sud = [self.state[(dic["sud"])]] list_King = [] list_King = nord + est + ovest + sud count = 0 for e in list_King: if e == "BLACK": count = count + 1 if count == 3: self.deletePawn(coord) MustBeKilled.append(King) else: if pos == "est" and coord[1] + 1 < 9: on_the_opposite_side = self.state[(coord[0], coord[1] + 1)] enemy = self.__enemy(pawn_considered) # print("\ton the opposite side",(coord[0],coord[1]+1)," -> ",on_the_opposite_side,". His enemy is ",enemy) if (on_the_opposite_side in enemy) or ( (coord[0], coord[1] + 1) in THRONE_CELLS + CAMP_CELLS): self.deletePawn(coord) MustBeKilled.append(coord) if pos == "ovest" and coord[1] - 1 > -1: on_the_opposite_side = self.state[(coord[0], coord[1] - 1)] enemy = self.__enemy(pawn_considered) # print("\ton the opposite side",(coord[0],coord[1]-1)," -> ",on_the_opposite_side,". His enemy is ",enemy) if (on_the_opposite_side in enemy) or ( (coord[0], coord[1] - 1) in THRONE_CELLS + CAMP_CELLS): self.deletePawn(coord) MustBeKilled.append(coord) if pos == "nord" and coord[0] - 1 < -1: on_the_opposite_side = self.state[(coord[0] - 1, coord[1])] enemy = self.__enemy(pawn_considered) # print("\ton the opposite side",(coord[0]-1,coord[1])," -> ",on_the_opposite_side,". His enemy is ",enemy) if (on_the_opposite_side in enemy) or ( (coord[0] - 1, coord[1]) in THRONE_CELLS + CAMP_CELLS): self.deletePawn(coord) MustBeKilled.append(coord) if pos == "sud" and coord[0] + 1 < 9: on_the_opposite_side = self.state[(coord[0] + 1, coord[1])] enemy = self.__enemy(pawn_considered) # print("\ton the opposite side",(coord[0]+1,coord[1])," -> ",on_the_opposite_side,". His enemy is ",enemy) if (on_the_opposite_side in enemy) or ( (coord[0] + 1, coord[1]) in THRONE_CELLS + CAMP_CELLS): self.deletePawn(coord) MustBeKilled.append(coord) return MustBeKilled else: DebugUtils.error("Killed error", []) return []
def __getMoveFromCoord(self, point_coord) -> object: # giving a real coordinate, return the list of possible (x,y) where the pawn can go ListOfReachableCoord = [] ListOfReachableCoordFinal = [] DictOfNeighbour = self.getTheMostNear(point_coord)[0] if DictOfNeighbour: point_coord = DictOfNeighbour["point_coord"] # print("getMoveFromCoord: point_coord -> ",point_coord) for key in DictOfNeighbour: value = DictOfNeighbour[key] # print(key, '->', value) if key != "point_coord": if value is not None: if key == "sud": #print(key, '->',value)# for i in range(point_coord[0] + 1, value[0]): # print("\ti: ",i," -> ", (i,value[1])) ListOfReachableCoord.append(("s", i, value[1])) ListOfReachableCoordFinal.append({ 'from': point_coord, 'to': (i, value[1]) }) if key == "nord": # print(key, '->',value) for i in range(value[0] + 1, point_coord[0]): # print("\ti",i," -> ", (i,value[1])) ListOfReachableCoord.append(("n", i, value[1])) ListOfReachableCoordFinal.append({ 'from': point_coord, 'to': (i, value[1]) }) if key == "est": # print(key, '->',value) for i in range(point_coord[1] + 1, value[1]): # print("\ti",i," -> ", (value[0],i)) ListOfReachableCoord.append(("e", value[0], i)) ListOfReachableCoordFinal.append({ 'from': point_coord, 'to': (value[0], i) }) if key == "ovest": # print(key, '->',value) for i in range(value[1] + 1, point_coord[1]): # print("\ti",i," -> ", (value[0],i)) ListOfReachableCoord.append(("o", value[0], i)) ListOfReachableCoordFinal.append({ 'from': point_coord, 'to': (value[0], i) }) # print("\nLista -->: ",ListOfReachableCoord) # print("Lista -->: ",ListOfReachableCoordFinal,"\n") return ListOfReachableCoordFinal DebugUtils.error( "(GameState): '.getMostNear' probably the point_considered is EMPTY", []) return []
def generateSearchTreeInParallel(params: tuple) -> GameTree: thread_index = params[0] gameState: GameState = params[2] # currentTurn = GameUtils.turnToString(CONFIGS.APP_ROLE) nodes_generated_counter = 0 # create the root node rootNode = GameNode().initialize(None, currentTurn, [], 0) # create the tree. searchTree = GameTree().initialize(rootNode) # prepare the queue for visiting the nodes. nodesToVisit: [GameNode] = [rootNode] # start the timer. timer: Timer = Timer().start() # start visiting the tree with a BFS search. while nodesToVisit: currentGameState: GameState = None currentRootNode: GameNode = nodesToVisit.pop(0) # # check if the time for generating the tree is not expired. time_left = timer.get_time_left( CONFIGS.GAME_TREE_GENERATION_TIMEOUT) if time_left <= 0: DebugUtils.info("[{}] >> (TreeGeneration) timeout emitted", [thread_index]) DebugUtils.info("[{}] >> (TreeGeneration) depth = {}", [thread_index, currentRootNode.depth]) break if currentRootNode.depth > int(CONFIGS._GAME_TREE_MAX_DEPTH): DebugUtils.info("[{}] >> (TreeGeneration) max-depth reached", [thread_index]) DebugUtils.info("[{}] >> (TreeGeneration) depth = {}", [thread_index, currentRootNode.depth]) break # # try to create a {GameState} instance starting from a GameNode moves. currentGameState: GameState = None try: currentGameState = GameState().createFromMoves( gameState, currentRootNode.moves) except Exception as _: continue # get possible moves moves = currentGameState.getPossibleMoves(currentRootNode.turn) # # if {currentNode} is the root node, then filter the available moves at first level. if currentRootNode.depth == 0: moves = np.array_split(moves, THREADS_COUNT)[thread_index] # # try to the generate childrens of current node. for move in moves: nodes_generated_counter += 1 # depth = currentRootNode.depth + 1 nextTurn = GameUtils.togglTurn(currentRootNode.turn) movesToSave = list(currentRootNode.moves) + [move] # newNode = GameNode().initialize(currentRootNode, nextTurn, movesToSave, depth) # nodesToVisit.append(newNode) searchTree.addNode(currentRootNode, [newNode]) # DebugUtils.info("[{}] >> (TreeGeneration) ended in {} seconds", [thread_index, timer.get_elapsed_time()]) DebugUtils.info( "[{}] >> (TreeGeneration) number of generated nodes = {}", [thread_index, nodes_generated_counter]) # stop the timer. timer.stop() return searchTree