def makeGame(displayActive): """ Make a game :param displayActive: True or False to indicate if the display should be active :return: game, agents, display, rules """ if not displayActive: import textDisplay display = textDisplay.NullGraphics() else: import graphicsDisplay display = graphicsDisplay.PacmanGraphics(frameTime=0.01) theLayout = layout.getLayout(layoutName) if theLayout == None: raise Exception("The layout " + layoutName + " cannot be found") rules = ClassicGameRules() agents = [trainedAgent] \ + [ghostAgents.DirectionalGhost(i + 1) for i in range(theLayout.getNumGhosts())] game = rules.newGame(theLayout, agents[0], agents[1:], display) return game
def buildRandomExperience(self, layoutName, displayActive=False, limit=None): import pacmanAgents, ghostAgents from pacman import ClassicGameRules import layout theLayout = layout.getLayout(layoutName) if theLayout == None: raise Exception("The layout " + layoutName + " cannot be found") display = None # Choose a display format if not displayActive: import textDisplay display = textDisplay.NullGraphics() else: import graphicsDisplay display = graphicsDisplay.PacmanGraphics(frameTime=0.01) counter = 0 finished = False while not finished: rules = ClassicGameRules() agents = [pacmanAgents.RandomAgent()] + [ ghostAgents.DirectionalGhost(i + 1) for i in range(theLayout.getNumGhosts()) ] game = rules.newGame(theLayout, agents[0], agents[1:], display) currentState = game.state display.initialize(currentState.data) while not (currentState.isWin() or currentState.isLose()): action = agents[0].getAction(currentState) newState = util.getSuccessor(agents, display, currentState, action) reward = newState.data.score - currentState.data.score self.remember(currentState, action, reward, newState) currentState = newState counter += 1 if counter % 100 == 0: self.persist() if counter % 2000 == 0: print("Explored " + str(counter) + " states") if limit is not None and counter > limit: finished = True display.finish() self.persist() self.replayMemory.close() print("Done")
def setUp(self): "setUp() - Initialize a Pacman board for testing" # Set up game arguments self.args = readCommand(self.argstr) # Initialize the agents self.studentAgent = self.args['pacman'] self.goldAgent = GoldTimidAgent() #layout, pacmanAgent, ghostAgents, display, quiet, catchExceptions self.rules = ClassicGameRules(self.args['timeout']) self.dist = 3
def __init__(self, layout, ghosts, display, timeout=30, percentRandomize=0.5): import __main__ __main__.__dict__['_display'] = display self._rules = ClassicGameRules(timeout) self._layout = layout self._ghosts = ghosts self._display = display self._percentRandomize = percentRandomize if isinstance(display, VizGraphics): self._obs_type = 'rgb_array' elif isinstance(display, TextGraphics): self._obs_type = 'ansi' elif isinstance(display, MatrixGraphics): self._obs_type = 'matrix' elif isinstance(display, PacPosGraphics): self._obs_type = 'pos' else: raise ValueError('Invalid display arg!') self.action_set = [ Directions.NORTH, Directions.SOUTH, Directions.EAST, Directions.WEST, Directions.STOP ] self.action_space = spaces.Discrete(len(self.action_set)) self.width = layout.width self.height = layout.height if self._obs_type == 'ansi': self.observation_space = spaces.Box(low=0, high=255, shape=(self.width, self.height), dtype=np.uint8) elif self._obs_type == 'pos': self.observation_space = spaces.Box(low=0, high=255, shape=(2, ), dtype=np.uint8) elif self._obs_type == 'matrix': self.observation_space = spaces.Box(low=0, high=1, shape=(self.width, self.height, display.NUM_CHANNELS), dtype=np.uint8) elif self._obs_type == 'rgb_array': (screen_width, screen_height) = display.get_size(self.width, self.height) self.observation_space = spaces.Box(low=0, high=255, shape=(int(screen_height), int(screen_width), 3), dtype=np.uint8)
def run_games(args, ghosts, num_runs=5, graphics=True): """ Run the games with the setup """ if graphics: import graphicsDisplay display = graphicsDisplay.PacmanGraphics(frameTime=0.1) else: import textDisplay display = textDisplay.NullGraphics() import __main__ __main__.__dict__['_display'] = display # Run games with classic rules rules = ClassicGameRules(timeout=30) games = [] for _ in range(num_runs): game = rules.newGame(args['layout'], args['pacman'], ghosts, display) game.run() games.append(game) return games
def train(layout, pacman, ghosts, numTraining, catchExceotions=False, timeout=30): """ Train the ghost with the specified game params """ rules = ClassicGameRules(timeout) games = [] # Run the game with numTraining times for i in range(numTraining): game_display = textDisplay.NullGraphics() rules.quiet = True game = rules.newGame(layout, pacman, ghosts, game_display, quiet=True, catchExceptions=catchExceotions) game.run() games.append(game) return games
def run_experiment(layout, pacman, ghosts, numTraining, catchExceotions=False, timeout=30): """ Run an experiment with the provided layout, pacman and ghosts Returns the game after it is run """ rules = ClassicGameRules(timeout) games = [] for i in range(numTraining): game_display = textDisplay.NullGraphics() rules.quiet = True game = rules.newGame(layout, pacman, ghosts, game_display, quiet=True, catchExceptions=catchExceotions) game.run() games.append(game) return games
def runGames(layoutName, pacman, ghosts, numGames, numGamesToDisplay=1, numTraining=0, catchExceptions=False, timeout=30, **args): """ A copy of same function in pacman.py """ #__main__.__dict__['_display'] = display layout = getLayout(layoutName) rules = ClassicGameRules(timeout) games = [] avgScore = 0 winCnt = 0 name = getTitleName(pacman, layoutName, numGames) numGames = max(numGames, numGamesToDisplay) numTraining = numGames - numGamesToDisplay frameDir = f"gif/{name}" import shutil # delete older dir if os.path.exists(frameDir): input("FrameDir exist, confirm to delete it") shutil.rmtree(frameDir) os.mkdir(frameDir) for i in range(numGames): print( f"({i}/{numGames}) game start, avgScore {avgScore:.2f} winCnt {winCnt}" ) #beQuiet = i < numTraining beQuiet = (i < numTraining) if beQuiet: # Suppress output and graphics gameDisplay = textDisplay.NullGraphics() rules.quiet = True else: import graphicsDisplay gameDisplay = graphicsDisplay.PacmanGraphicsGif( zoom=1.0, capture=False, frameTime=0.001, storeFrameDir=frameDir, gameIdx=i - numTraining + 1, totalGame=numGamesToDisplay) rules.quiet = False game = rules.newGame(layout, pacman, ghosts, gameDisplay, beQuiet, catchExceptions) game.run() avgScore = (avgScore * i + game.state.getScore()) / (i + 1) winCnt += game.state.isWin() games.append(game) # end of simulation of games # report and save the results 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])) ## save the result np.save(f"data/{name}.npy", { 'wins': wins, 'scores': scores }, allow_pickle=True) return games
class testProgram(unittest.TestCase): # This is poor form, but we want to be able to invoke the test with # different arguments which we will communicate throught this class # variable. argstr = "" def setUp(self): "setUp() - Initialize a Pacman board for testing" # Set up game arguments self.args = readCommand(self.argstr) # Initialize the agents self.studentAgent = self.args['pacman'] self.goldAgent = GoldTimidAgent() #layout, pacmanAgent, ghostAgents, display, quiet, catchExceptions self.rules = ClassicGameRules(self.args['timeout']) self.dist = 3 def initGame(self): "initGame() - Initialize game, returns game and game state" game = self.rules.newGame(self.args['layout'], self.studentAgent, self.args['ghosts'], self.args['display']) # Get game state return game, game.state TurnLeftAgentPoints = 30.0 @dec.partial_credit(TurnLeftAgentPoints) def testTurnLeftAgent(self, set_score=None): "Ensure left turn behavior when Pacman not in danger" game, gstate = self.initGame() ghosts = gstate.getGhostStates() pacman = gstate.getPacmanState() # Check left turn behavior at several positions # We ensure that none of the conditions that would permit TimidAgent # to change behavior occur. resultstr = "At (%d,%d) with direction %s: expected %s, not %s" tests = (LeftTrn((5, 9), Directions.STOP, Directions.WEST), LeftTrn((9, 9), Directions.EAST, Directions.NORTH), LeftTrn((4, 7), Directions.SOUTH, Directions.EAST), LeftTrn((6, 1), Directions.NORTH, Directions.EAST), LeftTrn((3, 7), Directions.WEST, Directions.SOUTH), LeftTrn((1, 2), Directions.SOUTH, Directions.SOUTH)) testsN = len(tests) passed, failed = [], [] for test in tests: # Set the pacman state cfg = pacman.configuration cfg.setPosition(test.position) cfg.setDirection(test.dir) # Determine what the next action will be action = self.studentAgent.getAction(gstate) goldAction = self.goldAgent.getAction(gstate) outcome = (resultstr % (test.position[0], test.position[1], test.dir, action, goldAction)) if action == goldAction: passed.append(outcome) else: failed.append(outcome) # Determine number of points awarded set_score(self.TurnLeftAgentPoints - len(failed) * self.TurnLeftAgentPoints / len(tests)) if len(failed) > 0: self.fail("Agent should have exhibited TurnLeftAgent behavior.\n" + "Given a pristine board and only moving the pacman: \n" + "\n".join(failed)) InDangerPoints = 30.0 @dec.partial_credit(InDangerPoints) def testInDanger(self, set_score=None): "Ensure inDanger tests for Pacman in danger work correctly" game, gstate = self.initGame() ghost = gstate.getGhostStates()[0] # first ghost pacman = gstate.getPacmanState() # Check left turn behavior at several positions # We ensure that none of the conditions that would permit TimidAgent # to change behavior occur. resultstr = "At (%d,%d) with direction %s: expected %s, not %s" tests = ( # pacman might get eaten InDanger((1, 1), (3, 1), False, 2, Directions.EAST), # pacman giving chase to a scared ghost InDanger((1, 1), (3, 1), True, 3, Directions.STOP), # not on same row/col InDanger((3, 3), (4, 2), False, 3, Directions.STOP), # same row, close enough InDanger((11, 3), (8, 3), False, 3, Directions.WEST), # same row too far InDanger((12, 3), (8, 3), False, 3, Directions.STOP), # danger from the south InDanger((3, 7), (3, 5), False, 2, Directions.SOUTH)) # Get agent states and configurations pacmanState = gstate.getPacmanState() ghostState = gstate.getGhostStates()[0] pacmanCfg = pacmanState.configuration ghostCfg = ghostState.configuration testN = len(tests) passed, failed = [], [] scared_time = 10 # Make ghosts scared for N clock ticks msg = "Pacman at (%d,%d), %s ghost at (%d,%d), reported %s expected %s" for test in tests: # Set the pacman and ghost states based on the test pacmanCfg.setPosition(test.pacman) ghostCfg.setPosition(test.ghost) if test.scared: ghostState.scaredTimer = scared_time else: ghostState.scaredTimer = 0 dir = self.studentAgent.inDanger(pacmanState, ghostState) result = msg % (test.pacman[0], test.pacman[1], "fleeing" if test.scared else "chasing", test.ghost[0], test.ghost[1], dir, test.danger) if dir == test.danger: passed.append(result) else: failed.append(result) # Determine number of points awarded failedN = len(failed) set_score(self.InDangerPoints - failedN * self.InDangerPoints / len(tests)) if failedN > 0: self.fail("Agent reported incorrect inDanger direction:\n" + "\n".join(failed)) ActionPoints = 20.0 @dec.partial_credit(ActionPoints) def test_getAction(self, set_score=None): """Ensure that getAction() returns expected behaviror The basic behavior of the agent has already been tested, the following simply ensures that the action taken based on when a Pacman might be in danger is correct. """ game, gstate = self.initGame() ghost = gstate.getGhostStates()[0] # first ghost pacman = gstate.getPacmanState() # Check left turn behavior at several positions # We ensure that none of the conditions that would permit TimidAgent # to change behavior occur. msg = "Pacman at (%d,%d) traveling %s, %s ghost at (%d,%d), " + \ "getAction: %s, expected %s" tests = ( # pacman might get eaten StatefulAction((1, 1), Directions.EAST, (3, 1), False, 2, Directions.NORTH), # pacman giving chase to a scared ghost StatefulAction((2, 1), Directions.EAST, (3, 1), True, 3, Directions.EAST), # not on same row/col StatefulAction((3, 3), Directions.NORTH, (4, 2), False, 3, Directions.NORTH), # agent takes available left turn StatefulAction((3, 3), Directions.EAST, (4, 2), False, 3, Directions.NORTH), # same row, close enough StatefulAction((11, 3), Directions.WEST, (8, 3), False, 3, Directions.EAST), # same row too far StatefulAction((12, 3), Directions.WEST, (8, 3), False, 3, Directions.WEST), # danger from the west, forced U-turn StatefulAction((13, 9), Directions.NORTH, (11, 9), False, 2, Directions.SOUTH), # same situation giving chase StatefulAction((13, 9), Directions.NORTH, (11, 9), True, 2, Directions.WEST)) # Get agent states and configurations pacmanState = gstate.getPacmanState() ghostState = gstate.getGhostStates()[0] pacmanCfg = pacmanState.configuration ghostCfg = ghostState.configuration testN = len(tests) passed, failed = [], [] scared_time = 10 # Make ghosts scared for N clock ticks msg = "Pacman at (%d,%d) moving %s, %s ghost at (%d,%d), getAction: %s expected %s" for test in tests: # Set the pacman and ghost states based on the test pacmanCfg.setPosition(test.pacman) pacmanCfg.setDirection(test.pacdir) ghostCfg.setPosition(test.ghost) if test.scared: ghostState.scaredTimer = scared_time else: ghostState.scaredTimer = 0 dir = self.studentAgent.getAction(gstate) result = msg % (test.pacman[0], test.pacman[1], test.pacdir, "fleeing" if test.scared else "chasing", test.ghost[0], test.ghost[1], dir, test.action) if dir != test.action: failed.append(result) else: passed.append(result) # Determine number of points awarded failedN = len(failed) set_score(self.ActionPoints - failedN * self.ActionPoints / len(tests)) if failedN > 0: self.fail("Agent reported incorrect getAction direction:\n" + "\n".join(failed))
def buildExperience(self, layoutName, displayActive=False, limit=None): import pacmanAgents, ghostAgents from pacman import ClassicGameRules from game import Directions import layout theLayout = layout.getLayout(layoutName) if theLayout == None: raise Exception("The layout " + layoutName + " cannot be found") display = None # Choose a display format if not displayActive: import textDisplay display = textDisplay.NullGraphics() else: import graphicsDisplay display = graphicsDisplay.PacmanGraphics(frameTime=0.01) rules = ClassicGameRules() agents = [pacmanAgents.GreedyAgent()] + [ ghostAgents.DirectionalGhost(i + 1) for i in range(theLayout.getNumGhosts()) ] game = rules.newGame(theLayout, agents[0], agents[1:], display) initialState = game.state display.initialize(initialState.data) exploredStateHashes = {initialState.__hash__()} pendingStates = {initialState} counter = 0 while pendingStates: pendingState = pendingStates.pop() for action in pendingState.getLegalActions(): if action == Directions.STOP: continue try: # Execute the action newState = util.getSuccessor(agents, display, pendingState, action) reward = newState.data.score - pendingState.data.score self.remember(pendingState, action, reward, newState) counter += 1 if not (newState.isWin() or newState.isLose( )) and newState.__hash__() not in exploredStateHashes: exploredStateHashes.add(newState.__hash__()) pendingStates.add(newState) except Exception, e: #print(e) pass if counter % 100 == 0: self.persist() if counter % 2000 == 0: print("Explored " + str(counter) + " states") if limit is not None and counter > limit: break