def readCommand(argv): """ Processes the command used to run pacman from the command line. """ from optparse import OptionParser usageStr = """ USAGE: python pacman.py <options> EXAMPLES: (1) python capture.py - starts a game with two baseline agents (2) python capture.py --keys0 - starts a two-player interactive game where the arrow keys control agent 0, and all other agents are baseline agents (3) python capture.py -r baselineTeam -b myTeam - starts a fully automated game where the red team is a baseline team and blue team is myTeam """ parser = OptionParser(usageStr) parser.add_option('-r', '--red', help=default('Red team'), default='baselineTeam') parser.add_option('-b', '--blue', help=default('Blue team'), default='baselineTeam') parser.add_option('--red-name', help=default('Red team name'), default='Red') parser.add_option('--blue-name', help=default('Blue team name'), default='Blue') parser.add_option('--redOpts', help=default('Options for red team (e.g. first=keys)'), default='') parser.add_option('--blueOpts', help=default('Options for blue team (e.g. first=keys)'), default='') parser.add_option('--keys0', help='Make agent 0 (first red player) a keyboard agent', action='store_true', default=False) parser.add_option('--keys1', help='Make agent 1 (second red player) a keyboard agent', action='store_true', default=False) parser.add_option('--keys2', help='Make agent 2 (first blue player) a keyboard agent', action='store_true', default=False) parser.add_option( '--keys3', help='Make agent 3 (second blue player) a keyboard agent', action='store_true', default=False) parser.add_option( '-l', '--layout', dest='layout', help=default( 'the LAYOUT_FILE from which to load the map layout; use RANDOM for a random maze; use RANDOM<seed> to use a specified random seed, e.g., RANDOM23' ), metavar='LAYOUT_FILE', default='defaultCapture') parser.add_option('-t', '--textgraphics', action='store_true', dest='textgraphics', help='Display output as text only', default=False) parser.add_option('-q', '--quiet', action='store_true', help='Display minimal output and no graphics', default=False) parser.add_option('-Q', '--super-quiet', action='store_true', dest="super_quiet", help='Same as -q but agent output is also suppressed', default=False) parser.add_option('-z', '--zoom', type='float', dest='zoom', help=default('Zoom in the graphics'), default=1) parser.add_option('-i', '--time', type='int', dest='time', help=default('TIME limit of a game in moves'), default=1200, metavar='TIME') parser.add_option('-n', '--numGames', type='int', help=default('Number of games to play'), default=1) parser.add_option( '-f', '--fixRandomSeed', action='store_true', help='Fixes the random seed to always play the same game', default=False) parser.add_option( '--record', action='store_true', help= 'Writes game histories to a file (named by the time they were played)', default=False) parser.add_option('--replay', default=None, help='Replays a recorded game file.') parser.add_option( '-x', '--numTraining', dest='numTraining', type='int', help=default('How many episodes are training (suppresses output)'), default=0) parser.add_option('-c', '--catchExceptions', action='store_true', default=False, help='Catch exceptions and enforce time limits') options, otherjunk = parser.parse_args(argv) assert len(otherjunk) == 0, "Unrecognized options: " + str(otherjunk) args = dict() # Choose a display format #if options.pygame: # import pygameDisplay # args['display'] = pygameDisplay.PacmanGraphics() if options.textgraphics: import pacman.textDisplay as textDisplay args['display'] = textDisplay.PacmanGraphics() elif options.quiet: import pacman.textDisplay as textDisplay args['display'] = textDisplay.NullGraphics() elif options.super_quiet: import pacman.textDisplay as textDisplay args['display'] = textDisplay.NullGraphics() args['muteAgents'] = True else: import pacman.captureGraphicsDisplay as captureGraphicsDisplay # Hack for agents writing to the display captureGraphicsDisplay.FRAME_TIME = 0 args['display'] = captureGraphicsDisplay.PacmanGraphics(options.red, options.blue, options.zoom, 0, capture=True) import __main__ __main__.__dict__['_display'] = args['display'] args['redTeamName'] = options.red_name args['blueTeamName'] = options.blue_name if options.fixRandomSeed: random.seed('cs188') # Special case: recorded games don't use the runGames method or args structure if options.replay != None: # print('Replaying recorded game %s.' % options.replay) import pickle with open(options.replay, 'rb') as f: recorded = pickle.load(open(options.replay, 'rb')) recorded['display'] = args['display'] replayGame(**recorded) sys.exit(0) # Choose a pacman agent redArgs, blueArgs = parseAgentArgs(options.redOpts), parseAgentArgs( options.blueOpts) if options.numTraining > 0: redArgs['numTraining'] = options.numTraining blueArgs['numTraining'] = options.numTraining nokeyboard = options.textgraphics or options.quiet or options.numTraining > 0 redAgents = loadAgents(True, options.red, nokeyboard, redArgs) blueAgents = loadAgents(False, options.blue, nokeyboard, blueArgs) args['agents'] = sum([list(el) for el in zip(redAgents, blueAgents)], []) # list of agents numKeyboardAgents = 0 for index, val in enumerate( [options.keys0, options.keys1, options.keys2, options.keys3]): if not val: continue if numKeyboardAgents == 0: agent = keyboardAgents.KeyboardAgent(index) elif numKeyboardAgents == 1: agent = keyboardAgents.KeyboardAgent2(index) else: raise Exception('Max of two keyboard agents supported') numKeyboardAgents += 1 args['agents'][index] = agent args['layout'] = options.layout args['length'] = options.time args['numGames'] = options.numGames args['numTraining'] = options.numTraining args['record'] = options.record args['catchExceptions'] = options.catchExceptions return args
def runGames( layout, pacman, ghosts, display, numGames, record, numTraining=0, numTesting=0, catchExceptions=False, timeout=30, ): import __main__ __main__.__dict__["_display"] = display rules = ClassicGameRules(timeout) games = [] if numTraining > 0: from pacman import textDisplay gameDisplay = textDisplay.NullGraphics() rules.quiet = True pbar = trange( numTraining, desc="Training Games" if numTesting == 0 else "Testing Games" ) for i in pbar: game = rules.newGame( layout, pacman, ghosts, gameDisplay, True, catchExceptions ) game.run() if record: import time, cPickle fname = ("recorded-game-%d" % (i + 1)) + "-".join( [str(t) for t in time.localtime()[1:6]] ) f = file(fname, "w") components = {"layout": layout, "actions": game.moveHistory} cPickle.dump(components, f) f.close() gameDisplay = display rules.quiet = False for i in range(numGames - numTraining): game = rules.newGame( layout, pacman, ghosts, gameDisplay, False, catchExceptions ) game.run() games.append(game) if record: import time, cPickle fname = ("recorded-game-%d" % (i + 1)) + "-".join( [str(t) for t in time.localtime()[1:6]] ) f = file(fname, "w") components = {"layout": layout, "actions": game.moveHistory} cPickle.dump(components, f) f.close() if (numGames - numTraining) > 0: scores = [game.state.getScore() for game in games] wins = [game.state.isWin() for game in games] winRate = wins.count(True) / float(len(wins)) print("Average Score:", sum(scores) / float(len(scores))) print("Scores: ", ", ".join([str(score) for score in scores])) print("Win Rate: %d/%d (%.2f)" % (wins.count(True), len(wins), winRate)) print("Record: ", ", ".join([["Loss", "Win"][int(w)] for w in wins])) return games
def runGames(agents, display, length, numGames, record, numTraining, redTeamName, blueTeamName, muteAgents=False, catchExceptions=False, seed=None, layout='RANDOM'): if seed is not None: random.seed(seed) # Choose a layout import pacman.layout as lay layouts = [] for i in range(numGames): if layout == 'RANDOM': l = lay.Layout(randomLayout().split('\n')) elif layout.startswith('RANDOM'): l = lay.Layout(randomLayout(int(layout[6:])).split('\n')) elif layout.lower().find('capture') == -1: raise Exception('You must use a capture layout with capture.py') else: l = lay.getLayout(layout) if l == None: raise Exception("The layout " + layout + " cannot be found") layouts.append(l) rules = CaptureRules() games = [] # if numTraining > 0: # print('Playing %d training games' % numTraining) for i in range(numGames): beQuiet = i < numTraining layout = layouts[i] if beQuiet: # Suppress output and graphics import pacman.textDisplay as textDisplay gameDisplay = textDisplay.NullGraphics() rules.quiet = True else: gameDisplay = display rules.quiet = False g = rules.newGame(layout, agents, gameDisplay, length, muteAgents, catchExceptions) g.run() if not beQuiet: games.append(g) g.record = None if record: import time, pickle, datetime, json import pacman.game as game #fname = ('recorded-game-%d' % (i + 1)) + '-'.join([str(t) for t in time.localtime()[1:6]]) #f = file(fname, 'w') components = { 'layout': layout, 'agents': [game.Agent() for a in agents], 'actions': g.moveHistory, 'length': length, 'redTeamName': redTeamName, 'blueTeamName': blueTeamName } #f.close() g.record = pickle.dumps(components) replay_id = 'replays/replay-{}-{}'.format( datetime.datetime.now().strftime("%Y-%m-%d %H_%M_%S"), random.randint(0, 99999)) print(replay_id) with open(replay_id, 'wb') as f: f.write(g.record) # IB: Added basic game->json conversion for js graphic display with open(replay_id + '.klvr', 'w') as f: import pacman.textDisplay as textDisplay states = [] class js_recorded(textDisplay.PacmanGraphics): def pause(self): pass def draw(self, state): pass def update(self, state): super().update(state) states.append(str(state)) def finish(self): json_components = { 'history': states, 'redTeamName': redTeamName, 'blueTeamName': blueTeamName } json.dump(json_components, f) replayGame(layout, agents, g.moveHistory, js_recorded(), length, redTeamName, blueTeamName) if numGames > 1: scores = [g.state.data.score for g in games] redWinRate = [s > 0 for s in scores].count(True) / float(len(scores)) blueWinRate = [s < 0 for s in scores].count(True) / float(len(scores)) return games
def readCommand(): """ Processes the command used to run pacman from the command line. """ from argparse import ArgumentParser usageStr = """ USAGE: python pacman.py <options> EXAMPLES: (1) python pacman.py - starts an interactive game (2) python pacman.py --layout smallClassic --zoom 2 OR python pacman.py -l smallClassic -z 2 - starts an interactive game on a smaller board, zoomed in """ parser = ArgumentParser(description=usageStr) parser.add_argument( "-n", "--numGames", dest="numGames", type=int, help="the number of GAMES to play", metavar="GAMES", default=1, ) parser.add_argument( "-l", "--layout", dest="layout", help="the LAYOUT_FILE from which to load the map layout", metavar="LAYOUT_FILE", default="mediumClassic", ) parser.add_argument( "-p", "--pacman", dest="pacman", help="the agent TYPE in the pacmanAgents module to use", metavar="TYPE", default="KeyboardAgent", ) parser.add_argument( "-t", "--textGraphics", action="store_true", dest="textGraphics", help="Display output as text only", default=False, ) parser.add_argument( "-q", "--quietTextGraphics", action="store_true", dest="quietGraphics", help="Generate minimal output and no graphics", default=False, ) parser.add_argument( "-g", "--ghosts", dest="ghost", help="the ghost agent TYPE in the ghostAgents module to use", metavar="TYPE", default="RandomGhost", ) parser.add_argument( "-k", "--numghosts", type=int, dest="numGhosts", help="The maximum number of ghosts to use", default=4, ) parser.add_argument( "-z", "--zoom", type=float, dest="zoom", help="Zoom the size of the graphics window", default=1.0, ) parser.add_argument( "-f", "--fixRandomSeed", action="store_true", dest="fixRandomSeed", help="Fixes the random seed to always play the same game", default=False, ) parser.add_argument( "-r", "--recordActions", action="store_true", dest="record", help="Writes game histories to a file (named by the time they were played)", default=False, ) parser.add_argument( "--replay", dest="gameToReplay", help="A recorded game file (pickle) to replay", default=None, ) parser.add_argument( "-x", "--numTraining", dest="numTraining", type=int, help="How many episodes are training (suppresses output)", default=0, ) parser.add_argument( "--frameTime", dest="frameTime", type=float, help="Time to delay between frames; <0 means keyboard", default=0.1, ) parser.add_argument( "-c", "--catchExceptions", action="store_true", dest="catchExceptions", help="Turns on exception handling and timeouts during games", default=False, ) parser.add_argument( "--timeout", dest="timeout", type=int, help="Maximum length of time an agent can spend computing in a single game", default=30, ) parser.add_argument("--from-experiment") parser.add_argument("--nb-testing-episodes", default=100, type=int) parser.add_argument("--show-board", action="store_true") options, _ = parser.parse_known_args() args = dict() # This is a fragile hack, don't touch it config = {} if options.from_experiment is not None: path = f"experiments/{options.from_experiment}/config.json" if not os.path.exists(path): raise ValueError( "`--from-experiment` must be a valid directory and contain a valid `config.json`" ) with open(path, "r") as f: config = json.load(f) config["is_training"] = False if "model_dir" not in config: raise ValueError( "When using `--from-experiment` to test models, the model directory must exist" ) config["model_paths"] = glob.glob( f"saved_models/{config['model_dir']}/policy*.th" ) config["numTraining"] = options.nb_testing_episodes * len(config["model_paths"]) if not options.show_board else 0 config["numGames"] = options.nb_testing_episodes * len(config["model_paths"]) config["nb_testing_episodes"] = options.nb_testing_episodes if options.show_board: config["quietGraphics"] = False config["textGraphics"] = False args["numTesting"] = options.nb_testing_episodes options.__dict__.update(config) # Fix the random seed if options.fixRandomSeed or options.from_experiment is not None: random.seed("cs188") np.random.seed(seed=0) torch.manual_seed(0) # Choose a layout args["layout"] = layout.getLayout(options.layout) if args["layout"] == None: raise Exception("The layout " + options.layout + " cannot be found") # Choose a Pacman agent noKeyboard = options.gameToReplay == None and ( options.textGraphics or options.quietGraphics ) pacmanType = loadAgent(options.pacman, noKeyboard) pacmanType.add_args(parser) options = parser.parse_args() options.__dict__.update(config) pacman = pacmanType( settings=options.__dict__, **options.__dict__ ) # Instantiate Pacman with agentArgs args["pacman"] = pacman args["numTraining"] = options.numTraining # Choose a ghost agent ghostType = loadAgent(options.ghost, noKeyboard) args["ghosts"] = [ghostType(i + 1) for i in range(options.numGhosts)] # Choose a display format if options.quietGraphics: from pacman import textDisplay args["display"] = textDisplay.NullGraphics() elif options.textGraphics: from pacman import textDisplay textDisplay.SLEEP_TIME = options.frameTime args["display"] = textDisplay.PacmanGraphics() else: from pacman import graphicsDisplay args["display"] = graphicsDisplay.PacmanGraphics( options.zoom, frameTime=options.frameTime ) args["numGames"] = options.numGames args["record"] = options.record args["catchExceptions"] = options.catchExceptions args["timeout"] = options.timeout # Special case: recorded games don't use the runGames method or args structure if options.gameToReplay != None: print("Replaying recorded game %s." % options.gameToReplay) import cPickle f = open(options.gameToReplay) try: recorded = cPickle.load(f) finally: f.close() recorded["display"] = args["display"] replayGame(**recorded) sys.exit(0) return args