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)
-
Entry point for a pacman game. The args are a blind pass of
sys.argv
with the executable stripped. def parseAgentArgs(str)
def readCommand(argv)
-
Processes the command used to run pacman from the command line.
def replayGame(layout, actions, display)
def runGames(layout, pacman, ghosts, display, numGames, record=None, numTraining=0, catchExceptions=False, timeout=30, **kwargs)
Classes
class ClassicGameRules (timeout=30)
-
These game rules manage the control flow of a game, deciding when and how the game starts and ends.
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 getMaxTotalTime(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
Methods
def agentCrash(self, game, agentIndex)
def getMaxStartupTime(self, agentIndex)
def getMaxTimeWarnings(self, agentIndex)
def getMaxTotalTime(self, agentIndex)
def getMoveTimeout(self, agentIndex)
def getMoveWarningTime(self, agentIndex)
def lose(self, state, game)
def newGame(self, layout, pacmanAgent, ghostAgents, display, catchExceptions=False)
def process(self, state, game)
-
Checks to see whether it is time to end the game.
def win(self, state, game)
class GhostRules
-
These functions dictate how ghosts interact with their environment.
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
Class variables
var GHOST_SPEED
Static methods
def applyAction(state, action, ghostIndex)
def canKill(pacmanPosition, ghostPosition)
def checkDeath(state, agentIndex)
def collide(state, ghostState, agentIndex)
def decrementTimer(agentState)
def getLegalActions(state, ghostIndex)
-
Ghosts cannot stop, and cannot turn around unless they reach a dead end, but can turn 90 degrees at intersections.
class PacmanGameState (layout)
-
A game state specific to pacman. Note that in classic Pacman, Pacman is always agent PACMAN_AGENT_INDEX.
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
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)
def generateSuccessor(self, agentIndex, action)
-
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)
def getGhostPosition(self, agentIndex)
def getGhostPositions(self)
def getGhostState(self, agentIndex)
def getGhostStates(self)
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
Gets the legal actions for the agent specified.
def getLegalPacmanActions(self)
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)
def getPacmanPosition(self)
def getPacmanState(self)
-
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
-
These functions govern how pacman interacts with his environment under the classic game rules.
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)
Class variables
var PACMAN_SPEED
Static methods
def applyAction(state, action)
-
Edits the state to reflect the results of the action.
def consume(position, state)
def getLegalActions(state)
-
Returns a list of possible actions.