Module pacai.core.gamestate
Classes
class AbstractGameState (layout)
-
A game state specifies the status of a game, including the food, capsules, agents, and score.
Game states are used by the
Game
to capture the actual state of the game, and can be used by agents to reason about the game.Only use the accessor methods to get data about the game state.
Expand source code
class AbstractGameState(abc.ABC): """ A game state specifies the status of a game, including the food, capsules, agents, and score. Game states are used by the `pacai.core.game.Game` to capture the actual state of the game, and can be used by agents to reason about the game. Only use the accessor methods to get data about the game state. """ def __init__(self, layout): self._lastAgentMoved = None self._gameover = False self._win = False self._layout = layout # Keep a copy of the hash, since it is expensive to compute. # Any children should be sure to clear the hash when modifications are made. self._hash = None # For food and capsules, we will only copy on write (if we eat one of them). # This avoid additional copies on successors that don't eat. self._foodCopied = False self._food = layout.food.copy() self._lastFoodEaten = None self._capsulesCopied = False self._capsules = layout.capsules.copy() self._lastCapsuleEaten = None # An ordered list of locations that this state considers special. # A view may choose to specially represent these locations. self._highlightLocations = [] self._agentStates = [] for (isPacman, position) in layout.agentPositions: self._agentStates.append(AgentState(position, Directions.STOP, isPacman)) self._score = 0 @abc.abstractmethod def generateSuccessor(self, agentIndex, action): """ Returns the successor state after the specified agent takes the action. Treat the returned state as a SHALLOW copy that has been modified. """ pass @abc.abstractmethod def getLegalActions(self, agentIndex = 0): """ Gets the legal actions for the agent specified. """ pass def addScore(self, score): self._hash = None self._score += score def eatCapsule(self, x, y): """ Mark the capsule at the given location as eaten. """ if (not self.hasCapsule(x, y)): return False if (not self._capsulesCopied): self._capsules = self._capsules.copy() self._capsulesCopied = True self._capsules.remove((x, y)) self._lastCapsuleEaten = (x, y) self._hash = None return True def eatFood(self, x, y): """ Mark the food at the given location as eaten. """ if (not self.hasFood(x, y)): return False if (not self._foodCopied): self._food = self._food.copy() self._foodCopied = True self._food[x][y] = False self._lastFoodEaten = (x, y) self._hash = None return True def endGame(self, win): self._gameover = True self._win = win self._hash = None def getAgentPosition(self, index): """ 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 it just died and is respawning). """ position = self._agentStates[index].getPosition() if (position is None): return None # Ensure positions are ints. return tuple(int(pos) for pos in position) def getAgentState(self, index): return self._agentStates[index] def getAgentStates(self): return self._agentStates def getCapsules(self): """ Returns a list of positions (x, y) of the remaining capsules. """ return self._capsules def getFood(self): """ Returns a Grid of boolean food indicator variables. Grids can be accessed via list notation. So to check if there is food at (x, y), just do something like: food[x][y]. Callers should favor hasFood() over this, since this will make a copy of the grid. """ return self._food.copy() def getHighlightLocations(self): return self._highlightLocations def getInitialAgentPosition(self, agentIndex): return self._layout.agentPositions[agentIndex][1] def getInitialLayout(self): """ Get the initial layout this state starte with. User's should typically call one of the more detailed methods directly, e.g. getWalls(). """ return self._layout def getLastAgentMoved(self): return self._lastAgentMoved def getLastCapsuleEaten(self): return self._lastCapsuleEaten def getLastFoodEaten(self): return self._lastFoodEaten def getNumAgents(self): return len(self._agentStates) def getNumCapsules(self): """ Get the amount of capsules left on the board. """ return len(self._capsules) def getNumFood(self): """ Get the amount of food left on the board. """ return self._food.count() def getScore(self): return self._score def getWalls(self): """ Returns a Grid of boolean wall indicator variables. Grids can be accessed via list notation. So to check if there is a wall at (x, y), just do something like: walls[x][y]. The caller should not try to modify the walls. """ return self._layout.walls def hasCapsule(self, x, y): """ Returns true if the location (x, y) has a capsule. """ return (x, y) in self._capsules def hasFood(self, x, y): """ Returns true if the location (x, y) has food. """ return self._food[x][y] def hasWall(self, x, y): """ Returns true if (x, y) has a wall, false otherwise. """ return self._layout.walls[x][y] def isLose(self): return self.isOver() and not self._win def isOver(self): return self._gameover def isWin(self): return self.isOver() and self._win def setHighlightLocations(self, locations): self._highlightLocations = list(locations) def setScore(self, score): self._score = score self._hash = None def _initSuccessor(self): """ Get a state that will eventually serve as a successor. Initialize the successor to look like this state. """ # Start with a shallow copy. successor = copy.copy(self) successor._hash = None # Leave food and capsules as a shallow copy, but mark them to be copied on write. successor._foodCopied = False successor._capsulesCopied = False # Agent states need to be deep copied. successor._agentStates = [agentState.copy() for agentState in self._agentStates] return successor def __eq__(self, other): if (other is None): return False # Reference equality check. if (self is other): return True if (type(self) != type(other)): return False # Note that not all fields are being used because we are checking if two states are equal, # not is they got to this confiruation in the same way. # Check simple fields first. if (self._score != other._score or self._gameover != other._gameover or self._win != other._win): return False # Now check the complex fields in increasing order of complexity. return (self._capsules == other._capsules and self._food == other._food and self._agentStates == other._agentStates and self._layout == other._layout) def __hash__(self): if (self._hash is None): self._hash = util.buildHash(self._score, self._gameover, self._win, *self._capsules, self._food, *self._agentStates, self._layout) return self._hash
Ancestors
- abc.ABC
Subclasses
Methods
def addScore(self, score)
def eatCapsule(self, x, y)
-
Mark the capsule at the given location as eaten.
def eatFood(self, x, y)
-
Mark the food at the given location as eaten.
def endGame(self, win)
def generateSuccessor(self, agentIndex, action)
-
Returns the successor state after the specified agent takes the action. Treat the returned state as a SHALLOW copy that has been modified.
def getAgentPosition(self, index)
-
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 it just died and is respawning).
def getAgentState(self, index)
def getAgentStates(self)
def getCapsules(self)
-
Returns a list of positions (x, y) of the remaining capsules.
def getFood(self)
-
Returns a Grid of boolean food indicator variables.
Grids can be accessed via list notation. So to check if there is food at (x, y), just do something like: food[x][y].
Callers should favor hasFood() over this, since this will make a copy of the grid.
def getHighlightLocations(self)
def getInitialAgentPosition(self, agentIndex)
def getInitialLayout(self)
-
Get the initial layout this state starte with. User's should typically call one of the more detailed methods directly, e.g. getWalls().
def getLastAgentMoved(self)
def getLastCapsuleEaten(self)
def getLastFoodEaten(self)
def getLegalActions(self, agentIndex=0)
-
Gets the legal actions for the agent specified.
def getNumAgents(self)
def getNumCapsules(self)
-
Get the amount of capsules left on the board.
def getNumFood(self)
-
Get the amount of food left on the board.
def getScore(self)
def getWalls(self)
-
Returns a Grid of boolean wall indicator variables.
Grids can be accessed via list notation. So to check if there is a wall at (x, y), just do something like: walls[x][y].
The caller should not try to modify the walls.
def hasCapsule(self, x, y)
-
Returns true if the location (x, y) has a capsule.
def hasFood(self, x, y)
-
Returns true if the location (x, y) has food.
def hasWall(self, x, y)
-
Returns true if (x, y) has a wall, false otherwise.
def isLose(self)
def isOver(self)
def isWin(self)
def setHighlightLocations(self, locations)
def setScore(self, score)