def minimax(board, depth, maximizingPlayer, alpha=None, beta=None): status = board.check_status(False) if status is not None: return board.score[status] if maximizingPlayer: value = -math.inf moves = board.get_available_moves() for move in moves: board.board[move[0]][move[1]] = game.Node(None, board.players[0]) value = max(value, minimax(board, depth + 1, False, alpha, beta)) board.board[move[0]][move[1]] = None alpha = max(alpha, value) if beta <= alpha: break # Beta cut-off return value - depth # Substract depth for shorter path moves else: value = math.inf moves = board.get_available_moves() for move in moves: board.board[move[0]][move[1]] = game.Node(None, board.players[1]) value = min(value, minimax(board, depth + 1, True, alpha, beta)) board.board[move[0]][move[1]] = None beta = min(beta, value) if beta <= alpha: break # Alpha cut-off return value + depth # Substract depth for shorter path moves
def bestMove(board): bestScore = -math.inf next_move = None moves = board.get_available_moves() for move in moves: board.board[move[0]][move[1]] = game.Node(None, board.players[0]) score = minimax(board, 0, False, -math.inf, math.inf) board.board[move[0]][move[1]] = None if score > bestScore: bestScore = score next_move = move board.play(board.players[0], next_move)
def recreateGameDaemon(self, gameBinary=None, extraArgs=[]): """ Recreates and resyncs from scratch the game daemon. This can optionally set a different binary and extra args for it as well. """ if gameBinary is None: gameBinary = self.args.game_daemon self.log.info("Recreating game daemon with binary %s..." % gameBinary) self.stopGameDaemon() self.gamenode = game.Node(self.basedir, self.basePort + 3, gameBinary) self.startGameDaemon(extraArgs=extraArgs) self.log.info("Restarted fresh game daemon")
def createGameNode(self, gameBinary=None): """ Creates a Game instance with the configuration of this test case (optionally overriding the GSP binary with the given one). This is used internally and should not be called from tests themselves. """ if gameBinary is None: gameBinary = self.args.game_daemon gameCmd = list(self.runGameWith) gameCmd.append(gameBinary) return game.Node(self.basedir, self.basePort + 3, gameCmd)
def main(self): """ Executes the testcase, including setup and cleanup. """ randomSuffix = "%08x" % random.getrandbits(32) self.basedir = os.path.join(self.args.dir, DIR_PREFIX + randomSuffix) shutil.rmtree(self.basedir, ignore_errors=True) os.mkdir(self.basedir) logfile = os.path.join(self.basedir, "xayagametest.log") logHandler = logging.FileHandler(logfile) logFmt = "%(asctime)s %(name)s (%(levelname)s): %(message)s" logHandler.setFormatter(logging.Formatter(logFmt)) rootLogger = logging.getLogger() rootLogger.setLevel(logging.INFO) rootLogger.addHandler(logHandler) self.log = logging.getLogger("xayagametest.testcase") mainHandler = logging.StreamHandler(sys.stderr) mainHandler.setFormatter(logging.Formatter("%(message)s")) self.mainLogger = logging.getLogger("main") self.mainLogger.addHandler(logHandler) self.mainLogger.addHandler(mainHandler) self.mainLogger.info("Base directory for integration test: %s" % self.basedir) self.basePort = random.randint(1024, 30000) self.log.info("Using port range %d..%d, hopefully it is free" % (self.basePort, self.basePort + 3)) zmqPorts = { "blocks": self.basePort + 1, } if self.zmqPending == "none": self.log.info("Disabling ZMQ for pending moves in Xaya Core") elif self.zmqPending == "one socket": self.log.info( "Pending moves are sent on the same socket as blocks") zmqPorts["pending"] = zmqPorts["blocks"] elif self.zmqPending == "two sockets": self.log.info( "Pending moves are sent on a different socket as blocks") zmqPorts["pending"] = self.basePort + 2 assert zmqPorts["pending"] != zmqPorts["blocks"] else: raise AssertionError("Invalid zmqPending: %s" % self.zmqPending) self.xayanode = xaya.Node(self.basedir, self.basePort, zmqPorts, self.args.xayad_binary) self.gamenode = game.Node(self.basedir, self.basePort + 3, self.args.game_daemon) class RpcHandles: xaya = None game = None self.rpc = RpcHandles() self.startXayaDaemon() cleanup = False success = False try: self.startGameDaemon() try: self.setup() self.run() self.mainLogger.info("Test succeeded") success = True if self.args.nocleanup: self.mainLogger.info("Not cleaning up logs as requested") else: cleanup = True except: self.mainLogger.exception("Test failed") self.log.info("Not cleaning up base directory %s" % self.basedir) finally: self.shutdown() self.stopGameDaemon() finally: self.stopXayaDaemon() if cleanup: self.log.info("Cleaning up base directory in %s" % self.basedir) shutil.rmtree(self.basedir, ignore_errors=True) logging.shutdown() if not success: sys.exit("Test failed")
def main(self): """ Executes the testcase, including setup and cleanup. """ randomSuffix = "%08x" % random.getrandbits(32) self.basedir = os.path.join(self.args.dir, DIR_PREFIX + randomSuffix) shutil.rmtree(self.basedir, ignore_errors=True) os.mkdir(self.basedir) logfile = os.path.join(self.basedir, "xayagametest.log") logHandler = logging.FileHandler(logfile) logFmt = "%(asctime)s %(name)s (%(levelname)s): %(message)s" logHandler.setFormatter(logging.Formatter(logFmt)) rootLogger = logging.getLogger() rootLogger.setLevel(logging.INFO) rootLogger.addHandler(logHandler) self.log = logging.getLogger("xayagametest.testcase") mainHandler = logging.StreamHandler(sys.stderr) mainHandler.setFormatter(logging.Formatter("%(message)s")) self.mainLogger = logging.getLogger("main") self.mainLogger.addHandler(logHandler) self.mainLogger.addHandler(mainHandler) self.mainLogger.info("Base directory for integration test: %s" % self.basedir) basePort = random.randint(1024, 30000) self.log.info("Using port range %d..%d, hopefully it is free" % (basePort, basePort + 2)) self.xayanode = xaya.Node(self.basedir, basePort, basePort + 1, self.args.xayad_binary) self.gamenode = game.Node(self.basedir, basePort + 2, self.args.game_daemon) class RpcHandles: xaya = None game = None self.rpc = RpcHandles() self.startXayaDaemon() cleanup = False success = False try: self.startGameDaemon() try: self.run() self.mainLogger.info("Test succeeded") success = True if self.args.nocleanup: self.mainLogger.info("Not cleaning up logs as requested") else: cleanup = True except: self.mainLogger.exception("Test failed") self.log.info("Not cleaning up base directory %s" % self.basedir) finally: self.stopGameDaemon() finally: self.stopXayaDaemon() if cleanup: self.log.info("Cleaning up base directory in %s" % self.basedir) shutil.rmtree(self.basedir, ignore_errors=True) logging.shutdown() if not success: sys.exit("Test failed")
# 6 7---8 # valid start/end nodes are 0, 2, 6, 8 } choice = '' map_string = '0---1---2\n | |\n3---4 5\n| |\n6 7---8' prompt = '> ' corners = [0, 2, 6, 8] nodes = [0, 1, 2, 3, 4, 5, 6, 7, 8] empty_board = [ game.Node(''), game.Node(''), game.Node(''), game.Node(''), game.Node(''), game.Node(''), game.Node(''), game.Node(''), game.Node('') ] tile_types = [ 'start', 'end', 'recharge', 'weak', 'weak', 'weak', 'weak', 'strong', 'strong' ]