Module pacai.bin.pacman
This file holds the logic for a classic pacman game along with the main code to run a game.
To play your first game, type 'python -m pacai.bin.pacman' from the command line. Use WASD (or the arrow keys) to move.
Have fun!
Functions
def main(argv)
-
Expand source code
def main(argv): """ Entry point for a pacman game. The args are a blind pass of `sys.argv` with the executable stripped. """ initLogging() # Get game components based on input args = readCommand(argv) # Special case: recorded games don't use the runGames method. if (args['gameToReplay'] is not None): logging.info('Replaying recorded game %s.' % args['gameToReplay']) recorded = None with open(args['gameToReplay'], 'rb') as file: recorded = pickle.load(file) recorded['display'] = args['display'] replayGame(**recorded) return return runGames(**args)
Entry point for a pacman game. The args are a blind pass of
sys.argv
with the executable stripped. def parseAgentArgs(str)
-
Expand source code
def parseAgentArgs(str): if (str is None): return {} pieces = str.split(',') opts = {} for p in pieces: if '=' in p: key, val = p.split('=') else: key, val = p, 1 opts[key] = val return opts
def readCommand(argv)
-
Expand source code
def readCommand(argv): """ Processes the command used to run pacman from the command line. """ description = """ DESCRIPTION: This program will run a classic pacman game. Collect all the pellets before the ghosts catch you! EXAMPLES: (1) python -m pacai.bin.pacman - Starts an interactive game. (2) python -m pacai.bin.pacman --layout smallClassic - Starts an interactive game on a smaller board. """ parser = getParser(description, os.path.basename(__file__)) parser.add_argument('-g', '--ghosts', dest = 'ghost', action = 'store', type = str, default = 'RandomGhost', help = 'use the specified ghostAgent module for the ghosts (default: %(default)s)') parser.add_argument('-k', '--num-ghosts', dest = 'numGhosts', action = 'store', type = int, default = 4, help = 'set the maximum number of ghosts (default: %(default)s)') parser.add_argument('-l', '--layout', dest = 'layout', action = 'store', type = str, default = 'mediumClassic', help = 'use the specified map layout (default: %(default)s)') parser.add_argument('-p', '--pacman', dest = 'pacman', action = 'store', type = str, default = 'WASDKeyboardAgent', help = 'use the specified pacmanAgent module for pacman (default: %(default)s)') parser.add_argument('--agent-args', dest = 'agentArgs', action = 'store', type = str, default = None, help = 'comma separated arguments to be passed to agents (e.g. \'opt1=val1,opt2\')' + '(default: %(default)s)') parser.add_argument('--timeout', dest = 'timeout', action = 'store', type = int, default = 30, help = 'maximum time limit (seconds) an agent can spend computing per game ' + '(default: %(default)s)') options, otherjunk = parser.parse_known_args(argv) args = dict() if len(otherjunk) != 0: raise ValueError('Unrecognized options: \'%s\'.' % (str(otherjunk))) # Set the logging level. if options.quiet and options.debug: raise ValueError('Logging cannont be set to both debug and quiet.') if options.quiet: updateLoggingLevel(logging.WARNING) elif options.debug: updateLoggingLevel(logging.DEBUG) # If seed value is not entered generate a random seed value. seed = options.seed if seed is None: seed = random.randint(0, 2**32) random.seed(seed) logging.debug('Seed value: ' + str(seed)) # Choose a layout. args['layout'] = getLayout(options.layout, maxGhosts = options.numGhosts) if (args['layout'] is None): raise ValueError('The layout ' + options.layout + ' cannot be found.') # Choose a Pacman agent. noKeyboard = (options.replay is None and (options.textGraphics or options.nullGraphics)) if (noKeyboard and ('KeyboardAgent' in options.pacman)): raise ValueError('Keyboard agents require graphics.') agentOpts = parseAgentArgs(options.agentArgs) if options.numTraining > 0: args['numTraining'] = options.numTraining if 'numTraining' not in agentOpts: agentOpts['numTraining'] = options.numTraining # Don't display training games. if 'numTrain' in agentOpts: options.numQuiet = int(agentOpts['numTrain']) options.numIgnore = int(agentOpts['numTrain']) viewOptions = { 'gifFPS': options.gifFPS, 'gifPath': options.gif, 'skipFrames': options.gifSkipFrames, 'spritesPath': options.spritesPath, } # Choose a display format. if options.nullGraphics: args['display'] = PacmanNullView(**viewOptions) elif options.textGraphics: args['display'] = PacmanTextView(**viewOptions) else: # Defer importing the GUI unless we actually need it. # This allows people to not have tkinter installed. from pacai.ui.pacman.gui import PacmanGUIView args['display'] = PacmanGUIView(fps = options.fps, title = 'Pacman', **viewOptions) agentOpts['keyboard'] = args['display'].getKeyboard() args['catchExceptions'] = options.catchExceptions args['gameToReplay'] = options.replay args['ghosts'] = [BaseAgent.loadAgent(options.ghost, i + 1) for i in range(options.numGhosts)] args['numGames'] = options.numGames args['pacman'] = BaseAgent.loadAgent(options.pacman, PACMAN_AGENT_INDEX, agentOpts) args['record'] = options.record args['timeout'] = options.timeout return args
Processes the command used to run pacman from the command line.
def replayGame(layout, actions, display)
-
Expand source code
def replayGame(layout, actions, display): rules = ClassicGameRules() agents = [] agents.append(GreedyAgent(PACMAN_AGENT_INDEX)) agents += [RandomGhost(i + 1) for i in range(layout.getNumGhosts())] game = rules.newGame(layout, agents[PACMAN_AGENT_INDEX], agents[1:], display) state = game.state display.initialize(state) for action in actions: # Execute the action state = state.generateSuccessor(*action) # Change the display display.update(state) # Allow for game specific conditions (winning, losing, etc.) rules.process(state, game) display.finish()
def runGames(layout,
pacman,
ghosts,
display,
numGames,
record=None,
numTraining=0,
catchExceptions=False,
timeout=30,
**kwargs)-
Expand source code
def runGames(layout, pacman, ghosts, display, numGames, record = None, numTraining = 0, catchExceptions = False, timeout = 30, **kwargs): rules = ClassicGameRules(timeout) games = [] nullView = None if (numTraining > 0): logging.info('Playing %d training games.' % numTraining) nullView = PacmanNullView() for i in range(numGames): isTraining = (i < numTraining) if (isTraining): # Suppress graphics for training. gameDisplay = nullView else: gameDisplay = display game = rules.newGame(layout, pacman, ghosts, gameDisplay, catchExceptions) game.run() if (not isTraining): games.append(game) if (record): path = 'pacman.replay' if (isinstance(record, str)): path = record components = {'layout': layout, 'actions': game.moveHistory} with open(path, 'wb') as file: pickle.dump(components, file) 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)) logging.info('Average Score: %s', sum(scores) / float(len(scores))) logging.info('Scores: %s', ', '.join([str(score) for score in scores])) logging.info('Win Rate: %d/%d (%.2f)' % (wins.count(True), len(wins), winRate)) logging.info('Record: %s', ', '.join([['Loss', 'Win'][int(w)] for w in wins])) return games
Classes
class ClassicGameRules (timeout=30)
-
Expand source code
class ClassicGameRules(object): """ These game rules manage the control flow of a game, deciding when and how the game starts and ends. """ def __init__(self, timeout = 30): self.timeout = timeout def newGame(self, layout, pacmanAgent, ghostAgents, display, catchExceptions = False): agents = [pacmanAgent] + ghostAgents[:layout.getNumGhosts()] initState = PacmanGameState(layout) game = Game(agents, display, self, catchExceptions = catchExceptions) game.state = initState self._initialFoodCount = initState.getNumFood() return game def process(self, state, game): """ Checks to see whether it is time to end the game. """ if (state.isWin()): self.win(state, game) elif (state.isLose()): self.lose(state, game) def win(self, state, game): logging.info('Pacman emerges victorious! Score: %d' % state.getScore()) game.gameOver = True def lose(self, state, game): logging.info('Pacman died! Score: %d' % state.getScore()) game.gameOver = True def agentCrash(self, game, agentIndex): if (agentIndex == PACMAN_AGENT_INDEX): logging.error('Pacman crashed') else: logging.error('A ghost crashed') def getMaxTotalAgentTime(self, agentIndex): return self.timeout def getMaxStartupTime(self, agentIndex): return self.timeout def getMoveWarningTime(self, agentIndex): return self.timeout def getMoveTimeout(self, agentIndex): return self.timeout def getMaxTimeWarnings(self, agentIndex): return 0
These game rules manage the control flow of a game, deciding when and how the game starts and ends.
Methods
def agentCrash(self, game, agentIndex)
-
Expand source code
def agentCrash(self, game, agentIndex): if (agentIndex == PACMAN_AGENT_INDEX): logging.error('Pacman crashed') else: logging.error('A ghost crashed')
def getMaxStartupTime(self, agentIndex)
-
Expand source code
def getMaxStartupTime(self, agentIndex): return self.timeout
def getMaxTimeWarnings(self, agentIndex)
-
Expand source code
def getMaxTimeWarnings(self, agentIndex): return 0
def getMaxTotalAgentTime(self, agentIndex)
-
Expand source code
def getMaxTotalAgentTime(self, agentIndex): return self.timeout
def getMoveTimeout(self, agentIndex)
-
Expand source code
def getMoveTimeout(self, agentIndex): return self.timeout
def getMoveWarningTime(self, agentIndex)
-
Expand source code
def getMoveWarningTime(self, agentIndex): return self.timeout
def lose(self, state, game)
-
Expand source code
def lose(self, state, game): logging.info('Pacman died! Score: %d' % state.getScore()) game.gameOver = True
def newGame(self, layout, pacmanAgent, ghostAgents, display, catchExceptions=False)
-
Expand source code
def newGame(self, layout, pacmanAgent, ghostAgents, display, catchExceptions = False): agents = [pacmanAgent] + ghostAgents[:layout.getNumGhosts()] initState = PacmanGameState(layout) game = Game(agents, display, self, catchExceptions = catchExceptions) game.state = initState self._initialFoodCount = initState.getNumFood() return game
def process(self, state, game)
-
Expand source code
def process(self, state, game): """ Checks to see whether it is time to end the game. """ if (state.isWin()): self.win(state, game) elif (state.isLose()): self.lose(state, game)
Checks to see whether it is time to end the game.
def win(self, state, game)
-
Expand source code
def win(self, state, game): logging.info('Pacman emerges victorious! Score: %d' % state.getScore()) game.gameOver = True
class GhostRules
-
Expand source code
class GhostRules: """ These functions dictate how ghosts interact with their environment. """ GHOST_SPEED = 1.0 @staticmethod def getLegalActions(state, ghostIndex): """ Ghosts cannot stop, and cannot turn around unless they reach a dead end, but can turn 90 degrees at intersections. """ agentState = state.getGhostState(ghostIndex) possibleActions = Actions.getPossibleActions(agentState.getPosition(), agentState.getDirection(), state.getWalls()) reverse = Actions.reverseDirection(agentState.getDirection()) if (Directions.STOP in possibleActions): possibleActions.remove(Directions.STOP) if (reverse in possibleActions and len(possibleActions) > 1): possibleActions.remove(reverse) return possibleActions @staticmethod def applyAction(state, action, ghostIndex): legal = GhostRules.getLegalActions(state, ghostIndex) if (action not in legal): raise ValueError('Illegal ghost action: ' + str(action)) ghostState = state.getGhostState(ghostIndex) speed = GhostRules.GHOST_SPEED if (ghostState.isScared()): speed /= 2.0 vector = Actions.directionToVector(action, speed) ghostState.updatePosition(vector) @staticmethod def decrementTimer(agentState): if (not agentState.isScared()): return agentState.decrementScaredTimer() if (not agentState.isScared()): # If the ghost is done being scared, snap it to the closest point. agentState.snapToNearestPoint() @staticmethod def checkDeath(state, agentIndex): pacmanPosition = state.getPacmanPosition() # Did pacman just move? if (agentIndex == PACMAN_AGENT_INDEX): # See if a ghost can kill pacman. for index in state.getGhostIndexes(): ghostState = state.getGhostState(index) ghostPosition = ghostState.getPosition() if (GhostRules.canKill(pacmanPosition, ghostPosition)): GhostRules.collide(state, ghostState, index) return else: # A ghost just moved. ghostState = state.getGhostState(agentIndex) ghostPosition = ghostState.getPosition() if (GhostRules.canKill(pacmanPosition, ghostPosition)): GhostRules.collide(state, ghostState, agentIndex) @staticmethod def collide(state, ghostState, agentIndex): if (ghostState.isScared()): # Pacman ate a ghost. state.addScore(GHOST_POINTS) ghostState.respawn() elif (not state.isOver()): # A ghost ate pacman. state.addScore(LOSE_POINTS) state.endGame(False) @staticmethod def canKill(pacmanPosition, ghostPosition): return manhattan(ghostPosition, pacmanPosition) <= COLLISION_TOLERANCE
These functions dictate how ghosts interact with their environment.
Class variables
var GHOST_SPEED
Static methods
def applyAction(state, action, ghostIndex)
-
Expand source code
@staticmethod def applyAction(state, action, ghostIndex): legal = GhostRules.getLegalActions(state, ghostIndex) if (action not in legal): raise ValueError('Illegal ghost action: ' + str(action)) ghostState = state.getGhostState(ghostIndex) speed = GhostRules.GHOST_SPEED if (ghostState.isScared()): speed /= 2.0 vector = Actions.directionToVector(action, speed) ghostState.updatePosition(vector)
def canKill(pacmanPosition, ghostPosition)
-
Expand source code
@staticmethod def canKill(pacmanPosition, ghostPosition): return manhattan(ghostPosition, pacmanPosition) <= COLLISION_TOLERANCE
def checkDeath(state, agentIndex)
-
Expand source code
@staticmethod def checkDeath(state, agentIndex): pacmanPosition = state.getPacmanPosition() # Did pacman just move? if (agentIndex == PACMAN_AGENT_INDEX): # See if a ghost can kill pacman. for index in state.getGhostIndexes(): ghostState = state.getGhostState(index) ghostPosition = ghostState.getPosition() if (GhostRules.canKill(pacmanPosition, ghostPosition)): GhostRules.collide(state, ghostState, index) return else: # A ghost just moved. ghostState = state.getGhostState(agentIndex) ghostPosition = ghostState.getPosition() if (GhostRules.canKill(pacmanPosition, ghostPosition)): GhostRules.collide(state, ghostState, agentIndex)
def collide(state, ghostState, agentIndex)
-
Expand source code
@staticmethod def collide(state, ghostState, agentIndex): if (ghostState.isScared()): # Pacman ate a ghost. state.addScore(GHOST_POINTS) ghostState.respawn() elif (not state.isOver()): # A ghost ate pacman. state.addScore(LOSE_POINTS) state.endGame(False)
def decrementTimer(agentState)
-
Expand source code
@staticmethod def decrementTimer(agentState): if (not agentState.isScared()): return agentState.decrementScaredTimer() if (not agentState.isScared()): # If the ghost is done being scared, snap it to the closest point. agentState.snapToNearestPoint()
def getLegalActions(state, ghostIndex)
-
Expand source code
@staticmethod def getLegalActions(state, ghostIndex): """ Ghosts cannot stop, and cannot turn around unless they reach a dead end, but can turn 90 degrees at intersections. """ agentState = state.getGhostState(ghostIndex) possibleActions = Actions.getPossibleActions(agentState.getPosition(), agentState.getDirection(), state.getWalls()) reverse = Actions.reverseDirection(agentState.getDirection()) if (Directions.STOP in possibleActions): possibleActions.remove(Directions.STOP) if (reverse in possibleActions and len(possibleActions) > 1): possibleActions.remove(reverse) return possibleActions
Ghosts cannot stop, and cannot turn around unless they reach a dead end, but can turn 90 degrees at intersections.
class PacmanGameState (layout)
-
Expand source code
class PacmanGameState(AbstractGameState): """ A game state specific to pacman. Note that in classic Pacman, Pacman is always agent PACMAN_AGENT_INDEX. """ def __init__(self, layout): super().__init__(layout) # Override def generateSuccessor(self, agentIndex, action): """ Returns the successor state after the specified agent takes the action. """ # Check that successors exist. if (self.isOver()): raise RuntimeError("Can't generate successors of a terminal state.") successor = self._initSuccessor() successor._applySuccessorAction(agentIndex, action) return successor # Override def getLegalActions(self, agentIndex = PACMAN_AGENT_INDEX): if (self.isOver()): return [] # Pacman's turn. if (agentIndex == PACMAN_AGENT_INDEX): return PacmanRules.getLegalActions(self) return GhostRules.getLegalActions(self, agentIndex) def generatePacmanSuccessor(self, action): return self.generateSuccessor(PACMAN_AGENT_INDEX, action) def getGhostIndexes(self): return range(1, self.getNumAgents()) def getGhostPosition(self, agentIndex): if (agentIndex <= PACMAN_AGENT_INDEX or agentIndex >= self.getNumAgents()): raise ValueError("Invalid index passed to getGhostPosition(): %d." % (agentIndex)) return self._agentStates[agentIndex].getPosition() def getGhostPositions(self): return [ghost.getPosition() for ghost in self.getGhostStates()] def getGhostState(self, agentIndex): if (agentIndex <= PACMAN_AGENT_INDEX or agentIndex >= self.getNumAgents()): raise ValueError("Invalid index passed to getGhostState(): %d." % (agentIndex)) return self._agentStates[agentIndex] def getGhostStates(self): return self._agentStates[1:] def getLegalPacmanActions(self): return self.getLegalActions(PACMAN_AGENT_INDEX) def getNumGhosts(self): return self.getNumAgents() - 1 def getPacmanPosition(self): return self._agentStates[PACMAN_AGENT_INDEX].getPosition() def getPacmanState(self): """ Returns an AgentState object for pacman. state.getPosition() gives the current position. state.getDirection() gives the travel vector. """ return self._agentStates[PACMAN_AGENT_INDEX] def _applySuccessorAction(self, agentIndex, action): """ Apply the action to the context state (self). """ # Let the agent's logic deal with its action's effects on the board. if (agentIndex == PACMAN_AGENT_INDEX): PacmanRules.applyAction(self, action) else: GhostRules.applyAction(self, action, agentIndex) # Time passes. if (agentIndex == PACMAN_AGENT_INDEX): # Penalty for waiting around. self.addScore(-TIME_PENALTY) else: GhostRules.decrementTimer(self.getAgentState(agentIndex)) # Resolve multi-agent effects. GhostRules.checkDeath(self, agentIndex) # Book keeping. self._lastAgentMoved = agentIndex self._hash = None
A game state specific to pacman. Note that in classic Pacman, Pacman is always agent PACMAN_AGENT_INDEX.
Ancestors
- AbstractGameState
- abc.ABC
Methods
def eatCapsule(self, x, y)
-
Inherited from:
AbstractGameState
.eatCapsule
Mark the capsule at the given location as eaten.
def eatFood(self, x, y)
-
Inherited from:
AbstractGameState
.eatFood
Mark the food at the given location as eaten.
def generatePacmanSuccessor(self, action)
-
Expand source code
def generatePacmanSuccessor(self, action): return self.generateSuccessor(PACMAN_AGENT_INDEX, action)
def generateSuccessor(self, agentIndex, action)
-
Expand source code
def generateSuccessor(self, agentIndex, action): """ Returns the successor state after the specified agent takes the action. """ # Check that successors exist. if (self.isOver()): raise RuntimeError("Can't generate successors of a terminal state.") successor = self._initSuccessor() successor._applySuccessorAction(agentIndex, action) return successor
Returns the successor state after the specified agent takes the action.
def getAgentPosition(self, index)
-
Inherited from:
AbstractGameState
.getAgentPosition
Returns a location tuple of the agent with the given index. It is possible for this method to return None if the agent's position is unknown (like if …
def getCapsules(self)
-
Inherited from:
AbstractGameState
.getCapsules
Returns a list of positions (x, y) of the remaining capsules.
def getFood(self)
-
Inherited from:
AbstractGameState
.getFood
Returns a Grid of boolean food indicator variables …
def getGhostIndexes(self)
-
Expand source code
def getGhostIndexes(self): return range(1, self.getNumAgents())
def getGhostPosition(self, agentIndex)
-
Expand source code
def getGhostPosition(self, agentIndex): if (agentIndex <= PACMAN_AGENT_INDEX or agentIndex >= self.getNumAgents()): raise ValueError("Invalid index passed to getGhostPosition(): %d." % (agentIndex)) return self._agentStates[agentIndex].getPosition()
def getGhostPositions(self)
-
Expand source code
def getGhostPositions(self): return [ghost.getPosition() for ghost in self.getGhostStates()]
def getGhostState(self, agentIndex)
-
Expand source code
def getGhostState(self, agentIndex): if (agentIndex <= PACMAN_AGENT_INDEX or agentIndex >= self.getNumAgents()): raise ValueError("Invalid index passed to getGhostState(): %d." % (agentIndex)) return self._agentStates[agentIndex]
def getGhostStates(self)
-
Expand source code
def getGhostStates(self): return self._agentStates[1:]
def getInitialLayout(self)
-
Inherited from:
AbstractGameState
.getInitialLayout
Get the initial layout this state starte with. User's should typically call one of the more detailed methods directly, e.g. getWalls().
def getLegalActions(self, agentIndex=0)
-
Inherited from:
AbstractGameState
.getLegalActions
Expand source code
def getLegalActions(self, agentIndex = PACMAN_AGENT_INDEX): if (self.isOver()): return [] # Pacman's turn. if (agentIndex == PACMAN_AGENT_INDEX): return PacmanRules.getLegalActions(self) return GhostRules.getLegalActions(self, agentIndex)
Gets the legal actions for the agent specified.
def getLegalPacmanActions(self)
-
Expand source code
def getLegalPacmanActions(self): return self.getLegalActions(PACMAN_AGENT_INDEX)
def getNumCapsules(self)
-
Inherited from:
AbstractGameState
.getNumCapsules
Get the amount of capsules left on the board.
def getNumFood(self)
-
Inherited from:
AbstractGameState
.getNumFood
Get the amount of food left on the board.
def getNumGhosts(self)
-
Expand source code
def getNumGhosts(self): return self.getNumAgents() - 1
def getPacmanPosition(self)
-
Expand source code
def getPacmanPosition(self): return self._agentStates[PACMAN_AGENT_INDEX].getPosition()
def getPacmanState(self)
-
Expand source code
def getPacmanState(self): """ Returns an AgentState object for pacman. state.getPosition() gives the current position. state.getDirection() gives the travel vector. """ return self._agentStates[PACMAN_AGENT_INDEX]
Returns an AgentState object for pacman.
state.getPosition() gives the current position. state.getDirection() gives the travel vector.
def getWalls(self)
-
Inherited from:
AbstractGameState
.getWalls
Returns a Grid of boolean wall indicator variables …
def hasCapsule(self, x, y)
-
Inherited from:
AbstractGameState
.hasCapsule
Returns true if the location (x, y) has a capsule.
def hasFood(self, x, y)
-
Inherited from:
AbstractGameState
.hasFood
Returns true if the location (x, y) has food.
def hasWall(self, x, y)
-
Inherited from:
AbstractGameState
.hasWall
Returns true if (x, y) has a wall, false otherwise.
class PacmanRules
-
Expand source code
class PacmanRules: """ These functions govern how pacman interacts with his environment under the classic game rules. """ PACMAN_SPEED = 1 @staticmethod def getLegalActions(state): """ Returns a list of possible actions. """ agentState = state.getPacmanState() return Actions.getPossibleActions(agentState.getPosition(), agentState.getDirection(), state.getWalls()) @staticmethod def applyAction(state, action): """ Edits the state to reflect the results of the action. """ legal = PacmanRules.getLegalActions(state) if (action not in legal): raise ValueError('Illegal pacman action: ' + str(action)) pacmanState = state.getPacmanState() # Update position. vector = Actions.directionToVector(action, PacmanRules.PACMAN_SPEED) pacmanState.updatePosition(vector) # Eat. nextPosition = pacmanState.getPosition() nearest = nearestPoint(nextPosition) if (manhattan(nearest, nextPosition) <= 0.5): # Remove food PacmanRules.consume(nearest, state) @staticmethod def consume(position, state): x, y = position if (state.hasFood(x, y)): # Eat food. state.eatFood(x, y) state.addScore(FOOD_POINTS) if (state.getNumFood() == 0 and not state.isLose()): state.addScore(BOARD_CLEAR_POINTS) state.endGame(True) elif (state.hasCapsule(x, y)): # Eat a capsule. state.eatCapsule(x, y) # Reset all ghosts' scared timers. for ghostState in state.getGhostStates(): ghostState.setScaredTimer(SCARED_TIME)
These functions govern how pacman interacts with his environment under the classic game rules.
Class variables
var PACMAN_SPEED
Static methods
def applyAction(state, action)
-
Expand source code
@staticmethod def applyAction(state, action): """ Edits the state to reflect the results of the action. """ legal = PacmanRules.getLegalActions(state) if (action not in legal): raise ValueError('Illegal pacman action: ' + str(action)) pacmanState = state.getPacmanState() # Update position. vector = Actions.directionToVector(action, PacmanRules.PACMAN_SPEED) pacmanState.updatePosition(vector) # Eat. nextPosition = pacmanState.getPosition() nearest = nearestPoint(nextPosition) if (manhattan(nearest, nextPosition) <= 0.5): # Remove food PacmanRules.consume(nearest, state)
Edits the state to reflect the results of the action.
def consume(position, state)
-
Expand source code
@staticmethod def consume(position, state): x, y = position if (state.hasFood(x, y)): # Eat food. state.eatFood(x, y) state.addScore(FOOD_POINTS) if (state.getNumFood() == 0 and not state.isLose()): state.addScore(BOARD_CLEAR_POINTS) state.endGame(True) elif (state.hasCapsule(x, y)): # Eat a capsule. state.eatCapsule(x, y) # Reset all ghosts' scared timers. for ghostState in state.getGhostStates(): ghostState.setScaredTimer(SCARED_TIME)
def getLegalActions(state)
-
Expand source code
@staticmethod def getLegalActions(state): """ Returns a list of possible actions. """ agentState = state.getPacmanState() return Actions.getPossibleActions(agentState.getPosition(), agentState.getDirection(), state.getWalls())
Returns a list of possible actions.