Пример #1
0
 def __init__( self, prevState = None ): ## This initializes the GameState object. This is important as it also specifies the self.data object which is derived from the GameStateData class.
     """
     Generates a new state by copying information from its predecessor.
     """
     if prevState != None: # Initial state
         self.data = GameStateData(prevState.data)
     else:
         self.data = GameStateData()
Пример #2
0
 def __init__( self, prevState = None ): ###PLEASE NOTE THIS THAT THE __init__ method is here and this is where GameState() starts
     """
     Generates a new state by copying information from its predecessor.
     """
     if prevState != None: # Initial state
         self.data = GameStateData(prevState.data)
     else:
         self.data = GameStateData()
Пример #3
0
 def __init__( self, prevState = None ):
   """ 
   Generates a new state by copying information from its predecessor.
   """
   if prevState != None: # Initial state
     self.data = GameStateData(prevState.data)
   else:
     self.data = GameStateData()
Пример #4
0
 def __init__( self, prevState = None ):
   """ 
   Generates a new state by copying information from its predecessor.
   """
   if prevState != None: 
     self.data = GameStateData(prevState.data)
     self.livingGhosts = prevState.livingGhosts[:]
   else: # Initial state
     self.data = GameStateData()
   self.data.ghostDistances = []
Пример #5
0
    def __init__( self, prevState = None ): ###PLEASE NOTE THIS THAT THE __init__ method is here and this is where GameState() starts
        """
        Generates a new state by copying information from its predecessor.
        """
        if prevState != None: # Initial state
            self.data = GameStateData(prevState.data) ##This statement imports the GameStateData object from the GameStateData class in game.py. This object contains a data packet documenting the state of the game.

        else:
            self.data = GameStateData()
        """
Пример #6
0
 def __init__( self, prevState = None ):
     """
     Generates a new state by copying information from its predecessor.
     """
     if prevState != None:
         self.data = GameStateData(prevState.data)
         self.livingGhosts = prevState.livingGhosts[:]
         self.numMoves = prevState.numMoves;
         self.maxMoves = prevState.maxMoves;
     else: # Initial state
         self.data = GameStateData()
         self.numMoves = 0;
         self.maxMoves = -1;
Пример #7
0
 def __init__( self, prevState = None ):
   """ 
   Generates a new state by copying information from its predecessor.
   """
   if prevState != None: # Initial state
     self.data = GameStateData(prevState.data)
     self.blueTeam = prevState.blueTeam
     self.redTeam = prevState.redTeam
     self.teams = prevState.teams
     self.agentDistances = prevState.agentDistances
   else:
     self.data = GameStateData()
     self.agentDistances = []
Пример #8
0
    def initPlot(self, xmin, ymin, width, height):
        if graphicsUtils._canvas is not None:
            graphicsUtils.clear_screen()
        
        # Initialize GameStateData with blank board with axes    
        self.width = width
        self.height = height
        self.xShift = -(xmin-1)
        self.yShift = -(ymin-1)
        self.line = None

        self.zoom = min(30.0/self.width, 20.0/self.height)
        self.gridSize = graphicsDisplay.DEFAULT_GRID_SIZE * self.zoom


#         fullRow = ['%']*self.width
#         row = ((self.width-1)/2)*[' '] + ['%'] + ((self.width-1)/2)*[' ']
#         boardText = ((self.height-1)/2)*[row] + [fullRow] + ((self.height-1)/2)*[row]

        numSpaces = self.width-1
        numSpacesLeft = self.xShift
        numSpacesRight = numSpaces-numSpacesLeft

        numRows = self.height
        numRowsBelow = self.yShift
        numRowsAbove = numRows-1-numRowsBelow


        fullRow = ['%']*self.width
        if numSpacesLeft < 0:
            row = [' ']*self.width
        else:
            row = numSpacesLeft*[' '] + ['%'] + numSpacesRight*[' ']
        boardText = numRowsAbove*[row] + [fullRow] + numRowsBelow*[row]

        layout = Layout(boardText)
    
        self.blankGameState = GameStateData()
        self.blankGameState.initialize(layout, 0)
        self.initialize(self.blankGameState)
        title = 'Pacman Plot'
        graphicsUtils.changeText(self.infoPane.scoreText, title)
        graphicsUtils.refresh()
Пример #9
0
class GameState:
    """
  A GameState specifies the full game state, including the food, capsules,
  agent configurations and score changes.

  GameStates are used by the Game object to capture the actual state of the game and
  can be used by agents to reason about the game.

  Much of the information in a GameState is stored in a GameStateData object.  We
  strongly suggest that you access that data via the accessor methods below rather
  than referring to the GameStateData object directly.

  Note that in classic Pacman, Pacman is always agent 0.
  """

    ####################################################
    # Accessor methods: use these to access state data #
    ####################################################

    def updateState(self, actions):
        """
    Returns the successor state after the actions of all active agents.
    """
        # Check that successors exist
        if self.isWin() or self.isLose():
            raise Exception('it is terminal state now.')

        self.data.clear()

        for agentIndex in range(len(actions)):
            if self.data._eaten[agentIndex] > 0:
                BombermanRules.applyAction(self, actions[agentIndex],
                                           agentIndex)

        self.minusOneFrame()
        for counter, position, power, index in self.data.bombs:
            if counter == self.getFramesUntilEnd():
                self.bombExplode(self.data.bombs, position, power)
                if index >= 0:
                    self.getAgentState(index).recoverABomb()
        self.data.bombs = [
            b for b in self.data.bombs if (b[0] != self.getFramesUntilEnd())
        ]

        self.updateBombScore()
        self.updateMapScore()

        self.data.score = self.data._eaten[0]

    def getLegalActions(self, agentIndex=0):
        """
    Returns the legal actions for the agent specified.
    """
        if self.isWin() or self.isLose(): return []
        return BombermanRules.getLegalActions(self, agentIndex)

    def generateSuccessor(self, agentIndex, action, force=False):
        """
    Returns the successor state after the specified agent takes the action.
    """
        # Check that successors exist
        if self.isWin() or self.isLose():
            raise Exception('Can\'t generate a successor of a terminal state.')

        # Copy current state
        state = GameState(self)

        # Let agent's logic deal with its action's effects on the board

        #state.data._eaten = [False for i in range(state.getNumAgents())]
        if state.data._eaten[agentIndex] > 0:
            BombermanRules.applyAction(state, action, agentIndex)

        if force or (agentIndex == state.getNumAgents() - 1):
            state.minusOneFrame()
            for counter, position, power, index in state.data.bombs:
                if counter == state.getFramesUntilEnd():
                    state.bombExplode(state.data.bombs, position, power)
                    state.getAgentState(index).recoverABomb()
            state.data.bombs = [
                b for b in state.data.bombs
                if (b[0] != state.getFramesUntilEnd())
            ]

        state.updateBombScore()
        state.updateMapScore()
        # Time passes
        state.data.scoreChange += -TIME_PENALTY  # Penalty for waiting around

        # Resolve multi-agent effects
        #GhostRules.checkDeath( state, agentIndex )

        # Book keeping
        state.data._agentMoved = agentIndex
        state.data.score += state.data.scoreChange
        return state

    def getAgentPosition(self, agentIndex):
        return self.data.agentStates[agentIndex].getPosition()

    def getAgentState(self, agentIndex):
        return self.data.agentStates[agentIndex]

    def getNumAgents(self):
        return len(self.data.agentStates)

    def getScore(self):
        return self.data.score

    def getMapScore(self, x, y=None):
        if y is None:
            try:
                x, y = x
            except:
                raise 'incomprehensible coordinates'
        return self.data.MapScore[x][y]

    def getBombScore(self, x, y=None):
        if y is None:
            try:
                x, y = x
            except:
                raise 'incomprehensible coordinates'
        return self.data.BombScore[x][y]

    def hasWall(self, x, y):
        return self.data.map.isWall((x, y))

    def isLose(self):
        return (self.getNumAgents() == 1
                and self.data._eaten[0] == 0) or (self.data._eaten.count(0)
                                                  == self.getNumAgents())

    def isWin(self):
        return (self.getNumAgents() != 1
                and self.data._eaten.count(0) is self.getNumAgents() - 1)

    def getFramesUntilEnd(self):
        return self.data.FramesUntilEnd

    def minusOneFrame(self):
        self.data.FramesUntilEnd = self.data.FramesUntilEnd - 1
        return self.data.FramesUntilEnd

    def layABomb(self, agentIndex, pos):
        self.data._bombLaid.append(pos)
        self.data.map.add_bomb(pos)
        self.getAgentState(agentIndex).minusABomb()
        self.data.bombs.append(
            (self.data.FramesUntilEnd - BOMB_DURATION, pos,
             self.getAgentState(agentIndex).getBombPower(), agentIndex))

    def bombExplode(self, bombs, position, power):
        x_int, y_int = position
        if not self.data.map.isBomb(position): return
        self.data._bombExplode.append(position)
        self.data.map.remove_object(position)
        fired = []
        for i in range(len(self.data._fire)):
            fired += self.data._fire[i]

        if not position in fired:
            self.checkDie(position)
            self.data._fire[0].append(position)
            fired.append(position)
        for vec in [
                v for dir, v in Actions._directionsAsList
                if (not dir in [Actions.LAY, Directions.STOP])
        ]:
            isbreak = False
            i = 0
            dx, dy = vec
            next_y, next_x = y_int, x_int
            while not isbreak and i < power:
                i = i + 1
                next_y = int(next_y + dy)
                next_x = int(next_x + dx)
                pos = (next_x, next_y)
                if pos in fired: continue
                if self.data.map.isEmpty(pos):
                    self.checkDie(pos)
                    self.data._fire[i].append(pos)
                    fired.append(pos)
                elif self.data.map.isBlock(pos):
                    isbreak = True
                    self.data._blockBroken.append(pos)
                    res = self.data.map.remove_object(pos)
                    self.data._fire[i].append(pos)
                    fired.append(pos)
                    if res != None:
                        self.data._itemDrop.append((next_x, next_y, res))
                elif self.data.map.isWall(pos):
                    isbreak = True
                elif self.data.map.isItem(pos):
                    self.data._itemEaten.append(pos)
                    self.data.map.remove_object(pos)
                    self.data._fire[i].append(pos)
                    fired.append(pos)
                    self.checkDie(pos)
                elif self.data.map.isBomb(pos):
                    self.checkDie(pos)
                    self.data._fire[i].append(pos)
                    fired.append(pos)
                    bombSweep = [(idx, bomb) for idx, bomb in enumerate(bombs)
                                 if (pos in bomb) and (
                                     bomb[0] < self.data.FramesUntilEnd -
                                     int(BOMB_DURATION / 10))]
                    if len(bombSweep) is 1:
                        bombs[bombSweep[0][0]] = (
                            self.data.FramesUntilEnd -
                            int(BOMB_DURATION / 10), ) + bombSweep[0][1][1:]

    def checkDie(self, position):
        x, y = position
        for index, agent in enumerate(self.data.agentStates):
            if self.data._eaten[index] is 0: continue
            sx, sy = agent.getPosition()
            sx, sy = round(sx), round(sy)
            if manhattanDistance(position, (sx, sy)) <= 0.5:
                self.data._eaten[index] -= 1
                agent.configuration = agent.start

    def updateBombScore(self):
        # The change to the BombScore:
        self.data.BombScore.data = [[0 for y in range(self.data.map.height)]
                                    for x in range(self.data.map.width)]
        for counter, pos, power, index in self.data.bombs:
            score = self.calBombScore(counter)
            self.data.BombScore[pos[0]][pos[1]] += score
            isbreak = False
            for vec in [
                    v for dir, v in Actions._directionsAsList
                    if (not dir in [Actions.LAY, Directions.STOP])
            ]:
                isbreak = False
                i = 0
                dx, dy = vec
                next_x, next_y = pos
                while not isbreak and i < power:
                    i += 1
                    next_x = int(next_x + dx)
                    next_y = int(next_y + dy)
                    if self.data.map.isBlock(
                        (next_x, next_y)) or self.data.map.isWall(
                            (next_x, next_y)):
                        isbreak = True
                    else:
                        self.data.BombScore[next_x][next_y] += score - i / 5.0

    def updateMapScore(self):
        self.data.MapScore.data = [[0 for y in range(self.data.map.height)]
                                   for x in range(self.data.map.width)]
        for x in range(self.data.map.width):
            for y in range(self.data.map.height):
                if not self.data.map.isBlocked((x, y)) or self.data.map.isBomb(
                    (x, y)):
                    main = [
                        self.data.map.isBlocked((row, col))
                        for row, col in [(x + 1, y), (x - 1,
                                                      y), (x, y + 1), (x,
                                                                       y - 1)]
                    ]
                    second = [
                        self.data.map.isBlocked((row, col))
                        for row, col in [(x + 1,
                                          y + 1), (x - 1,
                                                   y + 1), (x + 1, y -
                                                            1), (x - 1, y - 1)]
                    ]
                    self.data.MapScore[x][y] = (main.count(True) * 1 +
                                                second.count(True) * 0.4)
                    if main.count(True) == 4: self.data.MapScore[x][y] = 100
                    if self.data.map.isBomb((x, y)):
                        self.data.MapScore[x][y] += 1

    def calBombScore(self, counter):
        if self.getFramesUntilEnd() - 1 == counter:  # next frame would explode
            return 100

        return 3 * (BOMB_DURATION - (self.getFramesUntilEnd() - counter))

    def getTotalLives(self, indexes):
        return sum([self.data._eaten[index] for index in indexes])

    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__(self, prevState=None):
        """
    Generates a new state by copying information from its predecessor.
    """
        if prevState != None:  # Initial state
            self.data = GameStateData(prevState.data)
        else:
            self.data = GameStateData()

    def deepCopy(self):
        state = GameState(self)
        state.data = self.data.deepCopy()
        return state

    def __eq__(self, other):
        """
    Allows two states to be compared.
    """
        return self.data == other.data

    def __hash__(self):
        """
    Allows states to be keys of dictionaries.
    """
        return hash(self.data)

    def __str__(self):

        return str(self.data)

    def initialize(self, layout, numAgents=1000, timeout=3000, life=5):
        """
    Creates an initial game state from a layout array (see layout.py).
    """
        self.data.initialize(layout, numAgents, timeout, life, BOMB_DURATION)
Пример #10
0
class GameState:
    def getLegalActions(self, agentIndex=0):

        if self.isWin() or self.isLose(): return []

        if agentIndex == 0:  # Pacman is moving
            return PacmanRules.getLegalActions(self)
        else:
            return GhostRules.getLegalActions(self, agentIndex)

    def generateSuccessor(self, agentIndex, action):
        """
    Returns the successor state after the specified agent takes the action.
    """
        # Check that successors exist
        if self.isWin() or self.isLose():
            raise Exception('Can\'t generate a successor of a terminal state.')

        # Copy current state
        state = GameState(self)

        # Let agent's logic deal with its action's effects on the board
        if agentIndex == 0:  # Pacman is moving
            state.data._eaten = [False for i in range(state.getNumAgents())]
            PacmanRules.applyAction(state, action)
        else:  # A ghost is moving
            GhostRules.applyAction(state, action, agentIndex)

        # Time passes
        if agentIndex == 0:
            state.data.scoreChange += -TIME_PENALTY  # Penalty for waiting around
        else:
            GhostRules.decrementTimer(state.data.agentStates[agentIndex])

        # Resolve multi-agent effects
        GhostRules.checkDeath(state, agentIndex)

        # Book keeping
        state.data._agentMoved = agentIndex
        state.data.score += state.data.scoreChange
        return state

    def getLegalPacmanActions(self):
        return self.getLegalActions(0)

    def generatePacmanSuccessor(self, action):
        """
    Generates the successor state after the specified pacman move
    """
        return self.generateSuccessor(0, action)

    def getPacmanState(self):
        """
    Returns an AgentState object for pacman (in game.py)

    state.pos gives the current position
    state.direction gives the travel vector
    """
        return self.data.agentStates[0].copy()

    def getPacmanPosition(self):
        return self.data.agentStates[0].getPosition()

    def getGhostStates(self):
        return self.data.agentStates[1:]

    def getGhostState(self, agentIndex):
        if agentIndex == 0 or agentIndex >= self.getNumAgents():
            raise Exception("Invalid index passed to getGhostState")
        return self.data.agentStates[agentIndex]

    def getGhostPosition(self, agentIndex):
        if agentIndex == 0:
            raise Exception("Pacman's index passed to getGhostPosition")
        return self.data.agentStates[agentIndex].getPosition()

    def getGhostPositions(self):
        return [s.getPosition() for s in self.getGhostStates()]

    def getNumAgents(self):
        return len(self.data.agentStates)

    def getScore(self):
        return self.data.score

    def getCapsules(self):
        """
    Returns a list of positions (x,y) of the remaining capsules.
    """
        return self.data.capsules

    def getNumFood(self):
        return self.data.food.count()

    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 call

    currentFood = state.getFood()
    if currentFood[x][y] == True: ...
    """
        return self.data.food

    def getWalls(self):
        """
    Returns a Grid of boolean wall indicator variables.

    Grids can be accessed via list notation, so to check
    if there is food at (x,y), just call

    walls = state.getWalls()
    if walls[x][y] == True: ...
    """
        return self.data.layout.walls

    def hasFood(self, x, y):
        return self.data.food[x][y]

    def hasWall(self, x, y):
        return self.data.layout.walls[x][y]

    def isLose(self):
        return self.data._lose

    def isWin(self):
        return self.data._win

    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__(self, prevState=None):
        """
    Generates a new state by copying information from its predecessor.
    """
        if prevState != None:  # Initial state
            self.data = GameStateData(prevState.data)
        else:
            self.data = GameStateData()

    def deepCopy(self):
        state = GameState(self)
        state.data = self.data.deepCopy()
        return state

    def __eq__(self, other):
        """
    Allows two states to be compared.
    """
        return self.data == other.data

    def __hash__(self):
        """
    Allows states to be keys of dictionaries.
    """
        return hash(self.data)

    def __str__(self):

        return str(self.data)

    def initialize(self, layout, numGhostAgents=1000):
        """
    Creates an initial game state from a layout array (see layout.py).
    """
        self.data.initialize(layout, numGhostAgents)
Пример #11
0
class GameState:

    explored = set()
    def getAndResetExplored():
        tmp = GameState.explored.copy()
        GameState.explored = set()
        return tmp
    getAndResetExplored = staticmethod(getAndResetExplored)

    def getLegalActions( self, agentIndex=0 ):


        if self.isWin() or self.isLose(): return []

        if agentIndex == 0:  # Pacman is moving
            return PacmanRules.getLegalActions( self )
        else:
            return GhostRules.getLegalActions( self, agentIndex )

    def generateSuccessor( self, agentIndex, action):

        if self.isWin() or self.isLose(): raise Exception('Can\'t generate a successor of a terminal state.')


        state = GameState(self)


        if agentIndex == 0:
            state.data._eaten = [False for i in range(state.getNumAgents())]
            PacmanRules.applyAction( state, action )
        else:
            GhostRules.applyAction( state, action, agentIndex )


        if agentIndex == 0:
            state.data.scoreChange += -TIME_PENALTY
        else:
            GhostRules.decrementTimer( state.data.agentStates[agentIndex] )


        GhostRules.checkDeath( state, agentIndex )


        state.data._agentMoved = agentIndex
        state.data.score += state.data.scoreChange
        GameState.explored.add(self)
        GameState.explored.add(state)
        return state

    def getLegalPacmanActions( self ):
        return self.getLegalActions( 0 )

    def generatePacmanSuccessor( self, action ):

        return self.generateSuccessor( 0, action )

    def getPacmanState( self ):

        return self.data.agentStates[0].copy()

    def getPacmanPosition( self ):
        return self.data.agentStates[0].getPosition()

    def getGhostStates( self ):
        return self.data.agentStates[1:]

    def getGhostState( self, agentIndex ):
        if agentIndex == 0 or agentIndex >= self.getNumAgents():
            raise Exception("Invalid index passed to getGhostState")
        return self.data.agentStates[agentIndex]

    def getGhostPosition( self, agentIndex ):
        if agentIndex == 0:
            raise Exception("Pacman's index passed to getGhostPosition")
        return self.data.agentStates[agentIndex].getPosition()

    def getGhostPositions(self):
        return [s.getPosition() for s in self.getGhostStates()]

    def getNumAgents( self ):
        return len( self.data.agentStates )

    def getScore( self ):
        return float(self.data.score)

    def getCapsules(self):

        return self.data.capsules

    def getNumFood( self ):
        return self.data.food.count()

    def getFood(self):

        return self.data.food

    def getWalls(self):

        return self.data.layout.walls

    def hasFood(self, x, y):
        return self.data.food[x][y]

    def hasWall(self, x, y):
        return self.data.layout.walls[x][y]

    def isLose( self ):
        return self.data._lose

    def isWin( self ):
        return self.data._win


    def __init__( self, prevState = None ):
        """
        Generates a new state by copying information from its predecessor.
        """
        if prevState != None: # Initial state
            self.data = GameStateData(prevState.data)
        else:
            self.data = GameStateData()

    def deepCopy( self ):
        state = GameState( self )
        state.data = self.data.deepCopy()
        return state

    def __eq__( self, other ):

        return hasattr(other, 'data') and self.data == other.data

    def __hash__( self ):

        return hash( self.data )

    def __str__( self ):

        return str(self.data)

    def initialize( self, layout, numGhostAgents=1000 ):

        self.data.initialize(layout, numGhostAgents)
Пример #12
0
class GameState:
    """
    Un GameState (Estado del juego) especifica el estado completo del juego,
    incluyendo la comida, capsulas, configuraciones del agente y cambios en el
    puntaje.

    Los GameStates son utilizados por el objeto Game para caputar el estado acutal
    del juego y puede ser utilizado por los agentes para razonar sobre el juego.

    Mucha de la información en un GameState está almacenada en un objeto GameStateData.
    Recomendamos fuertemente que accedas a esa información por medio de los métodos
    descritos debajo que en lugar de utilizar el objeto GameStateData directamente.

    Observa que en Pacman clásico, Pacman siempre es el agente 0.
    """

    ##############################################################
    # Metodos de acceso: usa estos para acceder a GameStateData #
    ############################################################

    # static variable keeps track of which states have had getLegalActions called
    explored = set()

    def getAndResetExplored():
        tmp = GameState.explored.copy()
        GameState.explored = set()
        return tmp

    getAndResetExplored = staticmethod(getAndResetExplored)

    def getLegalActions(self, agentIndex=0):
        """
        Retorna las acciones legales del agente especificado
        """
        # GameState.explored.add(self)
        if self.isWin() or self.isLose(): return []

        if agentIndex == 0:  # Pacman está en movimiento
            return PacmanRules.getLegalActions(self)
        else:
            return GhostRules.getLegalActions(self, agentIndex)

    def generateSuccessor(self, agentIndex, action):
        """
        Retorna el estado sucesor después de que el agente especificado realiza la acción
        """
        # Verifica que los sucesores existen
        if self.isWin() or self.isLose():
            raise Exception(
                'No se puede generar un sucesor de un estado terminal')

        # Copy current state
        state = GameState(self)

        # Let agent's logic deal with its action's effects on the board
        if agentIndex == 0:  # Pacman is moving
            state.data._eaten = [False for i in range(state.getNumAgents())]
            PacmanRules.applyAction(state, action)
        else:  # A ghost is moving
            GhostRules.applyAction(state, action, agentIndex)

        # Time passes
        if agentIndex == 0:
            state.data.scoreChange += -TIME_PENALTY  # Penalty for waiting around
        else:
            GhostRules.decrementTimer(state.data.agentStates[agentIndex])

        # Resolve multi-agent effects
        GhostRules.checkDeath(state, agentIndex)

        # Book keeping
        state.data._agentMoved = agentIndex
        state.data.score += state.data.scoreChange
        GameState.explored.add(self)
        GameState.explored.add(state)
        return state

    def getLegalPacmanActions(self):
        return self.getLegalActions(0)

    def generatePacmanSuccessor(self, action):
        """
        Genera el estado sucesor después del movimiento de Pacman especificado
        """
        return self.generateSuccessor(0, action)

    def getPacmanState(self):
        """
        Regresa un objeto AgentState para Pacman (en game.py)

        state.pos gives da la posición actual
        state.direction da la dirección del vector de viaje
        """
        return self.data.agentStates[0].copy()

    def getPacmanPosition(self):
        return self.data.agentStates[0].getPosition()

    def getGhostStates(self):
        return self.data.agentStates[1:]

    def getGhostState(self, agentIndex):
        if agentIndex == 0 or agentIndex >= self.getNumAgents():
            raise Exception("Invalid index passed to getGhostState")
        return self.data.agentStates[agentIndex]

    def getGhostPosition(self, agentIndex):
        if agentIndex == 0:
            raise Exception("Pacman's index passed to getGhostPosition")
        return self.data.agentStates[agentIndex].getPosition()

    def getGhostPositions(self):
        return [s.getPosition() for s in self.getGhostStates()]

    def getNumAgents(self):
        return len(self.data.agentStates)

    def getScore(self):
        return float(self.data.score)

    def getCapsules(self):
        """
        Retorna una lista de posiciones (x,y) de las capsulas restantes.
        """
        return self.data.capsules

    def getNumFood(self):
        return self.data.food.count()

    def getFood(self):
        """
        Regresa un Grid de variables booleanas que indican el estado de la comida.

        Los Grids pueden ser accesados utilizando la notación de lista, asi que para
        verificar si hay comida en (x,y), simplemente llama

        currentFood = state.getFood()
        if currentFood[x][y] == True: ...
        """
        return self.data.food

    def getWalls(self):
        """
        Retorna un Grid de variables booleanas que indican la posición de las paredes.

        Los Grids pueden ser accesados utilizando la notación de lista, asi que para
        verificar si hay una pared en (x,y), simplemente llama

        walls = state.getWalls()
        if walls[x][y] == True: ...
        """
        return self.data.layout.walls

    def hasFood(self, x, y):
        return self.data.food[x][y]

    def hasWall(self, x, y):
        return self.data.layout.walls[x][y]

    def isLose(self):
        return self.data._lose

    def isWin(self):
        return self.data._win

    #####################################################
    #             Métodos auxiliares:                   #
    # No deberías llamar a estos métodos directamente   #
    #####################################################

    def __init__(self, prevState=None):
        """
        Generates a new state by copying information from its predecessor.
        """
        if prevState != None:  # Initial state
            self.data = GameStateData(prevState.data)
        else:
            self.data = GameStateData()

    def deepCopy(self):
        state = GameState(self)
        state.data = self.data.deepCopy()
        return state

    def __eq__(self, other):
        """
        Allows two states to be compared.
        """
        return hasattr(other, 'data') and self.data == other.data

    def __hash__(self):
        """
        Allows states to be keys of dictionaries.
        """
        return hash(self.data)

    def __str__(self):

        return str(self.data)

    def initialize(self, layout, numGhostAgents=1000):
        """
        Creates an initial game state from a layout array (see layout.py).
        """
        self.data.initialize(layout, numGhostAgents)
class GameState:
    """
    A GameState specifies the full game state, including the food, capsules,
    agent configurations and score changes.

    GameStates are used by the Game object to capture the actual state of the game and
    can be used by agents to reason about the game.

    Much of the information in a GameState is stored in a GameStateData object.  We
    strongly suggest that you access that data via the accessor methods below rather
    than referring to the GameStateData object directly.

    Note that in classic Pacman, Pacman is always agent 0.
    """

    ####################################################
    # Accessor methods: use these to access state data #
    ####################################################

    def getLegalActions(self, agentIndex=0):
        """
        Returns the legal actions for the agent specified.
        """
        if self.isWin() or self.isLose(): return []

        if agentIndex == 0:  # Pacman is moving
            return PacmanRules.getLegalActions(self)
        else:
            return GhostRules.getLegalActions(self, agentIndex)

    def generateSuccessor(self, agentIndex, action):
        """
        Returns the successor state after the specified agent takes the action.
        """
        # Check that successors exist
        if self.isWin() or self.isLose():
            raise Exception('Can\'t generate a successor of a terminal state.')

        # Copy current state
        state = GameState(self)

        # Let agent's logic deal with its action's effects on the board
        if agentIndex == 0:  # Pacman is moving
            state.data._eaten = [False for i in range(state.getNumAgents())]
            PacmanRules.applyAction(state, action)
        else:  # A ghost is moving
            GhostRules.applyAction(state, action, agentIndex)

        # Time passes
        if agentIndex == 0:
            state.data.scoreChange += -TIME_PENALTY  # Penalty for waiting around

        # Resolve multi-agent effects
        GhostRules.checkDeath(state, agentIndex)

        # Book keeping
        state.data._agentMoved = agentIndex
        state.data.score += state.data.scoreChange

        # Pacman observes neighboring squares
        state.getObservation()

        return state

    def getLegalPacmanActions(self):
        return self.getLegalActions(0)

    def generatePacmanSuccessor(self, action):
        """
        Generates the successor state after the specified pacman move
        """
        return self.generateSuccessor(0, action)

    def getPacmanState(self):
        """
        Returns an AgentState object for pacman (in game.py)

        state.pos gives the current position
        state.direction gives the travel vector
        """
        return self.data.agentStates[0].copy()

    def getPacmanPosition(self):
        return self.data.agentStates[0].getPosition()

    def getNumAgents(self):
        return len(self.data.agentStates)

    def getScore(self):
        return self.data.score

    def isLose(self):
        return self.data._lose

    def isWin(self):
        return self.data._win

    ################################
    # Additions for Hunters Pacman #
    ################################

    def getObservation(self):
        x, y = self.getPacmanPosition()
        adjacent = [(x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)]
        for x, y in adjacent:
            self.data.observedPositions[x][y] = True
        return {(x, y): self.squareInfo(x, y) for x, y in adjacent}

    def squareInfo(self, x, y):
        if self.hasWall(x, y):
            return WALL_STRING
        elif self.data.layout.redWalls[x][y]:
            return RED_WALL_STRING
        elif self.data.layout.blueWalls[x][y]:
            return BLUE_WALL_STRING
        else:
            return EMPTY_SQUARE_STRING

    def getObservedPositions(self):
        return self.data.observedPositions

    def getHouseWalls(self, house):
        return layout.buildHouseAroundCenter(*house)

    def getPossibleHouses(self):
        return layout.pickPossibleLocations(self.data.layout.width,
                                            self.data.layout.height)

    def getEvidence(self):
        evidence = {}
        possible = {
            w
            for h in self.getPossibleHouses() for w in self.getHouseWalls(h)
        }
        for pos in self.getObservedPositions().asList():
            if pos in possible:
                evidence[pos] = self.squareInfo(*pos)
        return evidence

    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__(self, prevState=None):
        """
        Generates a new state by copying information from its predecessor.
        """
        if prevState != None:
            self.data = GameStateData(prevState.data)
            self.numMoves = prevState.numMoves
            self.maxMoves = prevState.maxMoves
        else:  # Initial state
            self.data = GameStateData()
            self.numMoves = 0
            self.maxMoves = -1

    def deepCopy(self):
        state = GameState(self)
        state.data = self.data.deepCopy()
        return state

    def __eq__(self, other):
        """
        Allows two states to be compared.
        """
        return self.data == other.data

    def __hash__(self):
        """
        Allows states to be keys of dictionaries.
        """
        return hash(str(self))

    def __str__(self):

        return str(self.data)

    def initialize(self, layout, numGhostAgents=1000):
        """
        Creates an initial game state from a layout array (see layout.py).
        """
        self.data.initialize(layout, numGhostAgents)

    def getGhostPosition(self, agentIndex):
        if agentIndex == 0:
            raise "Pacman's index passed to getGhostPosition"
        return self.data.agentStates[agentIndex].getPosition()

    def getGhostState(self, agentIndex):
        if agentIndex == 0:
            raise "Pacman's index passed to getGhostPosition"
        return self.data.agentStates[agentIndex]

    def getCapsules(self):
        """
        Returns a list of positions (x,y) of the remaining capsules.
        """
        return self.data.capsules

    def getNumFood(self):
        return self.data.food.count()

    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 call

        currentFood = state.getFood()
        if currentFood[x][y] == True: ...
        """
        return self.data.food

    def getWalls(self):
        """
        Returns a Grid of boolean wall indicator variables.

        Grids can be accessed via list notation, so to check
        if there is food at (x,y), just call

        walls = state.getWalls()
        if walls[x][y] == True: ...
        """
        return self.data.layout.walls

    def hasFood(self, x, y):
        return self.data.food[x][y]

    def hasWall(self, x, y):
        return self.data.layout.walls[x][y]
Пример #14
0
class GameState:
    """
    A GameState specifies the full game state, including the food, capsules,
    agent configurations and score changes.

    GameStates are used by the Game object to capture the actual state of the game and
    can be used by agents to reason about the game.

    Much of the information in a GameState is stored in a GameStateData object.  We
    strongly suggest that you access that data via the accessor methods below rather
    than referring to the GameStateData object directly.

    Note that in classic Pacman, Pacman is always agent 0.
    """

    ####################################################
    # Accessor methods: use these to access state data #
    ####################################################

    def getLegalActions(self, agentIndex=0):
        """
        Returns the legal actions for the agent specified.
        """
        if self.isWin() or self.isLose():
            return []

        if agentIndex == 0:  # Pacman is moving
            return PacmanRules.getLegalActions(self)
        else:
            return GhostRules.getLegalActions(self, agentIndex)

    def generateSuccessor(self, agentIndex, action):
        """
        Returns the successor state after the specified agent takes the action.
        """
        # Check that successors exist
        if self.isWin() or self.isLose():
            raise Exception("Can't generate a successor of a terminal state.")

        # Copy current state
        state = GameState(self)

        # Let agent's logic deal with its action's effects on the board
        if agentIndex == 0:  # Pacman is moving
            state.data._eaten = [False for i in range(state.getNumAgents())]
            PacmanRules.applyAction(state, action)
        else:  # A ghost is moving
            GhostRules.applyAction(state, action, agentIndex)

        # Time passes
        if agentIndex == 0:
            state.data.scoreChange += -TIME_PENALTY  # Penalty for waiting around

        # Resolve multi-agent effects
        GhostRules.checkDeath(state, agentIndex)

        # Book keeping
        state.data._agentMoved = agentIndex
        state.data.score += state.data.scoreChange

        # Pacman observes neighboring squares
        state.getObservation()

        return state

    def getLegalPacmanActions(self):
        return self.getLegalActions(0)

    def generatePacmanSuccessor(self, action):
        """
        Generates the successor state after the specified pacman move
        """
        return self.generateSuccessor(0, action)

    def getPacmanState(self):
        """
        Returns an AgentState object for pacman (in game.py)

        state.pos gives the current position
        state.direction gives the travel vector
        """
        return self.data.agentStates[0].copy()

    def getPacmanPosition(self):
        return self.data.agentStates[0].getPosition()

    def getNumAgents(self):
        return len(self.data.agentStates)

    def getScore(self):
        return self.data.score

    def isLose(self):
        return self.data._lose

    def isWin(self):
        return self.data._win

    ################################
    # Additions for Hunters Pacman #
    ################################

    def getObservation(self):
        x, y = self.getPacmanPosition()
        adjacent = [(x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)]
        for x, y in adjacent:
            self.data.observedPositions[x][y] = True
        return {(x, y): self.squareInfo(x, y) for x, y in adjacent}

    def squareInfo(self, x, y):
        if self.hasWall(x, y):
            return WALL_STRING
        elif self.data.layout.redWalls[x][y]:
            return RED_WALL_STRING
        elif self.data.layout.blueWalls[x][y]:
            return BLUE_WALL_STRING
        else:
            return EMPTY_SQUARE_STRING

    def getObservedPositions(self):
        return self.data.observedPositions

    def getHouseWalls(self, house):
        return layout.buildHouseAroundCenter(*house)

    def getPossibleHouses(self):
        return layout.pickPossibleLocations(self.data.layout.width, self.data.layout.height)

    def getEvidence(self):
        evidence = {}
        possible = {w for h in self.getPossibleHouses() for w in self.getHouseWalls(h)}
        for pos in self.getObservedPositions().asList():
            if pos in possible:
                evidence[pos] = self.squareInfo(*pos)
        return evidence

    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__(self, prevState=None):
        """
        Generates a new state by copying information from its predecessor.
        """
        if prevState != None:
            self.data = GameStateData(prevState.data)
            self.numMoves = prevState.numMoves
            self.maxMoves = prevState.maxMoves
        else:  # Initial state
            self.data = GameStateData()
            self.numMoves = 0
            self.maxMoves = -1

    def deepCopy(self):
        state = GameState(self)
        state.data = self.data.deepCopy()
        return state

    def __eq__(self, other):
        """
        Allows two states to be compared.
        """
        return self.data == other.data

    def __hash__(self):
        """
        Allows states to be keys of dictionaries.
        """
        return hash(str(self))

    def __str__(self):

        return str(self.data)

    def initialize(self, layout, numGhostAgents=1000):
        """
        Creates an initial game state from a layout array (see layout.py).
        """
        self.data.initialize(layout, numGhostAgents)

    def getGhostPosition(self, agentIndex):
        if agentIndex == 0:
            raise "Pacman's index passed to getGhostPosition"
        return self.data.agentStates[agentIndex].getPosition()

    def getGhostState(self, agentIndex):
        if agentIndex == 0:
            raise "Pacman's index passed to getGhostPosition"
        return self.data.agentStates[agentIndex]

    def getCapsules(self):
        """
        Returns a list of positions (x,y) of the remaining capsules.
        """
        return self.data.capsules

    def getNumFood(self):
        return self.data.food.count()

    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 call

        currentFood = state.getFood()
        if currentFood[x][y] == True: ...
        """
        return self.data.food

    def getWalls(self):
        """
        Returns a Grid of boolean wall indicator variables.

        Grids can be accessed via list notation, so to check
        if there is food at (x,y), just call

        walls = state.getWalls()
        if walls[x][y] == True: ...
        """
        return self.data.layout.walls

    def hasFood(self, x, y):
        return self.data.food[x][y]

    def hasWall(self, x, y):
        return self.data.layout.walls[x][y]
Пример #15
0
class GameState:
    """A GameState specifies the full game state.

    Full game state includes the food, capsules, agent configurations,
    and score changes.

    GameStates are used by the Game object to capture the actual state of
    the game and can be used by agents to reason about the game.

    Much of the information in a GameState is stored in a GameStateData object.
    We strongly suggest that you access that data via the accessor methods
    below rather than referring to the GameStateData object directly.
    """

    ####################################################
    # Accessor methods: use these to access state data #
    ####################################################

    def get_legal_actions(self, agent_index=0):
        """Return the legal actions for the agent specified."""
        return AgentRules.get_legal_actions(self, agent_index)

    def generate_successor(self, agent_index, action):
        """Return the successor after the specified agent takes the action.

        Returns a GameState object
        """
        # Copy current state
        state = GameState(self)

        # Find appropriate rules for the agent
        AgentRules.apply_action(state, action, agent_index)
        AgentRules.check_death(state, agent_index)
        AgentRules.decrement_timer(state.data.agent_states[agent_index])

        # Book keeping
        state.data._agent_moved = agent_index
        state.data.score += state.data.score_change
        state.data.timeleft = self.data.timeleft - 1
        return state

    def get_agent_state(self, index):
        """Return the state (game.AgentState) of agent with given index."""
        return self.data.agent_states[index]

    def get_agent_position(self, index):
        """Attempt to get agent position.

        Return a location tuple if the agent with the given index is
        observable; if the agent is unobservable, return None.
        """
        agent_state = self.data.agent_states[index]
        ret = agent_state.get_position()
        if ret:
            return tuple(int(x) for x in ret)
        return ret

    def get_num_agents(self):
        """Return number of agents."""
        return len(self.data.agent_states)

    def get_score(self):
        """Return a number corresponding to the current score."""
        return self.data.score

    def get_red_food(self):
        """Return a matrix of food on the red team's side.

        For the matrix m, m[x][y]=true if there is food in (x,y) that belongs
        to red (meaning red is protecting it, blue is trying to eat it).
        """
        return half_grid(self.data.food, red=True)

    def get_blue_food(self):
        """Return a matrix of food on the blue team's side.

        For the matrix m, m[x][y]=true if there is food in (x,y) that belongs
        to blue (meaning blue is protecting it, red is trying to eat it).
        """
        return half_grid(self.data.food, red=False)

    def get_red_capsules(self):
        """Return list of capsule positions (x,y) on the red team's side."""
        return half_list(self.data.capsules, self.data.food, red=True)

    def get_blue_capsules(self):
        """Retun list of capsule positions (x,y) on the blue team's side."""
        return half_list(self.data.capsules, self.data.food, red=False)

    def get_walls(self):
        """Return a matrix of wall positions."""
        return self.data.layout.walls

    def has_food(self, x, y):
        """Return true if the location (x,y) has food.

        This is regardless of whether it's blue team food or red team food.
        """
        return self.data.food[x][y]

    def has_wall(self, x, y):
        """Return true if (x,y) has a wall, false otherwise."""
        return self.data.layout.walls[x][y]

    def is_over(self):
        """Return if game is over."""
        return self.data._win

    def get_red_team_indices(self):
        """Return a list of agent indices for the agents on the red team."""
        return self.red_team[:]

    def get_blue_team_indices(self):
        """Return a list of agent indices for the agents on the blue team."""
        return self.blue_team[:]

    def is_on_red_team(self, agent_index):
        """Return true if the agent is on the red team."""
        return self.teams[agent_index]

    def get_agent_distances(self):
        """Return a noisy distance to each agent."""
        if 'agent_distances' in dir(self):
            return self.agent_distances
        else:
            return None

    def get_distance_prob(self, true_distance, noisy_distance):
        """Return the probability of noisy_distance given true_distance."""
        if noisy_distance - true_distance in SONAR_NOISE_VALUES:
            return 1.0 / SONAR_NOISE_RANGE
        else:
            return 0

    def get_initial_agent_position(self, agent_index):
        """Return the initial position of an agent."""
        return self.data.layout.agent_positions[agent_index][1]

    def get_capsules(self):
        """Return a list of positions (x,y) of the remaining capsules."""
        return self.data.capsules

    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__(self, prev_state=None):
        """Generate a new state by copying information from its predecessor."""
        if prev_state is not None:  # Initial state
            self.data = GameStateData(prev_state.data)
            self.blue_team = prev_state.blue_team
            self.red_team = prev_state.red_team
            self.data.timeleft = prev_state.data.timeleft

            self.teams = prev_state.teams
            self.agent_distances = prev_state.agent_distances
        else:
            self.data = GameStateData()
            self.agent_distances = []

    def deep_copy(self):
        """Return a deep copy of this state."""
        state = GameState(self)
        state.data = self.data.deep_copy()
        state.data.timeleft = self.data.timeleft

        state.blue_team = self.blue_team[:]
        state.red_team = self.red_team[:]
        state.teams = self.teams[:]
        state.agent_distances = self.agent_distances[:]
        return state

    def make_observation(self, index):
        """Make observation for agent with given index.

        Return a GameState instance.
        """
        state = self.deep_copy()

        # Adds the sonar signal
        pos = state.get_agent_position(index)
        n = state.get_num_agents()
        distances = [
            noisy_distance(pos, state.get_agent_position(i)) for i in range(n)
        ]
        state.agent_distances = distances

        # Remove states of distant opponents
        if index in self.blue_team:
            team = self.blue_team
            other_team = self.red_team
        else:
            other_team = self.blue_team
            team = self.red_team

        for enemy in other_team:
            seen = False
            enemy_pos = state.get_agent_position(enemy)
            for teammate in team:
                if ((util.manhattan_distance(
                        enemy_pos, state.get_agent_position(teammate)) <=
                     SIGHT_RANGE)):
                    seen = True
            if not seen:
                state.data.agent_states[enemy].configuration = None
        return state

    def __eq__(self, other):
        """Allow two states to be compared."""
        if other is None:
            return False
        return self.data == other.data

    def __hash__(self):
        """Allow states to be keys of dictionaries."""
        return int(hash(self.data))

    def __str__(self):
        """Allow conversion to string."""
        return str(self.data)

    def initialize(self, layout, num_agents):
        """Create an initial game state from a layout array (see layout.py)."""
        self.data.initialize(layout, num_agents)
        positions = [a.configuration for a in self.data.agent_states]
        self.blue_team = [
            i for i, p in enumerate(positions) if not self.is_red(p)
        ]
        self.red_team = [i for i, p in enumerate(positions) if self.is_red(p)]
        self.teams = [self.is_red(p) for p in positions]
        # This is usually 60 (always 60 with random maps)
        # However, if layout map is specified otherwise, it could be less
        global TOTAL_FOOD
        TOTAL_FOOD = layout.total_food

    def is_red(self, config_or_pos):
        """Determine if position in on the red side of the board."""
        width = self.data.layout.width
        if isinstance(config_or_pos, tuple):
            return config_or_pos[0] < width / 2
        else:
            return config_or_pos.position[0] < width / 2
class GameState(object):
    """
    A GameState specifies the full game state, including the food, capsules,
    agent configurations and score changes.

    GameStates are used by the Game object to capture the actual state of the game and
    can be used by agents to reason about the game.

    Much of the information in a GameState is stored in a GameStateData object.  We
    strongly suggest that you access that data via the accessor methods below rather
    than referring to the GameStateData object directly.

    Note that in classic Pacman, Pacman is always agent 0.
    """

    ####################################################
    # Accessor methods: use these to access state data #
    ####################################################
    ghostDirections = {}

    def getLegalActions( self, agentIndex=0 ):
        """
        Returns the legal actions for the agent specified.
        """
        if self.isWin() or self.isLose():
            return []

        if agentIndex == 0:  # Pacman is moving
            return PacmanRules.getLegalActions( self )
        else:
            return GhostRules.getLegalActions( self, agentIndex )

    def generateSuccessor( self, agentIndex, action):
        """
        Returns the successor state after the specified agent takes the action.
        """
        # Check that successors exist
        if self.isWin() or self.isLose(): raise Exception('Can\'t generate a successor of a terminal state.')

        # Copy current state
        state = GameState(self)

        # Let agent's logic deal with its action's effects on the board
        if agentIndex == 0:  # Pacman is moving
            state.data._eaten = [False for i in range(state.getNumAgents())]
            PacmanRules.applyAction( state, action )
        else:                # A ghost is moving
            GhostRules.applyAction( state, action, agentIndex )

        # Time passes
        if agentIndex == 0:
            state.data.scoreChange += -TIME_PENALTY # Penalty for waiting around
        else:
            GhostRules.decrementTimer( state.data.agentStates[agentIndex] )

        # Resolve multi-agent effects
        GhostRules.checkDeath( state, agentIndex )

        # Check food eaten
        GhostRules.checkFoodEaten ( state, agentIndex )

        # Book keeping
        state.data._agentMoved = agentIndex
        state.data.score += state.data.scoreChange
        p = state.getPacmanPosition()
        state.data.ghostDistances = [getNoisyDistance(p, state.getGhostPosition(i)) for i in range(1,state.getNumAgents())]
        state.ghostPositions = self.ghostPositions = [self.getGhostPosition(i) for i in range(1, self.getNumAgents())]
        a = 0
        for i in range(1, self.getNumAgents()):
            self.ghostDirections[a] = (state.data.agentStates[i].configuration.getDirection())
            a += 1
        if agentIndex == self.getNumAgents() - 1:
            state.numMoves += 1
        
        return state

    def getLegalPacmanActions( self ):
        return self.getLegalActions( 0 )

    def generatePacmanSuccessor( self, action ):
        """
        Generates the successor state after the specified pacman move
        """
        return self.generateSuccessor( 0, action )

    def getPacmanState( self ):
        """
        Returns an AgentState object for pacman (in game.py)

        state.pos gives the current position
        state.direction gives the travel vector
        """
        return self.data.agentStates[0].copy()

    def getPacmanPosition( self ):
        return self.data.agentStates[0].getPosition()

    def getNumAgents( self ):
        
        try:
            return len( self.getGhostPositions() )+1
        except:
            return len( self.data.agentStates )

    def getScore( self ):
        return self.data.score

    def getCapsules(self):
        """
        Returns a list of positions (x,y) of the remaining capsules.
        """
        return self.data.capsules

    def getNumFood( self ):
        return self.data.food.count()

    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 call

        currentFood = state.getFood()
        if currentFood[x][y] == True: ...
        """
        return self.data.food

    def getWalls(self):
        """
        Returns a Grid of boolean wall indicator variables.

        Grids can be accessed via list notation, so to check
        if there is food at (x,y), just call

        walls = state.getWalls()
        if walls[x][y] == True: ...
        """
        return self.data.layout.walls

    def hasFood(self, x, y):
        return self.data.food[x][y]

    def hasWall(self, x, y):
        return self.data.layout.walls[x][y]

    ##############################
    # Additions for Busters Pacman #
    ##############################

    def getLivingGhosts(self):
        """
        Returns a list of booleans indicating which ghosts are not yet captured.

        The first entry (a placeholder for Pacman's index) is always False.
        """
        return self.livingGhosts

    def getDistanceNearestFood(self):
        """
        Returns the distance to the nearest food
        """
        if(self.getNumFood() > 0):
            minDistance = 900000
            pacmanPosition = self.getPacmanPosition()
            for i in range(self.data.layout.width):
                for j in range(self.data.layout.height):
                    if self.hasFood(i, j):
                        foodPosition = i, j
                        distance = util.manhattanDistance(pacmanPosition, foodPosition)
                        if distance < minDistance:
                            minDistance = distance
            return minDistance

        else:
            return None

    def getDistanceNearestGhost(self, x, y):
        positions = self.getGhostPositions()
        livingGhosts = self.getLivingGhosts()[1:] # Remove Pacman from list of ghosts
        ghostCount = []
        ghostPositions = []
        for i in range(len(positions)): # Store only the ghosts marked as True and their positions in the above lists

            if livingGhosts[i] == True:
                ghostCount.append(livingGhosts[i])
                ghostPositions.append(positions[i])              

        if len(ghostCount) > 0: # Check that there are still some ghosts alive
            objectPosition = (x, y)
            distances = []
            for j in ghostPositions:
                ghostPosition = j[0],j[1]
                distance = util.manhattanDistance(objectPosition, ghostPosition)
                if distance >= 0:
                    distances.append(distance)
            minDistance = min(distances)
            closestGhost = ghostPositions[distances.index(minDistance)]
        else: 
            minDistance = math.inf
            closestGhost = (-1,-1)
        return minDistance, closestGhost

    def getGhostPositions(self):
        return self.ghostPositions

    def getGhostDirections(self):
        return self.ghostDirections

    def setGhostNotLiving(self, index):
        self.livingGhosts[index] = False

    def isLose( self ):
        return self.maxMoves > 0 and self.numMoves >= self.maxMoves

    def isWin( self ):
        return self.livingGhosts.count(True) == 0

    def getNoisyGhostDistances(self):
        """
        Returns a noisy distance to each ghost.
        """
        return self.data.ghostDistances

    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__( self, prevState = None ):
        """
        Generates a new state by copying information from its predecessor.
        """
        if prevState != None:
            self.data = prevState.data.deepCopy()
            self.livingGhosts = prevState.livingGhosts[:]
            self.ghostPositions = prevState.ghostPositions[:]
            self.numMoves = prevState.numMoves;
            self.maxMoves = prevState.maxMoves;
        else: # Initial state
            self.data = GameStateData()
            self.numMoves = 0;
            self.maxMoves = -1;
            self.data.ghostDistances = []


    def deepCopy( self ):
        state = GameState( self )
        state.data = self.data.deepCopy()
        state.data.ghostDistances = self.data.ghostDistances
        return state

    def __eq__( self, other ):
        """
        Allows two states to be compared.
        """
        if (other):
            return self.data == other.data
        

    def __hash__( self ):
        """
        Allows states to be keys of dictionaries.
        """
        return hash( str( self ) )

    def __str__( self ):

        return str(self.data)

    def initialize( self, layout, numGhostAgents=1000 ):
        """
        Creates an initial game state from a layout array (see layout.py).
        """
        self.data.initialize(layout, numGhostAgents)
        self.data.ghostDistances = [getNoisyDistance(self.getPacmanPosition(), self.getGhostPosition(i)) for i in range(1, self.getNumAgents())]
        self.ghostPositions = [self.getGhostPosition(i) for i in range(1, self.getNumAgents())]
        self.livingGhosts = [False] + [True for i in range(len(self.getGhostPositions()))]

    def getGhostPosition( self, agentIndex ):
        if agentIndex == 0:
            raise Exception("Pacman's index passed to getGhostPosition")
        return self.data.agentStates[agentIndex].getPosition()
    def getGhostDirection( self, agentIndex ):
        if agentIndex == 0:
            raise Exception("Pacman's index passed to getGhostDirection")
        return self.data.agentStates[agentIndex].getDirection()

    def getGhostState( self, agentIndex ):
        if agentIndex == 0:
            raise Exception("Pacman's index passed to getGhostPosition")
        return self.data.agentStates[agentIndex]
Пример #17
0
class GameState:
  """
  A GameState specifies the full game state, including the food, capsules, 
  agent configurations and score changes.
  
  GameStates are used by the Game object to capture the actual state of the game and
  can be used by agents to reason about the game.
  
  Much of the information in a GameState is stored in a GameStateData object.  We 
  strongly suggest that you access that data via the accessor methods below rather
  than referring to the GameStateData object directly.
  """
  
  ####################################################
  # Accessor methods: use these to access state data #
  ####################################################
  
  def getLegalActions( self, agentIndex=0 ):
    """
    Returns the legal actions for the agent specified.
    """
    return AgentRules.getLegalActions( self, agentIndex )
    
  def generateSuccessor( self, agentIndex, action):
    """
    Returns the successor state after the specified agent takes the action.
    """
    # Copy current state
    state = GameState(self)

    # Find appropriate rules for the agent
    AgentRules.applyAction( state, action, agentIndex )
    AgentRules.checkDeath(state, agentIndex)
    
    # Book keeping
    state.data._agentMoved = agentIndex
    state.data.score += state.data.scoreChange
    return state
  
  def getAgentState(self, index):
    return self.data.agentStates[index]

  def getAgentPosition(self, index):
    " Note: this could return None if the agent is unobservable "
    agentState = self.data.agentStates[index]
    return agentState.getPosition()
  
  def getNumAgents( self ):
    return len( self.data.agentStates )
  
  def getScore( self ):
    return self.data.score
  
  def getRedFood(self):
    return halfGrid(self.data.food, red = True)

  def getBlueFood(self):
    return halfGrid(self.data.food, red = False)
  
  def getWalls(self):
    """
    Just like getFood but for walls
    """
    return self.data.layout.walls

  def hasFood(self, x, y):
    return self.data.food[x][y]
  
  def hasWall(self, x, y):
    return self.data.layout.walls[x][y]

  def isOver( self ):
    return self.data._win
  
  def getRedTeamIndices(self):
    return self.redTeam[:]

  def getBlueTeamIndices(self):
    return self.blueTeam[:]
  
  def isOnRedTeam(self, agentIndex):
    return self.teams[agentIndex]
  
  def getAgentDistances(self):
    "Returns a noisy distance to each agent."
    if 'agentDistances' in dir(self) : 
      return self.agentDistances
    else:
      return None
      
  #############################################
  #             Helper methods:               #          
  # You shouldn't need to call these directly #
  #############################################
  
  def __init__( self, prevState = None ):
    """ 
    Generates a new state by copying information from its predecessor.
    """
    if prevState != None: # Initial state
      self.data = GameStateData(prevState.data)
      self.blueTeam = prevState.blueTeam
      self.redTeam = prevState.redTeam
      self.teams = prevState.teams
      self.agentDistances = prevState.agentDistances
    else:
      self.data = GameStateData()
      self.agentDistances = []
    
  def deepCopy( self ):
    state = GameState( self )
    state.data = self.data.deepCopy()
    state.blueTeam = self.blueTeam[:]
    state.redTeam = self.redTeam[:]
    state.teams = self.teams[:]
    state.agentDistances = self.agentDistances[:]
    return state
    
  def makeObservation(self, index):
    state = self.deepCopy()
    
    # Adds the sonar signal
    pos = state.getAgentPosition(index)
    n = state.getNumAgents()
    distances = [noisyDistance(pos, state.getAgentPosition(i)) for i in range(n)]
    state.agentDistances = distances
    
    # Remove states of distant opponents
    if index in self.blueTeam:
      team = self.blueTeam
      otherTeam = self.redTeam
    else:
      otherTeam = self.blueTeam
      team = self.redTeam
      
    for enemy in otherTeam:
      seen = False
      enemyPos = state.getAgentPosition(enemy)
      for teammate in team:
        if util.manhattanDistance(enemyPos, state.getAgentPosition(teammate)) <= SIGHT_RANGE:
          seen = True
      if not seen: state.data.agentStates[enemy].configuration = None
    return state    

  def __eq__( self, other ):
    """
    Allows two states to be compared.
    """
    if other == None: return False
    return self.data == other.data
                                                      
  def __hash__( self ):
    """
    Allows states to be keys of dictionaries.
    """
    return int(hash( self.data ))

  def __str__( self ):
    
    return str(self.data)
      
  def initialize( self, layout, numAgents):
    """
    Creates an initial game state from a layout array (see layout.py).
    """
    self.data.initialize(layout, numAgents)
    positions = [a.configuration for a in self.data.agentStates]
    self.blueTeam = [i for i,p in enumerate(positions) if not self.isRed(p)]
    self.redTeam = [i for i,p in enumerate(positions) if self.isRed(p)]
    self.teams = [self.isRed(p) for p in positions]
  
  def isRed(self, configOrPos):
    width = self.data.layout.width
    if type(configOrPos) == type( (0,0) ):
      return configOrPos[0] < width / 2
    else:
      return configOrPos.pos[0] < width / 2
class GameState:
    """A GameState specifies the full game state.

    Full game state includes the food, capsules, agent configurations,
    and score changes.

    GameStates are used by the Game object to capture the actual state of the
    game and can be used by agents to reason about the game.

    Much of the information in a GameState is stored in a GameStateData object.
    We strongly suggest that you access that data via the accessor methods
    below rather than referring to the GameStateData object directly.

    Note that in classic Pacman, Pacman is always agent 0.
    """

    ####################################################
    # Accessor methods: use these to access state data #
    ####################################################

    # static variable keeps track of which states have had get_legal_actions
    # called
    explored = set()

    @staticmethod
    def get_and_reset_explored():
        """Return a copy of the explored set and reset the original."""
        tmp = GameState.explored.copy()
        GameState.explored = set()
        return tmp

    def get_legal_actions(self, agent_index=0):
        """Return the legal actions for the agent specified."""
        if self.is_win() or self.is_lose():
            return []

        if agent_index == 0:  # Pacman is moving
            return PacmanRules.get_legal_actions(self)
        else:
            return GhostRules.get_legal_actions(self, agent_index)

    def generate_successor(self, agent_index, action):
        """Generate the successor state after specified agent takes action."""
        # Check that successors exist
        if self.is_win() or self.is_lose():
            raise Exception('Can\'t generate a successor of a terminal state.')

        # Copy current state
        state = GameState(self)

        # Let agent's logic deal with its action's effects on the board
        if agent_index == 0:  # Pacman is moving
            state.data._eaten = [False for i in range(state.get_num_agents())]
            PacmanRules.apply_action(state, action)
        else:                # A ghost is moving
            GhostRules.apply_action(state, action, agent_index)

        # Time passes
        if agent_index == 0:
            # Penalty for waiting around
            state.data.score_change += -TIME_PENALTY
        else:
            GhostRules.decrement_timer(state.data.agent_states[agent_index])

        # Resolve multi-agent effects
        GhostRules.check_death(state, agent_index)

        # Book keeping
        state.data._agent_moved = agent_index
        state.data.score += state.data.score_change
        GameState.explored.add(self)
        GameState.explored.add(state)
        return state

    def get_legal_pacman_actions(self):
        """Return legal actions for pacman (convience function).

        (convenience function that calls get_legal_actions with pacman's index)
        """
        return self.get_legal_actions(0)

    def generate_pacman_successor(self, action):
        """Generate successor state after the specified pacman action.

        (convenience function that calls generate_successor with
        pacman's index)
        """
        return self.generate_successor(0, action)

    def get_pacman_state(self):
        """Return an game.AgentState object for pacman.

        state.position gives the current position
        state.direction gives the travel vector
        """
        return self.data.agent_states[0].copy()

    def get_pacman_position(self):
        """Return pacman's position."""
        return self.data.agent_states[0].get_position()

    def get_ghost_states(self):
        """Return list of game.AgentState objects for all ghosts."""
        return self.data.agent_states[1:]

    def get_ghost_state(self, agent_index):
        """Return game.AgentState object for specified ghost.

        :raise IndexError if invalid agent_index.
        """
        if agent_index == 0 or agent_index >= self.get_num_agents():
            raise IndexError("Invalid index passed to get_ghost_state")
        return self.data.agent_states[agent_index]

    def get_ghost_position(self, agent_index):
        """Return position of specified ghost.

        :raise IndexError if invalid agent_index.
        """
        return self.get_ghost_state(agent_index).get_position()

    def get_ghost_positions(self):
        """Return list of ghost positions for all ghosts."""
        return [s.get_position() for s in self.get_ghost_states()]

    def get_num_agents(self):
        """Return total number of agents (pacman + ghosts)."""
        return len(self.data.agent_states)

    def get_score(self):
        """Return score of the state."""
        return float(self.data.score)

    def get_capsules(self):
        """Return a list of positions (x,y) of the remaining capsules."""
        return self.data.capsules

    def get_num_food(self):
        """Return number of food pellets in the game state."""
        return self.data.food.count()

    def get_food(self):
        """Return 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 call

        current_food = state.get_food()
        if current_food[x][y] == True: ...
        """
        return self.data.food

    def get_walls(self):
        """Return 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 call

        walls = state.get_walls()
        if walls[x][y] == True: ...
        """
        return self.data.layout.walls

    def has_food(self, x, y):
        """Return whether there is food at (x,y)."""
        return self.data.food[x][y]

    def has_wall(self, x, y):
        """Return whether there is a wall at (x,y)."""
        return self.data.layout.walls[x][y]

    def is_lose(self):
        """Return if the state is a losing one."""
        return self.data._lose

    def is_win(self):
        """Return if the state is a winning one."""
        return self.data._win

    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__(self, prev_state=None):
        """Generate a new state by copying information from its predecessor."""
        if prev_state is not None:  # Initial state
            self.data = GameStateData(prev_state.data)
        else:
            self.data = GameStateData()

    def deep_copy(self):
        """Return a deep copy of the state."""
        state = GameState(self)
        state.data = self.data.deep_copy()
        return state

    def __eq__(self, other):
        """Allow two states to be compared."""
        return hasattr(other, 'data') and self.data == other.data

    def __hash__(self):
        """Allow states to be keys of dictionaries / set entries."""
        return hash(self.data)

    def __str__(self):
        """Return string representation of state."""
        return str(self.data)

    def initialize(self, layout, num_ghost_agents=1000):
        """Create an initial game state from a layout array (see layout.py)."""
        self.data.initialize(layout, num_ghost_agents)
 def __init__(self, prev_state=None):
     """Generate a new state by copying information from its predecessor."""
     if prev_state is not None:  # Initial state
         self.data = GameStateData(prev_state.data)
     else:
         self.data = GameStateData()
class GameState:
    """
    A GameState specifies the full game state, including the food,
    agent configurations and score changes.

    GameStates are used by the Game object to capture the actual state of the 
    game and can be used by agents to reason about the game.

    Much of the information in a GameState is stored in a GameStateData 
    object.  We strongly suggest that you access that data via the accessor 
    methods below rather than referring to the GameStateData object directly.

    Note that Green House Worker is always agent 0.
    """

    ####################################################
    # Accessor methods: use these to access state data #
    ####################################################

    # static variable keeps track of which states have had getLegalActions called
    explored = set()
    def getAndResetExplored():
        tmp = GameState.explored.copy()
        GameState.explored = set()
        return tmp
    getAndResetExplored = staticmethod(getAndResetExplored)

    def getLegalActions( self, agentIndex=0 ):
        """
        Returns the legal actions for the agent specified.
        """
        GameState.explored.add(self)
        if self.isWin() or self.isLose(): return []

        if agentIndex == 0:  # Pacman is moving
            return GHworkerRules.getLegalActions( self )

    def generateSuccessor( self, agentIndex, action):
        """
        Returns the successor state after the specified agent takes the action.
        """
        # Check that successors exist
        if self.isWin() or self.isLose(): raise Exception('Can\'t generate a successor of a terminal state.')

        # Copy current state
        state = GameState(self)

        # Let agent's logic deal with its action's effects on the board
        if agentIndex == 0:  # Pacman is moving
            state.data._eaten = [False for i in range(state.getNumAgents())]
            GHworkerRules.applyAction( state, action )

        # Time passes
        if agentIndex == 0:
            state.data.scoreChange += -TIME_PENALTY # Penalty for waiting around

        # Book keeping
        state.data._agentMoved = agentIndex
        state.data.score += state.data.scoreChange
        return state

    def getLegalGHworkerActions( self ):
        return self.getLegalActions( 0 )

    def generateGHworkerSuccessor( self, action ):
        """
        Generates the successor state after the specified pacman move
        """
        return self.generateSuccessor( 0, action )

    def getGHworkerState( self ):
        """
        Returns an AgentState object for pacman (in game.py)

        state.pos gives the current position
        state.direction gives the travel vector
        """
        return self.data.agentStates[0].copy()

    def getGHworkerPosition( self ):
        return self.data.agentStates[0].getPosition()

    def getNumAgents( self ):
        return len( self.data.agentStates )

    def getScore( self ):
        return self.data.score

    def getNumFood( self ):
        print "getNumFood"
        print self.data.food
        return self.data.food.count()

    def getNumGHs( self ):
        print "getNumGHs"
        print self.data._foodEaten
        return self.data._foodEaten.count()

    def getFood(self):
        """
        Returns a Grid of boolean food indicator variables (strawberries!)

        Grids can be accessed via list notation, so to check
        if there is food at (x,y), just call

        currentFood = state.getFood()
        if currentFood[x][y] == True: ...
        """
        return self.data.food

    def getWalls(self):
        """
        Returns a Grid of boolean wall indicator variables.

        Grids can be accessed via list notation, so to check
        if there is food at (x,y), just call

        walls = state.getWalls()
        if walls[x][y] == True: ...
        """
        return self.data.layout.walls

    def hasFood(self, x, y):
        return self.data.food[x][y]

    def hasWall(self, x, y):
        return self.data.layout.walls[x][y]

    def isLose( self ):
        return self.data._lose

    def isWin( self ):
        return self.data._win

    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__( self, prevState = None ):
        """
        Generates a new state by copying information from its predecessor.
        """
        if prevState != None: # Initial state
            self.data = GameStateData(prevState.data)
        else:
            self.data = GameStateData()

    def deepCopy( self ):
        state = GameState( self )
        state.data = self.data.deepCopy()
        return state

    def __eq__( self, other ):
        """
        Allows two states to be compared.
        """
        return self.data == other.data

    def __hash__( self ):
        """
        Allows states to be keys of dictionaries.
        """
        return hash( self.data )

    def __str__( self ):

        return str(self.data)

    def initialize( self, layout):
        """
        Creates an initial game state from a layout array (see layout.py).
        """
        self.data.initialize(layout)
Пример #21
0
class GameState:
    def getLegalActions(self, agentIndex=0):
        if self.isWin() or self.isLose(): return []

        if agentIndex == 0:
            return PacmanRules.getLegalActions(self)
        else:
            return GhostRules.getLegalActions(self, agentIndex)

    def generateSuccessor(self, agentIndex, action):
        if self.isWin() or self.isLose():
            raise Exception("Can\'t generate a successor of a terminal state.")

        state = GameState(self)

        if agentIndex == 0:
            state.data._eaten = [False for i in range(state.getNumAgents())]
            PacmanRules.applyAction(state, action)
        else:
            GhostRules.applyAction(state, action, agentIndex)

        if agentIndex == 0:
            state.data.scoreChange += 0
        else:
            GhostRules.decrementTimer(state.data.agentStates[agentIndex])

        GhostRules.checkDeath(state, agentIndex)

        state.data._agentMoved = agentIndex
        state.data.score += state.data.scoreChange
        return state

    def getLegalPacmanActions(self):
        return self.getLegalActions(0)

    def generatePacmanSuccessor(self, action):
        return self.generateSuccessor(0, action)

    def getPacmanState(self):
        return self.data.agentStates[0].copy()

    def getPacmanPosition(self):
        return self.data.agentStates[0].getPosition()

    def getGhostStates(self):
        return self.data.agentStates[1:]

    def getGhostState(self, agentIndex):
        if agentIndex == 0 or agentIndex >= self.getNumAgents():
            raise BaseException("Invalid index passed to getGhostState")
        return self.data.agentStates[agentIndex]

    def getGhostPosition(self, agentIndex):
        if agentIndex == 0:
            raise BaseException("Pacman's index passed to getGhostPosition")
        return self.data.agentStates[agentIndex].getPosition()

    def getNumAgents(self):
        return len(self.data.agentStates)

    def getScore(self):
        return self.data.score

    def getCapsules(self):
        return self.data.capsules

    def getNumFood(self):
        return self.data.food.count()

    def getFood(self):
        return self.data.food

    def getWalls(self):
        return self.data.layout.walls

    def hasFood(self, x, y):
        return self.data.food[x][y]

    def hasWall(self, x, y):
        return self.data.layout.walls[x][y]

    def isLose(self):
        return self.data._lose

    def isWin(self):
        return self.data._win

    def __init__(self, prevState=None):
        if prevState != None:  # Initial state
            self.data = GameStateData(prevState.data)
        else:
            self.data = GameStateData()

    def deepCopy(self):
        state = GameState(self)
        state.data = self.data.deepCopy()
        return state

    def __eq__(self, other):
        if other == None:
            return self.data == other
        return self.data == other.data

    def __hash__(self):
        return hash(str(self))

    def __str__(self):

        return str(self.data)

    def initialize(self, layout, numGhostAgents=1000):
        self.data.initialize(layout, numGhostAgents)
class GameState:
    """
    A GameState specifies the full game state, including the food, capsules,
    agent configurations and score changes.

    GameStates are used by the Game object to capture the actual state of the game and
    can be used by agents to reason about the game.

    Much of the information in a GameState is stored in a GameStateData object.  We
    strongly suggest that you access that data via the accessor methods below rather
    than referring to the GameStateData object directly.

    Note that in classic Pacman, Pacman is always agent 0.
    """

    ####################################################
    # Accessor methods: use these to access state data #
    ####################################################

    # static variable keeps track of which states have had getLegalActions called
    explored = set()

    def getAndResetExplored(self):
        tmp = GameState.explored.copy()
        GameState.explored = set()
        return tmp

    getAndResetExplored = staticmethod(getAndResetExplored)

    def getLegalActions(self, agentIndex=0):
        """
        Returns the legal actions for the agent specified.
        """
        #        GameState.explored.add(self)
        if self.isWin() or self.isLose(): return []

        if agentIndex == 0:  # Pacman is moving
            return PacmanRules.getLegalActions(self)
        else:
            return GhostRules.getLegalActions(self, agentIndex)

    def generateSuccessor(self, agentIndex, action):
        """
        Returns the successor state after the specified agent takes the action.
        """
        # Check that successors exist
        if self.isWin() or self.isLose():
            raise Exception('Can\'t generate a successor of a terminal state.')

        # Copy current state
        state = GameState(self)

        # Let agent's logic deal with its action's effects on the board
        if agentIndex == 0:  # Pacman is moving
            state.data._eaten = [False for i in range(state.getNumAgents())]
            PacmanRules.applyAction(state, action)
        else:  # A ghost is moving
            GhostRules.applyAction(state, action, agentIndex)
            ghostPosition = state.getGhostPosition(agentIndex)
            state.explorePositionSurrounding(ghostPosition, agentIndex)
            state.data.ghostDistances[agentIndex -
                                      1] = self.getGhostDistance(agentIndex)

        # Time passes
        if agentIndex == 0:
            state.data.scoreChange += -TIME_PENALTY  # Penalty for waiting around
        else:
            GhostRules.decrementTimer(state.data.agentStates[agentIndex])

        # Resolve multi-agent effects
        GhostRules.checkDeath(state, agentIndex)

        #print(self.getBestSectors(5))

        # Book keeping
        state.data._agentMoved = agentIndex
        state.visibleData._agentMoved = agentIndex
        state.visibleData.fitness += self.fitnessfunction()

        state.data.score += state.data.scoreChange
        state.visibleData.score += state.data.scoreChange
        state.data.fitness += self.fitnessfunction()
        state.data.fitnessChange += self.fitnessfunction()
        state.visibleData.previousExploredCount = self.countExploredTiles()

        GameState.explored.add(self)
        GameState.explored.add(state)
        return state

    def getLegalPacmanActions(self):
        return self.getLegalActions(0)

    def generatePacmanSuccessor(self, action):
        """
        Generates the successor state after the specified pacman move
        """
        return self.generateSuccessor(0, action)

    def getPacmanState(self):
        """
        Returns an AgentState object for pacman (in game.py)

        state.pos gives the current position
        state.direction gives the travel vector
        """
        return self.data.agentStates[0].copy()

    def getPacmanPosition(self):
        return self.data.agentStates[0].getPosition()

    def getPacmanPositionIfVisible(self):
        pacman_position = self.getPacmanPosition()
        for ghost_position in self.getGhostPositions():
            withinXBound = ghost_position[0] - self.ghostVisionDistance <= pacman_position[0] and\
                           ghost_position[0] + self.ghostVisionDistance >= pacman_position[0]
            withinYBound = ghost_position[1] - self.ghostVisionDistance <= pacman_position[1] and\
                           ghost_position[1] + self.ghostVisionDistance >= pacman_position[1]

            withinBound = withinXBound and withinYBound
            if withinBound:
                return self.getPacmanPosition()

        return None

    def getGhostStates(self):
        return self.data.agentStates[1:]

    def getGhostState(self, agentIndex):
        if agentIndex == 0 or agentIndex >= self.getNumAgents():
            raise Exception("Invalid index passed to getGhostState")
        return self.data.agentStates[agentIndex]

    def getGhostPosition(self, agentIndex):
        if agentIndex == 0:
            raise Exception("Pacman's index passed to getGhostPosition")
        return self.data.agentStates[agentIndex].getPosition()

    def getGhostPositions(self):
        return [s.getPosition() for s in self.getGhostStates()]

    def fitnessfunction(self):
        sightingPoint = 1000
        points = 0
        maxTime = self.data.maxTime
        currentTime = self.data.timeRemaining
        timeRatio = currentTime / maxTime
        if self.getPacmanPositionIfVisible() != None:
            points += sightingPoint * timeRatio
        #exploration points
        explorationPoint = 10 * timeRatio

        ##fix unexplored count

        points += explorationPoint * (self.countExploredTiles() -
                                      self.visibleData.previousExploredCount)
        return points

    def countExploredTiles(self):
        j = 0
        for i in range(len(self.visibleData.unexplored)):
            if self.visibleData.unexplored[i] == False:
                j += 1
        return j

    def getGhostDistance(self, ghost_index):
        pacman_position = self.getPacmanPosition()

        ghost_position = self.data.agentStates[ghost_index].getPosition()
        ghostDistance = manhattanDistance(pacman_position, ghost_position)

        return ghostDistance

    def getNumAgents(self):
        return len(self.data.agentStates)

    def getScore(self):
        return float(self.data.score)

    def getFitness(self):

        return self.data.fitness

    def getCapsules(self):
        """
        Returns a list of positions (x,y) of the remaining capsules.
        """
        return self.data.capsules

    def getNumFood(self):
        return self.data.food.count()

    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 call

        currentFood = state.getFood()
        if currentFood[x][y] == True: ...
        """
        return self.data.food

    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 call

        walls = state.getWalls()
        if walls[x][y] == True: ...
        """
        return self.data.layout.walls

    def getBestSectors(self, topCount):
        maxTime = self.data.maxTime
        currentTime = self.data.timeRemaining
        timeRatio = currentTime / maxTime * 1.0
        rowCount = self.data.sectorrow
        colCount = self.data.sectorcol
        PacManPoint = 2 * (1 - (timeRatio + 0.1))
        print(timeRatio)
        print(PacManPoint)
        ghostPoint = -2

        if topCount > rowCount * colCount:
            topCount = rowCount * colCount
        y = self.getWalls().__getheight__()
        x = self.getWalls().__getwidth__()

        sectorWidth = math.floor(x / colCount)
        sectorHeight = math.floor(y / rowCount)
        #how you compute a sector number
        sector = (math.floor(x / sectorWidth) +
                  1) * (math.floor(y / sectorHeight) + 1)
        #now count where each ghost, pac is
        #pacman
        pacX, pacY = self.data.agentStates[0].getPosition()
        pacSector, pacMinSec, pacMaxSec = self.getSectorPosition(
            pacX, pacY, sectorWidth, sectorHeight)
        ghostSector = {}
        sectorScore = {}
        sectorMax = {}
        sectorMin = {}
        sectorCount = 0
        for row in range(rowCount):
            for col in range(colCount):
                #min
                x_min = col * sectorWidth
                y_min = row * sectorHeight
                x_max = x_min + sectorWidth
                y_max = y_min + sectorHeight
                if y_max >= y:
                    y_max = y - 1
                if x_max >= x:
                    x_max = x - 1
                sectorMin[sectorCount + 1] = (x_min, y_min)
                sectorMax[sectorCount + 1] = (x_max, y_max)
                sectorCount += 1
        #populate based on sector count
        for i in range(rowCount * colCount):
            ghostSector[i + 1] = 0
            sectorScore[i + 1] = 0

        #get sector per ghosts
        for ghost in range(len(self.data.agentStates) - 1):
            gX, gY = self.data.agentStates[ghost + 1].getPosition()
            sector, sec_min, sec_max = self.getSectorPosition(
                gX, gY, sectorWidth, sectorHeight)

            ghostSector[sector] += 1

        sectorScore[pacSector] += PacManPoint
        queue = []
        for i in range(colCount * rowCount):
            sectorScore[i + 1] += ghostSector[i + 1] * ghostPoint
            if i + 1 != pacSector:
                sectorScore[i + 1] += 0.5 * random.random()
            queue.append((sectorScore[i + 1], i + 1))
        topSectorsPairs = sorted(queue, key=lambda tup: tup[0], reverse=True)
        topSectors = []
        for i in range(len(topSectorsPairs)):
            topSectors.append(topSectorsPairs[i][1])
        topSubSectors = []
        for s in range(topCount):
            topSubSectors.append(topSectors[s])
        topSectors = topSubSectors

        return topSectors, [sectorMin[i] for i in topSectors
                            ], [sectorMax[i] for i in topSectors]

    def getSectorPosition(self, x, y, sectorWidth, sectorHeight):
        xcal = math.floor(x / sectorWidth)
        ycal = math.floor(y / sectorHeight)
        if xcal == math.floor(x / sectorWidth) and xcal > 1:
            xcal -= 1
        if ycal == math.floor(y / sectorHeight) and ycal > 1:
            ycal -= 1

        return (xcal + 1) * (ycal + 1), (xcal, ycal), (xcal + sectorWidth,
                                                       ycal + sectorHeight)

    def hasFood(self, x, y):
        return self.data.food[x][y]

    def hasWall(self, x, y):
        return self.data.layout.walls[x][y]

    def isLose(self):
        return self.data._lose

    def isWin(self):
        return self.data._win

    "adding method to help figure out how much ghost has explored"

    def getExplored(self):
        #print(type(self.visibleData.layout.unexplored))
        return self.visibleData.layout.unexplored

    def getToExplore(self):
        return self.visibleData.layout.unexploredAccessible

    def resetExplored(self):
        self.visibleData.layout.resUn()

    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__(self, prevState=None):
        """
        Generates a new state by copying information from its predecessor.
        """
        if prevState != None:  # Initial state
            self.data = GameStateData(prevState.data)
            self.visibleData = GameStateData(prevState.visibleData)
            self.visibleData.agentStates = self.data.agentStates
            self.visibleData.ghostDistances = self.data.ghostDistances
            self.ghostVisionDistance = prevState.ghostVisionDistance
        else:
            self.data = GameStateData()
            self.visibleData = GameStateData()

    def deepCopy(self):
        state = GameState(self)
        state.data = self.data.deepCopy()
        return state

    def __eq__(self, other):
        """
        Allows two states to be compared.
        """
        return hasattr(other, 'data') and self.data == other.data and \
               hasattr(other, 'visibleData') and self.visibleData == other.visibleData

    def __hash__(self):
        """
        Allows states to be keys of dictionaries.
        """
        return hash(self.data)

    def __str__(self):

        return str(self.data)

    def initialize(self,
                   fullLayout,
                   ghostVisionDistance,
                   numGhostAgents=1000,
                   sectorrow=2,
                   sectorcol=3):
        """
        Creates an initial game state from a layout array (see layout.py).
        """
        self.ghostVisionDistance = ghostVisionDistance
        self.data.initialize(fullLayout, numGhostAgents, sectorrow, sectorcol)
        self.visibleData.initialize(fullLayout, numGhostAgents, sectorrow,
                                    sectorcol)

    def explorePositionSurrounding(self, position, agentIndex):
        orig_x, orig_y = position
        width = self.visibleData.layout.width
        height = self.visibleData.layout.height

        min_x = int(max(0, orig_x - self.ghostVisionDistance))
        max_x = int(min(width, orig_x + self.ghostVisionDistance + 1))
        min_y = int(max(0, orig_y - self.ghostVisionDistance))
        max_y = int(min(height, orig_y + self.ghostVisionDistance + 1))
        brmin_x = (min_x > 0)
        brmax_x = (max_x + 1 < width)
        brmin_y = (min_y > 0)
        brmax_y = (max_y + 1 < height)

        self.visibleData._visited = self.visibleData._visible[agentIndex - 1]
        self.visibleData._visible[agentIndex - 1] = []

        for y in range(min_y, max_y):
            borderymin = (brmin_y and y == min_y)
            borderymax = (brmax_y and y == max_y - 1)
            for x in range(min_x, max_x):
                self.visibleData.food[x][y] = self.data.food[x][y]
                if (x, y) in self.data.capsules and (
                        x, y) not in self.visibleData.capsules:
                    self.visibleData.capsules.append((x, y))
                elif (x, y) in self.visibleData.capsules and (
                        x, y) not in self.data.capsules:
                    self.visibleData.capsules.remove((x, y))

                self.visibleData.layout.walls[x][y] = self.data.layout.walls[
                    x][y]
                self.visibleData.layout.food[x][y] = self.data.layout.food[x][
                    y]
                self.visibleData.layout.unexplored[x][y] = False
                self.visibleData.layout.unexploredRepeat[x][y] = False
                self.visibleData.layout.unexploredAccessible[x][y] = False

                #if self.visibleData.unexplored[x][y]:
                self.visibleData._visible[agentIndex - 1].append((x, y))

                if (x, y) in self.visibleData._visited:
                    self.visibleData._visited.remove((x, y))

                if (brmin_x and x == min_x
                        and self.visibleData.layout.unexploredRepeat[x - 1][y]
                        and not (self.visibleData.layout.walls[x][y])):
                    self.visibleData.layout.unexploredAccessible[x -
                                                                 1][y] = True
                if (brmax_x and x == max_x - 1
                        and self.visibleData.layout.unexploredRepeat[x + 1][y]
                        and not (self.visibleData.layout.walls[x][y])):
                    self.visibleData.layout.unexploredAccessible[x +
                                                                 1][y] = True
                if (borderymin
                        and self.visibleData.layout.unexploredRepeat[x][y - 1]
                        and not (self.visibleData.layout.walls[x][y])):
                    self.visibleData.layout.unexploredAccessible[x][y -
                                                                    1] = True
                if (borderymax
                        and self.visibleData.layout.unexploredRepeat[x][y + 1]
                        and not (self.visibleData.layout.walls[x][y])):
                    self.visibleData.layout.unexploredAccessible[x][y +
                                                                    1] = True
Пример #23
0
class GameState:
  """
  A GameState specifies the full game state, including the food, capsules,
  agent configurations and score changes.

  GameStates are used by the Game object to capture the actual state of the game and
  can be used by agents to reason about the game.

  Much of the information in a GameState is stored in a GameStateData object.  We
  strongly suggest that you access that data via the accessor methods below rather
  than referring to the GameStateData object directly.
  """

  ####################################################
  # Accessor methods: use these to access state data #
  ####################################################

  def getLegalActions(self, agentIndex=0):
    """
    Returns the legal actions for the agent specified.
    """
    return AgentRules.getLegalActions(self, agentIndex)

  def generateSuccessor(self, agentIndex, action):
    """
    Returns the successor state (a GameState object) after the specified agent takes the action.
    """
    # Copy current state
    state = GameState(self)

    # Find appropriate rules for the agent
    AgentRules.applyAction(state, action, agentIndex)
    AgentRules.checkDeath(state, agentIndex)
    AgentRules.decrementTimer(state.data.agentStates[agentIndex])

    # Book keeping
    state.data._agentMoved = agentIndex
    state.data.score += state.data.scoreChange
    state.data.timeleft = self.data.timeleft - 1
    return state

  def getAgentState(self, index):
    return self.data.agentStates[index]

  def getAgentPosition(self, index):
    """
    Returns a location tuple if the agent with the given index is observable;
    if the agent is unobservable, returns None.
    """
    agentState = self.data.agentStates[index]
    ret = agentState.getPosition()
    if ret:
      return tuple(int(x) for x in ret)
    return ret

  def getNumAgents(self):
    return len(self.data.agentStates)

  def getScore(self):
    """
    Returns a number corresponding to the current score.
    """
    return self.data.score

  def getRedFood(self):
    """
    Returns a matrix of food that corresponds to the food on the red team's side.
    For the matrix m, m[x][y]=true if there is food in (x,y) that belongs to
    red (meaning red is protecting it, blue is trying to eat it).
    """
    return halfGrid(self.data.food, red=True)

  def getBlueFood(self):
    """
    Returns a matrix of food that corresponds to the food on the blue team's side.
    For the matrix m, m[x][y]=true if there is food in (x,y) that belongs to
    blue (meaning blue is protecting it, red is trying to eat it).
    """
    return halfGrid(self.data.food, red=False)

  def getRedCapsules(self):
    return halfList(self.data.capsules, self.data.food, red=True)

  def getBlueCapsules(self):
    return halfList(self.data.capsules, self.data.food, red=False)

  def getWalls(self):
    """
    Just like getFood but for walls
    """
    return self.data.layout.walls

  def hasFood(self, x, y):
    """
    Returns true if the location (x,y) has food, regardless of
    whether it's blue team food or red team food.
    """
    return self.data.food[x][y]

  def hasWall(self, x, y):
    """
    Returns true if (x,y) has a wall, false otherwise.
    """
    return self.data.layout.walls[x][y]

  def isOver(self):
    return self.data._win

  def getRedTeamIndices(self):
    """
    Returns a list of agent index numbers for the agents on the red team.
    """
    return self.redTeam[:]

  def getBlueTeamIndices(self):
    """
    Returns a list of the agent index numbers for the agents on the blue team.
    """
    return self.blueTeam[:]

  def isOnRedTeam(self, agentIndex):
    """
    Returns true if the agent with the given agentIndex is on the red team.
    """
    return self.teams[agentIndex]

  def getAgentDistances(self):
    """
    Returns a noisy distance to each agent.
    """
    if 'agentDistances' in dir(self) :
      return self.agentDistances
    else:
      return None

  def getDistanceProb(self, trueDistance, noisyDistance):
    "Returns the probability of a noisy distance given the true distance"
    if noisyDistance - trueDistance in SONAR_NOISE_VALUES:
      return 1.0 / SONAR_NOISE_RANGE
    else:
      return 0

  def getInitialAgentPosition(self, agentIndex):
    "Returns the initial position of an agent."
    return self.data.layout.agentPositions[agentIndex][1]

  def getCapsules(self):
    """
    Returns a list of positions (x,y) of the remaining capsules.
    """
    return self.data.capsules

  #############################################
  #             Helper methods:               #
  # You shouldn't need to call these directly #
  #############################################

  def __init__(self, prevState=None):
    """
    Generates a new state by copying information from its predecessor.
    """
    if prevState != None: # Initial state
      self.data = GameStateData(prevState.data)
      self.blueTeam = prevState.blueTeam
      self.redTeam = prevState.redTeam
      self.data.timeleft = prevState.data.timeleft

      self.teams = prevState.teams
      self.agentDistances = prevState.agentDistances
    else:
      self.data = GameStateData()
      self.agentDistances = []

  def deepCopy(self):
    state = GameState(self)
    state.data = self.data.deepCopy()
    state.data.timeleft = self.data.timeleft

    state.blueTeam = self.blueTeam[:]
    state.redTeam = self.redTeam[:]
    state.teams = self.teams[:]
    state.agentDistances = self.agentDistances[:]
    return state

  def makeObservation(self, index):
    state = self.deepCopy()

    # Adds the sonar signal
    pos = state.getAgentPosition(index)
    n = state.getNumAgents()
    distances = [noisyDistance(pos, state.getAgentPosition(i)) for i in range(n)]
    state.agentDistances = distances

    # Remove states of distant opponents
    if index in self.blueTeam:
      team = self.blueTeam
      otherTeam = self.redTeam
    else:
      otherTeam = self.blueTeam
      team = self.redTeam

    for enemy in otherTeam:
      seen = False
      enemyPos = state.getAgentPosition(enemy)
      for teammate in team:
        if util.manhattanDistance(enemyPos, state.getAgentPosition(teammate)) <= SIGHT_RANGE:
          seen = True
      if not seen: state.data.agentStates[enemy].configuration = None
    return state

  def __eq__(self, other):
    """
    Allows two states to be compared.
    """
    if other == None: return False
    return self.data == other.data

  def __hash__(self):
    """
    Allows states to be keys of dictionaries.
    """
    return int(hash(self.data))

  def __str__(self):

    return str(self.data)

  def initialize(self, layout, numAgents):
    """
    Creates an initial game state from a layout array (see layout.py).
    """
    self.data.initialize(layout, numAgents)
    positions = [a.configuration for a in self.data.agentStates]
    self.blueTeam = [i for i, p in enumerate(positions) if not self.isRed(p)]
    self.redTeam = [i for i, p in enumerate(positions) if self.isRed(p)]
    self.teams = [self.isRed(p) for p in positions]

  def isRed(self, configOrPos):
    width = self.data.layout.width
    if type(configOrPos) == type((0, 0)):
      return configOrPos[0] < width / 2
    else:
      return configOrPos.pos[0] < width / 2
Пример #24
0
class GameState:
    """
    A GameState specifies the full game state, including the food, capsules,
    agent configurations and score changes.

    GameStates are used by the Game object to capture the actual state of the game and
    can be used by agents to reason about the game.

    Much of the information in a GameState is stored in a GameStateData object.  We
    strongly suggest that you access that data via the accessor methods below rather
    than referring to the GameStateData object directly.

    Note that in classic Pacman, Pacman is always agent 0.
    """

    ####################################################
    # Accessor methods: use these to access state data #
    ####################################################

    def getLegalActions( self, agentIndex=0 ):
        """
        Returns the legal actions for the agent specified.
        """
        if self.isWin() or self.isLose(): return []

        if agentIndex == 0:  # Pacman is moving
            return PacmanRules.getLegalActions( self )
        else:
            return GhostRules.getLegalActions( self, agentIndex )

    def generateSuccessor( self, agentIndex, action):
        """
        Returns the successor state after the specified agent takes the action.
        """
        # Check that successors exist
        if self.isWin() or self.isLose(): raise Exception('Can\'t generate a successor of a terminal state.')

        # Copy current state
        state = GameState(self)

        # Let agent's logic deal with its action's effects on the board
        if agentIndex == 0:  # Pacman is moving
            state.data._eaten = [False for i in range(state.getNumAgents())]
            PacmanRules.applyAction( state, action )
        else:                # A ghost is moving
            GhostRules.applyAction( state, action, agentIndex )

        # Time passes
        if agentIndex == 0:
            state.data.scoreChange += -TIME_PENALTY # Penalty for waiting around
        else:
            GhostRules.decrementTimer( state.data.agentStates[agentIndex] )

        # Resolve multi-agent effects
        GhostRules.checkDeath( state, agentIndex )

        # Book keeping
        state.data._agentMoved = agentIndex
        state.data.score += state.data.scoreChange
        p = state.getPacmanPosition()
        state.data.ghostDistances = [getNoisyDistance(p, state.getGhostPosition(i)) for i in range(1,state.getNumAgents())]
        if agentIndex == self.getNumAgents() - 1:
            state.numMoves += 1
        return state

    def getLegalPacmanActions( self ):
        return self.getLegalActions( 0 )

    def generatePacmanSuccessor( self, action ):
        """
        Generates the successor state after the specified pacman move
        """
        return self.generateSuccessor( 0, action )

    def getPacmanState( self ):
        """
        Returns an AgentState object for pacman (in game.py)

        state.pos gives the current position
        state.direction gives the travel vector
        """
        return self.data.agentStates[0].copy()

    def getPacmanPosition( self ):
        return self.data.agentStates[0].getPosition()

    def setAgentPosition(self, pos, agentIndex):
        self.data.agentStates[agentIndex].setPosition(pos)
        
    def getNumAgents( self ):
        return len( self.data.agentStates )

    def getScore( self ):
        return self.data.score

    def getCapsules(self):
        """
        Returns a list of positions (x,y) of the remaining capsules.
        """
        return self.data.capsules

    def getNumFood( self ):
        return self.data.food.count()

    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 call

        currentFood = state.getFood()
        if currentFood[x][y] == True: ...
        """
        return self.data.food

    def getWalls(self):
        """
        Returns a Grid of boolean wall indicator variables.

        Grids can be accessed via list notation, so to check
        if there is food at (x,y), just call

        walls = state.getWalls()
        if walls[x][y] == True: ...
        """
        return self.data.layout.walls

    def hasFood(self, x, y):
        return self.data.food[x][y]

    def hasWall(self, x, y):
        return self.data.layout.walls[x][y]

    ##############################
    # Additions for Busters Pacman #
    ##############################

    def getLivingGhosts(self):
        """
        Returns a list of booleans indicating which ghosts are not yet captured.

        The first entry (a placeholder for Pacman's index) is always False.
        """
        return self.livingGhosts

    def setGhostNotLiving(self, index):
        self.livingGhosts[index] = False

    def isLose( self ):
        return self.data._lose

    def isWin( self ):
        return self.data._win

    """
    def isLose( self ):
        return self.maxMoves > 0 and self.numMoves >= self.maxMoves

    def isWin( self ):
        return self.livingGhosts.count(True) == 0
    """
    
    def getNoisyGhostDistances(self):
        """
        Returns a noisy distance to each ghost.
        """
        return self.data.ghostDistances

    def generateStateObservationReward(self, agent, ghostAgents, action):
        gameStateCopy = self.deepCopy()
        nextGameState = gameStateCopy.generateSuccessor(0, action)
        for (i, ghostAgent) in zip(range(1, len(ghostAgents)+1),
                                   ghostAgents):
            if nextGameState.isWin() or nextGameState.isLose():
                break
            nextGameState = nextGameState.generateSuccessor(
                i, ghostAgent.getAction(nextGameState))
            
        reward = nextGameState.getScore() - self.getScore()
        if agent.obsOnStopOnly:
            if action == Directions.STOP:
                observation = nextGameState.getNoisyGhostDistances()
            else:
                observation = [None]
        else:
            observation = nextGameState.getNoisyGhostDistances()

        
        return (nextGameState, tuple(observation), reward)

    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__( self, prevState = None ):
        """
        Generates a new state by copying information from its predecessor.
        """
        if prevState != None:
            self.data = GameStateData(prevState.data)
            self.livingGhosts = prevState.livingGhosts[:]
            self.numMoves = prevState.numMoves;
            self.maxMoves = prevState.maxMoves;
        else: # Initial state
            self.data = GameStateData()
            self.numMoves = 0;
            self.maxMoves = -1;
        self.data.ghostDistances = []

    def deepCopy( self ):
        state = GameState( self )
        state.data = self.data.deepCopy()
        state.data.ghostDistances = self.data.ghostDistances
        return state

    def __eq__( self, other ):
        """
        Allows two states to be compared.
        """
        return self.data == other.data

    def __hash__( self ):
        """
        Allows states to be keys of dictionaries.
        """
        return hash( str( self ) )

    def __str__( self ):

        return str(self.data)

    def initialize( self, layout, numGhostAgents=1000 ):
        """
        Creates an initial game state from a layout array (see layout.py).
        """
        self.data.initialize(layout, numGhostAgents)
        self.livingGhosts = [False] + [True for i in range(numGhostAgents)]
        self.data.ghostDistances = [getNoisyDistance(self.getPacmanPosition(), self.getGhostPosition(i)) for i in range(1, self.getNumAgents())]

    def getGhostPosition( self, agentIndex ):
        if agentIndex == 0:
            raise "Pacman's index passed to getGhostPosition"
        return self.data.agentStates[agentIndex].getPosition()

    def getGhostState( self, agentIndex ):
        if agentIndex == 0:
            raise "Pacman's index passed to getGhostPosition"
        return self.data.agentStates[agentIndex]
Пример #25
0
class GameState:
  """
  A 【GameState】 specifies the full game state, including the food, capsules胶囊,
  agent configurations and score changes.

  GameStates are used by the Game object to capture the actual state of the game and
  can be used by agents to reason about the game.

  Much of the information in a GameState is stored in a 【GameStateData】 object.  We
  strongly suggest that you access that data via the accessor methods below rather
  than referring to the GameStateData object directly.
  """

  ####################################################
  # Accessor methods: use these to access state data #
  ####################################################

  def getLegalActions( self, agentIndex=0 ):
    """
    传入agentIndex,返回其当前可选actions
    Returns the legal actions for the agent specified.
    """
    return AgentRules.getLegalActions( self, agentIndex )

  def generateSuccessor( self, agentIndex, action):
    """
    返回某个agent,在当前gameState,执行完某个action,
    之后的gameState(是个整个地图的网格数据,当敌方在范围5内,会显示对方 )
    Returns the successor state (a GameState object) after the specified agent takes the action.
    """
    # Copy current state
    state = GameState(self)

    # Find appropriate rules for the agent通过游戏规则更新gamestate
    AgentRules.applyAction( state, action, agentIndex )
    AgentRules.checkDeath(state, agentIndex)
    AgentRules.decrementTimer(state.data.agentStates[agentIndex])

    # Book keeping 记账,更新“谁移动过”,“当前分数”,“所剩时间”
    state.data._agentMoved = agentIndex
    state.data.score += state.data.scoreChange
    state.data.timeleft = self.data.timeleft - 1
    return state
  
  
  def getAgentState(self, index):
    """
    传入一个agentIndex,返回其当前状态。若不在范围内,会返回身份,但其余值为none。
    格式为:当前身份,位置,运动方向
    Ghost: (x,y)=(9.0, 13.0), East
    Ghost: None
    Pacman: (x,y)=(19.0, 6.0), West
    """
    return self.data.agentStates[index]

  def getAgentPosition(self, index):
    """
    如果当前传入的agent是可见的,那么返回其坐标(元组);不可见,返回None
    Returns a location tuple if the agent with the given index is observable;
    if the agent is unobservable, returns None.
    """
    agentState = self.data.agentStates[index]
    ret = agentState.getPosition()
    if ret:
      return tuple(int(x) for x in ret)
    return ret

  def getNumAgents( self ):
    """
    返回当前游戏中agent的数量,值一直是固定的4
    """
    return len( self.data.agentStates )

  def getScore( self ):
    """
    返回当前己方的分数?
    Returns a number corresponding to the current score.
    """
    return self.data.score

  def getRedFood(self):
    """
    返回红方要保护的豆,矩阵,里面全是T/F
    Returns a matrix of food that corresponds to the food on the red team's side.
    For the matrix m, m[x][y]=true if there is food in (x,y) that belongs to
    red (meaning red is protecting it, blue is trying to eat it).
    """
    return halfGrid(self.data.food, red = True)

  def getBlueFood(self):
    """
    返回蓝方要保护的豆,矩阵,里面全是T/F
    Returns a matrix of food that corresponds to the food on the blue team's side.
    For the matrix m, m[x][y]=true if there is food in (x,y) that belongs to
    blue (meaning blue is protecting it, red is trying to eat it).
    """
    return halfGrid(self.data.food, red = False)

  def getRedCapsules(self):
    """
    返回红方要保护的“变身胶囊”
    """
    return halfList(self.data.capsules, self.data.food, red = True)

  def getBlueCapsules(self):
    """
    返回蓝方要保护的“变身胶囊”
    """
    return halfList(self.data.capsules, self.data.food, red = False)

  def getWalls(self):
    """
    返回一个“墙”矩阵,全是T/F
    Just like getFood but for walls
    """
    return self.data.layout.walls

  def hasFood(self, x, y):
    """
    判断具体某个点是否有食物,有ture,无false
    Returns true if the location (x,y) has food, regardless of
    whether it's blue team food or red team food.
    """
    return self.data.food[x][y]

  def hasWall(self, x, y):
    """
    判断具体某个点是否有“墙”
    Returns true if (x,y) has a wall, false otherwise.
    """
    return self.data.layout.walls[x][y]

  def isOver( self ):
    """
    判断游戏是否结束,有什么用?游戏结束后,这个方法也执行不了。否则一直返回false
    """
    return self.data._win

  def getRedTeamIndices(self):
    """
    返回红队的agent索引值,格式为:[0, 2]
    Returns a list of agent index numbers for the agents on the red team.
    """
    return self.redTeam[:]

  def getBlueTeamIndices(self):
    """
    Returns a list of the agent index numbers for the agents on the blue team.
    """
    return self.blueTeam[:]

  def isOnRedTeam(self, agentIndex):
    """
    判断某个indice是否属于红队
    Returns true if the agent with the given agentIndex is on the red team.
    """
    return self.teams[agentIndex]

  def getAgentDistances(self):
    """
    返回每个agent到当前agent的粗糙距离list,
    格式为:[4, 32, -3, 29],对应着到0-3 agentIndices的距离。
    Returns a noisy distance to each agent.
    """
    if 'agentDistances' in dir(self) :
      return self.agentDistances
    else:
      return None

  def getDistanceProb(self, trueDistance, noisyDistance):
    """
    传入实际距离和粗糙距离,计算粗糙距离的“可信度”。
    怎么用?如果我知道真实距离,我要粗糙距离干什么用?
    Returns the probability of a noisy distance given the true distance
    """
    if noisyDistance - trueDistance in SONAR_NOISE_VALUES:
      return 1.0/SONAR_NOISE_RANGE
    else:
      return 0

  def getInitialAgentPosition(self, agentIndex):
    """
    根据index获取该agent的出生位置,对于同一个地图,该值是固定的。
    Returns the initial position of an agent.
    """
    return self.data.layout.agentPositions[agentIndex][1]

  def getCapsules(self):
    """
    返回剩余的“超级胶囊”的坐标list
    Returns a list of positions (x,y) of the remaining capsules.
    """
    return self.data.capsules

  #############################################
  #             Helper methods:               #
  # You shouldn't need to call these directly #
  #############################################

  def __init__( self, prevState = None ):
    """
    Generates a new state by copying information from its predecessor.
    """
    if prevState != None: # Initial state
      self.data = GameStateData(prevState.data)
      self.blueTeam = prevState.blueTeam
      self.redTeam = prevState.redTeam
      self.data.timeleft = prevState.data.timeleft

      self.teams = prevState.teams
      self.agentDistances = prevState.agentDistances
    else:
      self.data = GameStateData()
      self.agentDistances = []

  def deepCopy( self ):
    state = GameState( self )
    state.data = self.data.deepCopy()
    state.data.timeleft = self.data.timeleft

    state.blueTeam = self.blueTeam[:]
    state.redTeam = self.redTeam[:]
    state.teams = self.teams[:]
    state.agentDistances = self.agentDistances[:]
    return state

  def makeObservation(self, index):
    state = self.deepCopy()

    # Adds the sonar signal
    pos = state.getAgentPosition(index)
    n = state.getNumAgents()
    distances = [noisyDistance(pos, state.getAgentPosition(i)) for i in range(n)]
    state.agentDistances = distances

    # Remove states of distant opponents
    if index in self.blueTeam:
      team = self.blueTeam
      otherTeam = self.redTeam
    else:
      otherTeam = self.blueTeam
      team = self.redTeam

    for enemy in otherTeam:
      seen = False
      enemyPos = state.getAgentPosition(enemy)
      for teammate in team:
        if util.manhattanDistance(enemyPos, state.getAgentPosition(teammate)) <= SIGHT_RANGE:
          seen = True
      if not seen: state.data.agentStates[enemy].configuration = None
    return state

  def __eq__( self, other ):
    """
    Allows two states to be compared.
    """
    if other == None: return False
    return self.data == other.data

  def __hash__( self ):
    """
    Allows states to be keys of dictionaries.
    """
    return int(hash( self.data ))

  def __str__( self ):

    return str(self.data)

  def initialize( self, layout, numAgents):
    """
    Creates an initial game state from a layout array (see layout.py).
    """
    self.data.initialize(layout, numAgents)
    positions = [a.configuration for a in self.data.agentStates]
    self.blueTeam = [i for i,p in enumerate(positions) if not self.isRed(p)]
    self.redTeam = [i for i,p in enumerate(positions) if self.isRed(p)]
    self.teams = [self.isRed(p) for p in positions]
    #This is usually 60 (always 60 with random maps)
    #However, if layout map is specified otherwise, it could be less
    global TOTAL_FOOD
    TOTAL_FOOD = layout.totalFood

  def isRed(self, configOrPos):
    width = self.data.layout.width
    if type(configOrPos) == type( (0,0) ):
      return configOrPos[0] < width / 2
    else:
      return configOrPos.pos[0] < width / 2
Пример #26
0
class GameState:
    """
    A GameState specifies the full game state, including the food, capsules,
    agent configurations and score changes.

    GameStates are used by the Game object to capture the actual state of the game and
    can be used by agents to reason about the game.

    Much of the information in a GameState is stored in a GameStateData object.  We
    strongly suggest that you access that data via the accessor methods below rather
    than referring to the GameStateData object directly.

    Note that in classic Pacman, Pacman is always agent 0.
    """

    ####################################################
    # Accessor methods: use these to access state data #
    ####################################################

    # static variable keeps track of which states have had getLegalActions called
    explored = set()
    def getAndResetExplored():
        tmp = GameState.explored.copy()
        GameState.explored = set()
        return tmp
    getAndResetExplored = staticmethod(getAndResetExplored)

    def getLegalActions( self, agentIndex=0 ):
        """
        Returns the legal actions for the agent specified.
        """
#        GameState.explored.add(self)
        if self.isWin() or self.isLose(): return []

        if agentIndex == 0:  # Pacman is moving
            return PacmanRules.getLegalActions( self )
        else:
            return GhostRules.getLegalActions( self, agentIndex )

    def generateSuccessor( self, action ):
        """
        Returns the successor state after the specified agent takes the action.
        """
        # Check that successors exist
        if self.isWin() or self.isLose() or self.eventQueue.isEmpty():
            raise Exception('Can\'t generate a successor of a terminal state.')

        time, event = self.eventQueue.peek()
        assert event.isAgentMove(), 'Can only generate successors of a state where an agent is about to move'
        state = self.makeAgentMove(action)
        state.resolveEventsUntilAgentEvent()

        # Book keeping
        GameState.explored.add(self.data)
        GameState.explored.add(state.data)
        return state

    def makeAgentMove( self, action ):
        # Copy current state
        state = GameState(self)

        time, event = state.eventQueue.pop()
        agentIndex = event.getAgentIndex()
        agentState = state.data.agentStates[agentIndex]
        state.data.time = time
        delay = agentState.powers.timestepsBetweenMoves
        state.registerEventWithDelay(event, delay)

        # Let agent's logic deal with its action's effects on the board
        if agentIndex == 0:  # Pacman is moving
            state.data._eaten = [False for i in range(state.getNumAgents())]
            PacmanRules.applyAction( state, action )
            state.data.scoreChange -= TIME_PENALTY # Penalty for waiting around
        else:                # A ghost is moving
            GhostRules.applyAction(state, action, agentIndex)
            GhostRules.decrementTimer(agentState)

        # Resolve multi-agent effects
        GhostRules.checkDeath( state, agentIndex )
        if action == Directions.LASER:
            GhostRules.checkLaserShot(state,agentIndex)
        if action == Directions.BLAST:
            GhostRules.checkBlast(state,agentIndex)

        # Book keeping
        state.data._agentMoved = agentIndex
        # Note:  It is important that the following value accurately
        # reflects when Pacman will make the next move, even if the
        # speed changes (such as a speed-up power pellet).  Otherwise
        # the graphics will do weird things.
        state.data._timeTillAgentMovesAgain = delay
        state.data._action = action
        state.data.score += state.data.scoreChange

        return state

    def runEvent( self ):
        # Check that successors exist
        if self.eventQueue.isEmpty():
            raise Exception('Can\'t run an event of a terminal state.')

        time, event = self.eventQueue.pop()
        assert not event.isAgentMove(), 'Can\'t run an AgentMoveEvent'
        self.data.time = time
        event.trigger(self)
        return event

    def getNextEvent( self ):
        _, event = self.eventQueue.peek()
        return event

    def getLegalPacmanActions( self ):
        return self.getLegalActions( 0 )

    def getPacmanState( self ):
        """
        Returns an AgentState object for pacman (in game.py)

        state.pos gives the current position
        state.direction gives the travel vector
        """
        return self.data.agentStates[0].copy()

    def getPacmanPosition( self ):
        return self.data.agentStates[0].getPosition()

    def getPacmanDirection(self):
        return self.data.agentStates[0].getDirection()

    def getGhostStates( self ):
        return self.data.agentStates[1:]

    def getGhostState( self, agentIndex ):
        if agentIndex == 0 or agentIndex >= self.getNumAgents():
            raise Exception("Invalid index passed to getGhostState")
        return self.data.agentStates[agentIndex]

    def getGhostPosition( self, agentIndex ):
        if agentIndex == 0:
            raise Exception("Pacman's index passed to getGhostPosition")
        return self.data.agentStates[agentIndex].getPosition()

    def getGhostPositions(self):
        return [s.getPosition() for s in self.getGhostStates()]

    def getNextAgentIndex(self):
        for time, event in self.eventQueue.getSortedTimesAndEvents():
            if event.isAgentMove():
                return event.getAgentIndex()
        assert False, "No more moves can be made"

    def getAgentMoveTime(self, agentIndex):
        for time, event in self.eventQueue.getSortedTimesAndEvents():
            if event.isAgentMove():
                if event.getAgentIndex() == agentIndex:
                    return time
        assert False, "No more moves can be made by agent " + str(agentIndex)

    def getNumAgents( self ):
        return len( self.data.agentStates )

    def getScore( self ):
        return float(self.data.score)

    def getCapsules(self):
        """
        Returns a list of positions (x,y) of the remaining capsules.
        """
        return self.data.capsules

    def getNumFood( self ):
        return self.data.food.count()

    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 call

        currentFood = state.getFood()
        if currentFood[x][y] == True: ...
        """
        return self.data.food

    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 call

        walls = state.getWalls()
        if walls[x][y] == True: ...
        """
        return self.data.walls

    def hasFood(self, x, y):
        return self.data.food[x][y]

    def hasWall(self, x, y):
        return self.data.walls[x][y]

    def isLose( self ):
        return self.data._lose

    def isWin( self ):
        return self.data._win

    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__( self, prevState = None ):
        """
        Generates a new state by copying information from its predecessor.
        """
        if prevState != None: # Initial state
            self.data = GameStateData(prevState.data)
            self.eventQueue = prevState.eventQueue.deepCopy()
        else:
            self.data = GameStateData()
            self.eventQueue = EventQueue()

    def resolveEventsUntilAgentEvent(self):
        # Resolve any events until the next agent event
        while not self.eventQueue.isEmpty():
            time, event = self.eventQueue.peek()
            if event.isAgentMove():
                return
            else:
                self.runEvent()

    def registerEventWithDelay(self, event, delay):
        self.eventQueue.registerEventAtTime(event, self.data.time + delay)

    def deepCopy( self ):
        state = GameState( self )
        state.data = self.data.deepCopy()
        # Event queue has already been copied in the constructor
        return state

    def __eq__( self, other ):
        """
        Allows two states to be compared.
        """
        return hasattr(other, 'data') and self.data == other.data \
            and hasattr(other, 'eventQueue') and self.eventQueue == other.eventQueue \

    def __hash__( self ):
        """
        Allows states to be keys of dictionaries.
        """
        return hash( (self.data, self.eventQueue) )

    def __str__( self ):

        return str(self.data)

    def initialize( self, layout, pacmanPowers, ghostPowers, numGhostAgents=1000 ):
        """
        Creates an initial game state from a layout array (see layout.py).
        """
        self.data.initialize(layout, pacmanPowers, ghostPowers, numGhostAgents)
        numAgents = self.getNumAgents()
        for i in range(numAgents):
            self.registerEventWithDelay(AgentMoveEvent(i), i)
        self.registerEventWithDelay(WallTimerEvent(), 1)
Пример #27
0
class GameState:

    explored = set()

    def getAndResetExplored():
        tmp = GameState.explored.copy()
        GameState.explored = set()
        return tmp
    getAndResetExplored = staticmethod(getAndResetExplored)

    def getLegalActions(self, agentIndex=0):
        """
        Returns the legal actions for the agent specified.
        """
        # GameState.explored.add(self)
        if self.isWin() or self.isLose():
            return []

        if agentIndex == 0:  # Pacman is moving
            return PacmanRules.getLegalActions(self)
        else:
            return GhostRules.getLegalActions(self, agentIndex)

    def generateSuccessor(self, agentIndex, action):
        """
        Returns the successor state after the specified agent takes the action.
        """
        # Check that successors exist
        if self.isWin() or self.isLose():
            raise Exception('Can\'t generate a successor of a terminal state.')

        # Copy current state
        state = GameState(self)

        # Let agent's logic deal with its action's effects on the board
        if agentIndex == 0:  # Pacman is moving
            state.data._eaten = [False for i in range(state.getNumAgents())]
            PacmanRules.applyAction(state, action)
        else:                # A ghost is moving
            GhostRules.applyAction(state, action, agentIndex)

        # Time passes
        if agentIndex == 0:
            state.data.scoreChange += -TIME_PENALTY  # Penalty for waiting around
        else:
            GhostRules.decrementTimer(state.data.agentStates[agentIndex])

        # Resolve multi-agent effects
        GhostRules.checkDeath(state, agentIndex)

        # Book keeping
        state.data._agentMoved = agentIndex
        state.data.score += state.data.scoreChange
        GameState.explored.add(self)
        GameState.explored.add(state)
        return state

    def getLegalPacmanActions(self):
        return self.getLegalActions(0)

    def generatePacmanSuccessor(self, action):
        """
        Generates the successor state after the specified pacman move
        """
        return self.generateSuccessor(0, action)

    def getPacmanState(self):
        return self.data.agentStates[0].copy()

    def getPacmanPosition(self):
        return self.data.agentStates[0].getPosition()

    def getGhostStates(self):
        return self.data.agentStates[1:]

    def getGhostState(self, agentIndex):
        if agentIndex == 0 or agentIndex >= self.getNumAgents():
            raise Exception("Invalid index passed to getGhostState")
        return self.data.agentStates[agentIndex]

    def getGhostPosition(self, agentIndex):
        if agentIndex == 0:
            raise Exception("Pacman's index passed to getGhostPosition")
        return self.data.agentStates[agentIndex].getPosition()

    def getGhostPositions(self):
        return [s.getPosition() for s in self.getGhostStates()]

    def getNumAgents(self):
        return len(self.data.agentStates)

    def getScore(self):
        return float(self.data.score)

    def getCapsules(self):
        return self.data.capsules

    def getNumFood(self):
        return self.data.food.count()

    def getFood(self):
        return self.data.food

    def getWalls(self):
        return self.data.layout.walls

    def hasFood(self, x, y):
        return self.data.food[x][y]

    def hasWall(self, x, y):
        return self.data.layout.walls[x][y]

    def isLose(self):
        return self.data._lose

    def isWin(self):
        return self.data._win


    def __init__(self, prevState=None):
        if prevState != None:  # Initial state
            self.data = GameStateData(prevState.data)
        else:
            self.data = GameStateData()

    def deepCopy(self):
        state = GameState(self)
        state.data = self.data.deepCopy()
        return state

    def __eq__(self, other):
        """
        Allows two states to be compared.
        """
        return hasattr(other, 'data') and self.data == other.data

    def __hash__(self):
        """
        Allows states to be keys of dictionaries.
        """
        return hash(self.data)

    def __str__(self):

        return str(self.data)

    def initialize(self, layout, numGhostAgents=1000):
        """
        Creates an initial game state from a layout array (see layout.py).
        """
        self.data.initialize(layout, numGhostAgents)
Пример #28
0
class CornerMaz:
    # static variable keeps track of which states have had getLegalActions called
    explored = set()

    def generateSuccessor(self, agentIndex, action):
        """
        Returns the successor state after the specified agent takes the action.
        """
        # Check that successors exist
        if self.isWin() or self.isLose():
            raise Exception('Can\'t generate a successor of a terminal state.')

        # Copy current state
        state = CornerMaz(self)

        # Let agent's logic deal with its action's effects on the board
        if agentIndex == 0:  # Pacman is moving
            state.data._eaten = [False for i in range(state.getNumAgents())]
            PacmanRules.applyAction(state, action)

        # Time passes
        if agentIndex == 0:
            state.data.scoreChange += -TIME_PENALTY  # Penalty for waiting around

        # Book keeping
        state.data._agentMoved = agentIndex
        state.data.score += state.data.scoreChange
        GameState.explored.add(self)
        GameState.explored.add(state)
        return state

    def getLegalPacmanActions(self):
        return self.getLegalActions(0)

    def generatePacmanSuccessor(self, action):
        """
        Generates the successor state after the specified pacman move
        """
        return self.generateSuccessor(0, action)

    def getPacmanState(self):
        """
        Returns an AgentState object for pacman (in game.py)

        state.pos gives the current position
        state.direction gives the travel vector
        """
        return self.data.agentStates[0].copy()

    def getPacmanPosition(self):
        return self.data.agentStates[0].getPosition()

    def getNumFood(self):
        return self.data.food.count()

    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 call

        currentFood = state.getFood()
        if currentFood[x][y] == True: ...
        """
        return self.data.food

    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 call

        walls = state.getWalls()
        if walls[x][y] == True: ...
        """
        return self.data.layout.walls

    def isLose(self):
        return self.data._lose

    def isWin(self):
        return self.data._win

    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__(self, prevState=None):
        """
        Generates a new state by copying information from its predecessor.
        """
        if prevState != None:  # Initial state
            self.data = GameStateData(prevState.data)
        else:
            self.data = GameStateData()

    def deepCopy(self):
        state = GameState(self)
        state.data = self.data.deepCopy()
        return state

    def __eq__(self, other):
        """
        Allows two states to be compared.
        """
        return hasattr(other, 'data') and self.data == other.data

    def __hash__(self):
        """
        Allows states to be keys of dictionaries.
        """
        return hash(self.data)

    def __str__(self):

        return str(self.data)

    def initialize(self, layout, numGhostAgents=1000):
        """
        Creates an initial game state from a layout array (see layout.py).
        """
        self.data.initialize(layout, numGhostAgents)
Пример #29
0
class PacmanPlot(PacmanGraphics):
    def __init__(self, x=None, y=None, zoom=1.0, frameTime=0.0):
        """
        Create and dispaly a pacman plot figure.
        
        If both x and y are provided, plot the points (x[i],y[i]) for all i in len(x).
        
        This will draw on the existing pacman window (clearing it first) or create a new one if no window exists.
        
        x: array or list of N scalar values. Default=None, in which case no points will be plotted
        y: array or list of N scalar values. Default=None, in which case no points will be plotted
        """        
        super(PacmanPlot, self).__init__(zoom, frameTime)

        if x is None or y is None:
            width = 23
            height = 23
            xmin = -(width-1)/2+1
            ymin = -(height-1)/2+1
            
            self.initPlot(xmin, ymin, width, height)
        else:
            self.plot(x,y)

    def initPlot(self, xmin, ymin, width, height):
        if graphicsUtils._canvas is not None:
            graphicsUtils.clear_screen()
        
        # Initialize GameStateData with blank board with axes    
        self.width = width
        self.height = height
        self.xShift = -(xmin-1)
        self.yShift = -(ymin-1)
        self.line = None

        self.zoom = min(30.0/self.width, 20.0/self.height)
        self.gridSize = graphicsDisplay.DEFAULT_GRID_SIZE * self.zoom


#         fullRow = ['%']*self.width
#         row = ((self.width-1)/2)*[' '] + ['%'] + ((self.width-1)/2)*[' ']
#         boardText = ((self.height-1)/2)*[row] + [fullRow] + ((self.height-1)/2)*[row]

        numSpaces = self.width-1
        numSpacesLeft = self.xShift
        numSpacesRight = numSpaces-numSpacesLeft

        numRows = self.height
        numRowsBelow = self.yShift
        numRowsAbove = numRows-1-numRowsBelow


        fullRow = ['%']*self.width
        if numSpacesLeft < 0:
            row = [' ']*self.width
        else:
            row = numSpacesLeft*[' '] + ['%'] + numSpacesRight*[' ']
        boardText = numRowsAbove*[row] + [fullRow] + numRowsBelow*[row]

        layout = Layout(boardText)
    
        self.blankGameState = GameStateData()
        self.blankGameState.initialize(layout, 0)
        self.initialize(self.blankGameState)
        title = 'Pacman Plot'
        graphicsUtils.changeText(self.infoPane.scoreText, title)
        graphicsUtils.refresh()
        
    def plot(self, x, y, weights=None, title='Pacman Plot'):
        """
        Plot the input values x with their corresponding output values y (either true or predicted).
        Also, plot the linear regression line if weights are given; assuming h_w(x) = weights[0]*x + weights[1].
        
        This will draw on the existing pacman window (clearing it first) or create a new one if no window exists.
        
        x: array or list of N scalar values.
        y: array or list of N scalar values.
        weights: array or list of 2 values (or if just one value, the bias weight is assumed to be zero). If None,
            no line is drawn. Default: None
        """
        if np.array(x).size == 0:
            return
        
        if isinstance(x[0], np.ndarray):
            # Scrape the first element of each data point
            x = [data[0] for data in x]
        
        xmin = int(math.floor(min(x)))
        ymin = int(math.floor(min(y)))
        xmax = int(math.ceil(max(x)))
        ymax = int(math.ceil(max(y)))
        width = xmax-xmin+3
        height = ymax-ymin+3
        self.initPlot(xmin, ymin, width, height)
        
        gameState = self.blankGameState.deepCopy()
                
        gameState.agentStates = []
        
        # Add ghost at each point
        for (px,py) in zip(x,y):
            point = (px+self.xShift, py+self.yShift)
            gameState.agentStates.append( AgentState( Configuration( point, Directions.STOP), False) )

#         self.initialize(gameState)
        graphicsUtils.clear_screen()
        self.infoPane = InfoPane(gameState.layout, self.gridSize)
        self.drawStaticObjects(gameState)
        self.drawAgentObjects(gameState)

        graphicsUtils.changeText(self.infoPane.scoreText, title)
        graphicsUtils.refresh()

    
    def setWeights(self, weights):
        pass        
        
    def takeControl(self):
        """
        Give full control to the window. Blocks current thread. Program will exit when window is closed.
        """
        mainloop()
Пример #30
0
class GameState:
    """
    A GameState specifies the full game state, including the food, capsules,
    agent configurations and score changes.

    GameStates are used by the Game object to capture the actual state of the game and
    can be used by agents to reason about the game.

    Much of the information in a GameState is stored in a GameStateData object.  We
    strongly suggest that you access that data via the accessor methods below rather
    than referring to the GameStateData object directly.

    Note that in classic Pacman, Pacman is always agent 0.
    """

    ####################################################
    # Accessor methods: use these to access state data #
    ####################################################

    # static variable keeps track of which states have had getLegalActions called
    explored = set()

    def getAndResetExplored():
        tmp = GameState.explored.copy()
        GameState.explored = set()
        return tmp

    getAndResetExplored = staticmethod(getAndResetExplored)

    def getLegalActions(self, agentIndex=0):
        """
        Returns the legal actions for the agent specified.
        """
        #        GameState.explored.add(self)
        if self.isWin() or self.isLose(): return []

        if agentIndex == 0:  # Pacman is moving
            return PacmanRules.getLegalActions(self)
        else:
            return GhostRules.getLegalActions(self, agentIndex)

    def generateSuccessor(self, agentIndex, action):
        """
        Returns the successor state after the specified agent takes the action.
        """
        # Check that successors exist
        if self.isWin() or self.isLose():
            raise Exception('Can\'t generate a successor of a terminal state.')

        # Copy current state
        state = GameState(self)

        # Let agent's logic deal with its action's effects on the board
        if agentIndex == 0:  # Pacman is moving
            state.data._eaten = [False for i in range(state.getNumAgents())]
            PacmanRules.applyAction(state, action)
        else:  # A ghost is moving
            GhostRules.applyAction(state, action, agentIndex)

        # Time passes
        if agentIndex == 0:
            state.data.scoreChange += -TIME_PENALTY  # Penalty for waiting around
        else:
            GhostRules.decrementTimer(state.data.agentStates[agentIndex])

        # Resolve multi-agent effects
        GhostRules.checkDeath(state, agentIndex)

        # Book keeping
        state.data._agentMoved = agentIndex
        state.data.score += state.data.scoreChange
        GameState.explored.add(self)
        GameState.explored.add(state)
        return state

    def getLegalPacmanActions(self):
        return self.getLegalActions(0)

    def generatePacmanSuccessor(self, action):
        """
        Generates the successor state after the specified pacman move
        """
        return self.generateSuccessor(0, action)

    def getPacmanState(self):
        """
        Returns an AgentState object for pacman (in game.py)

        state.pos gives the current position
        state.direction gives the travel vector
        """
        return self.data.agentStates[0].copy()

    def getPacmanPosition(self):
        return self.data.agentStates[0].getPosition()

    def getGhostStates(self):
        return self.data.agentStates[1:]

    def getGhostState(self, agentIndex):
        if agentIndex == 0 or agentIndex >= self.getNumAgents():
            raise Exception("Invalid index passed to getGhostState")
        return self.data.agentStates[agentIndex]

    def getGhostPosition(self, agentIndex):
        if agentIndex == 0:
            raise Exception("Pacman's index passed to getGhostPosition")
        return self.data.agentStates[agentIndex].getPosition()

    def getGhostPositions(self):
        return [s.getPosition() for s in self.getGhostStates()]

    def getNumAgents(self):
        return len(self.data.agentStates)

    def getScore(self):
        return float(self.data.score)

    def getCapsules(self):
        """
        Returns a list of positions (x,y) of the remaining capsules.
        """
        return self.data.capsules

    def getNumFood(self):
        return self.data.food.count()

    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 call

        currentFood = state.getFood()
        if currentFood[x][y] == True: ...
        """
        return self.data.food

    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 call

        walls = state.getWalls()
        if walls[x][y] == True: ...
        """
        return self.data.layout.walls

    def hasFood(self, x, y):
        return self.data.food[x][y]

    def hasWall(self, x, y):
        return self.data.layout.walls[x][y]

    def isLose(self):
        return self.data._lose

    def isWin(self):
        return self.data._win

    #############################################
    #             Elena methods :               #
    # Metodos anhadidos para funcionalidad q    #
    #############################################
    """
    FOOD
    """

    def getDistanceNearestFood(self):
        """
        Returns the distance to the nearest food
        """
        if (self.getNumFood() > 0):
            minDistance = 900000
            pacmanPosition = self.getPacmanPosition()
            for i in range(self.data.layout.width):
                for j in range(self.data.layout.height):
                    if self.hasFood(i, j):
                        foodPosition = i, j
                        distance = util.manhattanDistance(
                            pacmanPosition, foodPosition)
                        if distance < minDistance:
                            minDistance = distance
            return minDistance

        else:
            return None

    def getPositionNearestFood(self):
        if not self.getFoodPositions():
            return None
        else:
            return min(self.getFoodPositions())

    def getFoodPositions(self):
        """
        Elena: returns an array of food positions
        """
        foodPositionArray = []
        for i in range(self.data.layout.width):
            for j in range(self.data.layout.height):
                if self.hasFood(i, j):
                    foodPositionArray.append((i, j))

        return foodPositionArray

    """
    GHOSTS
    """

    def getLivingGhosts(self):
        """
        Returns a list of booleans indicating which ghosts are not yet captured.

        The first entry (a placeholder for Pacman's index) is always False.
        """
        return self.livingGhosts

    def getPositionNearestGhost(self):
        if all(v is None for v in self.data.ghostDistances):
            return None
        else:
            livingGhosts = self.getLivingGhosts()
            return self.getGhostPositions()[self.data.ghostDistances.index(
                min(value for value in self.data.ghostDistances
                    if value is not None))]

    def getGhostDirections(self):
        return self.ghostDirections

    def setGhostNotLiving(self, index):
        self.livingGhosts[index] = False

    """
    WALLS: POR DEFINIR
    """

    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__(self, prevState=None):
        """
        Generates a new state by copying information from its predecessor.
        """
        if prevState != None:  # Initial state
            self.data = GameStateData(prevState.data)
        else:
            self.data = GameStateData()

    def deepCopy(self):
        state = GameState(self)
        state.data = self.data.deepCopy()
        return state

    def __eq__(self, other):
        """
        Allows two states to be compared.
        """
        return hasattr(other, 'data') and self.data == other.data

    def __hash__(self):
        """
        Allows states to be keys of dictionaries.
        """
        return hash(self.data)

    def __str__(self):

        return str(self.data)

    def initialize(self, layout, numGhostAgents=1000):
        """
        Creates an initial game state from a layout array (see layout.py).
        """
        self.data.initialize(layout, numGhostAgents)
Пример #31
0
 def __init__(self, prevState=None):
     if prevState != None:  # Initial state
         self.data = GameStateData(prevState.data)
     else:
         self.data = GameStateData()
Пример #32
0
class PacmanPlotLP(PacmanGraphics):
    def __init__(self,
                 constraints=[],
                 infeasiblePoints=[],
                 feasiblePoints=[],
                 optimalPoint=None,
                 costVector=None,
                 zoom=1.0,
                 frameTime=0.0):
        """
        Create and dispaly a pacman plot figure.
        
        This will draw on the existing pacman window (clearing it first) or create a new one if no window exists.
        
        constraints: list of inequality constraints, where each constraint w1*x + w2*y <= b is represented as a tuple ((w1, w2), b)
        infeasiblePoints (food): list of points where each point is a tuple (x, y)
        feasiblePoints (power): list of points where each point is a tuple (x, y)
        optimalPoint (pacman): optimal point as a tuple (x, y)
        costVector (shading): cost vector represented as a tuple (c1, c2), where cost is c1*x + c2*x
        """
        super(PacmanPlotLP, self).__init__(zoom, frameTime)

        xmin = 100000
        ymin = 100000
        xmax = -100000
        ymax = -100000

        for point in feasiblePoints:
            if point[0] < xmin:
                xmin = point[0]
            if point[0] > xmax:
                xmax = point[0]
            if point[1] < ymin:
                ymin = point[1]
            if point[1] > ymax:
                ymax = point[1]

        if len(feasiblePoints) == 0:
            for point in infeasiblePoints:
                if point[0] < xmin:
                    xmin = point[0]
                if point[0] > xmax:
                    xmax = point[0]
                if point[1] < ymin:
                    ymin = point[1]
                if point[1] > ymax:
                    ymax = point[1]

        xmin = int(math.floor(xmin)) - 3
        ymin = int(math.floor(ymin)) - 3
        xmax = int(math.ceil(xmax)) + 3
        ymax = int(math.ceil(ymax)) + 3
        width = xmax - xmin + 1
        height = ymax - ymin + 1

        #        p = feasiblePoints[2]
        #        print("p={}".format(p))
        #        print("feasible={}".format(self.pointFeasible(p, constraints)))
        #        g = self.cartesianToLayout(xmin, ymin, xmax, ymax, p)
        #        print("g={}".format(g))
        #        gr = (int(round(g[0])), int(round(g[1])))
        #        p2 = self.layoutToCartesian(xmin, ymin, xmax, ymax, gr)
        #        print("p2={}".format(p2))
        #        print("p2 feasible={}".format(self.pointFeasible(p2, constraints)))

        layoutLists = self.blankLayoutLists(width, height)

        self.addInfeasibleGhosts(layoutLists, constraints, xmin, ymin, xmax,
                                 ymax)

        layoutLists = self.changeBorderGhostsToWall(layoutLists)

        for point in infeasiblePoints:
            self.addCartesianPointToLayout(layoutLists, point, '.', xmin, ymin,
                                           xmax, ymax)

        for point in feasiblePoints:
            self.addCartesianPointToLayout(layoutLists, point, 'o', xmin, ymin,
                                           xmax, ymax)

        if optimalPoint is not None:
            self.addCartesianPointToLayout(layoutLists, optimalPoint, 'P',
                                           xmin, ymin, xmax, ymax)

        if graphicsUtils._canvas is not None:
            graphicsUtils.clear_screen()

        # Initialize GameStateData with blank board with axes
        self.width = width
        self.height = height

        self.zoom = min(30.0 / self.width, 20.0 / self.height)
        self.gridSize = graphicsDisplay.DEFAULT_GRID_SIZE * self.zoom

        maxNumGhosts = 10000
        layout = Layout(layoutLists)
        self.blankGameState = GameStateData()
        self.blankGameState.initialize(layout, maxNumGhosts)
        self.initialize(self.blankGameState)
        title = 'Pacman Plot LP'
        graphicsUtils.changeText(self.infoPane.scoreText, title)
        graphicsUtils.refresh()

        if costVector is not None:
            self.shadeCost(layoutLists, constraints, costVector,
                           feasiblePoints, xmin, ymin, xmax, ymax)

    def takeControl(self):
        """
        Give full control to the window. Blocks current thread. Program will exit when window is closed.
        """
        mainloop()

    def pointCost(self, costVector, point):
        return costVector[0] * point[0] + costVector[1] * point[1]

    def shadeCost(self, layout, constraints, costVector, feasiblePoints, xmin,
                  ymin, xmax, ymax):
        baseColor = [1.0, 0.0, 0.0]

        costs = [self.pointCost(costVector, point) for point in feasiblePoints]
        minCost = min(costs)
        maxCost = max(costs)
        costSpan = maxCost - minCost

        allFeasiblePoints = self.getFeasibleLayoutPoints(
            layout, constraints, xmin, ymin, xmax, ymax)

        # The feasible points themselves may have been gridded to infeasible grid points,
        # but we want to make sure they are shaded too.
        #cornerPoints = [self.cartesianToLayout(xmin, ymin, xmax, ymax, point) for point in feasiblePoints]
        cornerPoints = self.getLayoutPointsWithSymbol(layout, ('o', 'P'))

        gridPointsToShade = cornerPoints + allFeasiblePoints

        for gridPoint in gridPointsToShade:
            point = self.layoutToCartesian(xmin, ymin, xmax, ymax, gridPoint)

            relativeCost = (self.pointCost(costVector, point) -
                            minCost) * 1.0 / costSpan

            # Whoops our grid points are flipped top-bottom from what to_screen expects
            screenPos = self.to_screen(
                (gridPoint[0], len(layout) - gridPoint[1] - 1))

            cellColor = [
                0.25 + 0.5 * relativeCost * channel for channel in baseColor
            ]

            graphicsUtils.square(screenPos,
                                 0.5 * self.gridSize,
                                 color=graphicsUtils.formatColor(*cellColor),
                                 filled=1,
                                 behind=2)

        graphicsUtils.refresh()

    def layoutToCartesian(self, xmin, ymin, xmax, ymax, point):
        xnew = point[0] + xmin
        ynew = (ymax - ymin) - point[1] + ymin

        return (xnew, ynew)

    def cartesianToLayout(self, xmin, ymin, xmax, ymax, point):
        xnew = point[0] - xmin
        ynew = (ymax - ymin) - (point[1] - ymin)

        return (xnew, ynew)

    def printLayout(self, layout):
        print('-' * (len(layout[0]) + 2))
        for row in layout:
            print('|' + ''.join(row) + '|')
        print('-' * (len(layout[0]) + 2))

    def blankLayoutLists(self, width, height):
        layout = []
        for _ in range(height):
            row = [' '] * width
            layout.append(row)

        return layout

    def roundPoint(self, p):
        return (int(round(p[0])), int(round(p[1])))

    def setLayoutWall(self, layout, point):
        self.setLayoutPoint(layout, point, '%')

    def getLayoutPointsWithSymbol(self, layout, symbolSet):
        points = []
        for gy in range(len(layout)):
            for gx in range(len(layout[0])):
                if layout[gy][gx] in symbolSet:
                    points.append((gx, gy))

        return points

    def getLayoutSymbol(self, layout, point):
        point = self.roundPoint(point)

        if point[0] >= 0 and point[0] < len(
                layout[0]) and point[1] >= 0 and point[1] < len(layout):
            return layout[point[1]][point[0]]

        return None

    def setLayoutPoint(self, layout, point, symbol):
        point = self.roundPoint(point)

        if point[0] >= 0 and point[0] < len(
                layout[0]) and point[1] >= 0 and point[1] < len(layout):
            layout[point[1]][point[0]] = symbol
            return True

        return False

    def distance(self, p1, p2):
        vec = (p2[0] - p1[0], p2[1] - p1[1])
        vecLen = math.sqrt(vec[0]**2 + vec[1]**2)
        return vecLen

    def addLineToLayout(self, layout, p1, p2):
        radius = 1
        STEPS_PER_UNIT = 10

        fullVec = (p2[0] - p1[0], p2[1] - p1[1])
        fullVecLen = math.sqrt(fullVec[0]**2 + fullVec[1]**2)

        stepVec = (fullVec[0] / fullVecLen / STEPS_PER_UNIT,
                   fullVec[1] / fullVecLen / STEPS_PER_UNIT)
        numSteps = int(math.ceil(fullVecLen) * STEPS_PER_UNIT)

        self.setLayoutWall(layout, p1)
        point = p1
        while point != p2:
            # Generate four connected points
            deltas = [(-1, 0), (0, 1), (1, 0), (0, -1)]
            nextPoints = [(point[0] + delta[0], point[1] + delta[1])
                          for delta in deltas]
            distances = [
                self.distance(nextPoint, p2) for nextPoint in nextPoints
            ]
            minDist = distances[0]
            minIndex = 0
            for i, dist in enumerate(distances):
                if dist < minDist:
                    minDist = dist
                    minIndex = i
            #print("distances={}, minIndex={}".format(distances, minIndex))

            point = nextPoints[minIndex]
            self.setLayoutWall(layout, point)
            #print("p1={}, point={}, p2={}".format(p1, point, p2))

        #for n in range(1, numSteps+1):
        #    x = p1[0] + n*stepVec[0]
        #    y = p1[1] + n*stepVec[1]
        #    self.setLayoutWall(layout, (x,y))

    def getCartesianSymbol(self, layout, point, xmin, ymin, xmax, ymax):
        point = self.cartesianToLayout(xmin, ymin, xmax, ymax, point)
        return self.getLayoutSymbol(layout, point)

    def addCartesianPointToLayout(self, layout, point, symbol, xmin, ymin,
                                  xmax, ymax):
        point = self.cartesianToLayout(xmin, ymin, xmax, ymax, point)
        return self.setLayoutPoint(layout, point, symbol)

    def addCartesianLineToLayout(self, layout, w1, w2, b, xmin, ymin, xmax,
                                 ymax):
        (p1, p2) = lineBoxIntersection(w1, w2, b, xmin, ymin, xmax, ymax)
        p1 = self.cartesianToLayout(xmin, ymin, xmax, ymax, p1)
        p2 = self.cartesianToLayout(xmin, ymin, xmax, ymax, p2)

        self.addLineToLayout(layout, p1, p2)

    def pointFeasible(self, point, constraints):
        EPSILON = 1e-6
        for constraint in constraints:
            if constraint[0][0] * point[0] + constraint[0][1] * point[
                    1] > constraint[1] + EPSILON:
                #print("Infeasible: point={}, constraint={}".format(point, constraint))
                #print("\t{}*{} + {}*{} = {}".format(constraint[0][0], point[0], constraint[0][1], point[1], constraint[0][0]*point[0] + constraint[0][1]*point[1]))
                return False

        return True

    def getFeasibleLayoutPoints(self, layout, constraints, xmin, ymin, xmax,
                                ymax):
        height = len(layout)
        width = len(layout[0])

        layoutPoints = []

        for gy in range(height):
            for gx in range(width):
                point = self.layoutToCartesian(xmin, ymin, xmax, ymax,
                                               (gx, gy))
                if self.pointFeasible(point, constraints):
                    layoutPoints.append((gx, gy))

        return layoutPoints

    def addInfeasibleGhosts(self, layout, constraints, xmin, ymin, xmax, ymax):
        numGhosts = 0

        height = len(layout)
        width = len(layout[0])

        for gy in range(height):
            for gx in range(width):
                point = self.layoutToCartesian(xmin, ymin, xmax, ymax,
                                               (gx, gy))
                if not self.pointFeasible(point, constraints):
                    self.setLayoutPoint(layout, (gx, gy), 'G')
                    numGhosts += 1

        return numGhosts

    def isSymbolNeighbor(self, layout, point, symbols):
        deltas = [(-1, -1), (-1, 0), (-1, 1), (0, 1), (1, 1), (1, 0), (1, -1),
                  (0, -1)]

        neighborSymbols = [
            self.getLayoutSymbol(layout,
                                 (point[0] + delta[0], point[1] + delta[1]))
            for delta in deltas
        ]
        for symbol in symbols:
            if symbol in neighborSymbols:
                return True

        return False

    def changeBorderGhostsToWall(self, layout):
        width = len(layout[0])
        height = len(layout)

        newLayout = self.blankLayoutLists(width, height)

        for gy in range(height):
            for gx in range(width):
                symbol = self.getLayoutSymbol(layout, (gx, gy))
                newLayout[gy][gx] = symbol

                if symbol == 'G':
                    if self.isSymbolNeighbor(layout, (gx, gy),
                                             (' ', 'o', 'P')):
                        newLayout[gy][gx] = '%'

        return newLayout
Пример #33
0
class PacmanPlot(PacmanGraphics):
    def __init__(self, x=None, y=None, zoom=1.0, frameTime=0.0):
        """
        Create and dispaly a pacman plot figure.

        If both x and y are provided, plot the points (x[i],y[i]) for all i in len(x).

        This will draw on the existing pacman window (clearing it first) or create a new one if no window exists.

        x: array or list of N scalar values. Default=None, in which case no points will be plotted
        y: array or list of N scalar values. Default=None, in which case no points will be plotted
        """
        super(PacmanPlot, self).__init__(zoom, frameTime)

        if x is None or y is None:
            width = 23
            height = 23
            xmin = -(width - 1) / 2 + 1
            ymin = -(height - 1) / 2 + 1

            self.initPlot(xmin, ymin, width, height)
        else:
            self.plot(x, y)

    def initPlot(self, xmin, ymin, width, height):
        if graphicsUtils._canvas is not None:
            graphicsUtils.clear_screen()

        # Initialize GameStateData with blank board with axes
        self.width = width
        self.height = height
        self.xShift = -(xmin - 1)
        self.yShift = -(ymin - 1)
        self.line = None

        self.zoom = min(30.0 / self.width, 20.0 / self.height)
        self.gridSize = graphicsDisplay.DEFAULT_GRID_SIZE * self.zoom

        #         fullRow = ['%']*self.width
        #         row = ((self.width-1)/2)*[' '] + ['%'] + ((self.width-1)/2)*[' ']
        #         boardText = ((self.height-1)/2)*[row] + [fullRow] + ((self.height-1)/2)*[row]

        numSpaces = self.width - 1
        numSpacesLeft = self.xShift
        numSpacesRight = numSpaces - numSpacesLeft

        numRows = self.height
        numRowsBelow = self.yShift
        numRowsAbove = numRows - 1 - numRowsBelow

        fullRow = ['%'] * self.width
        if numSpacesLeft < 0:
            row = [' '] * self.width
        else:
            row = numSpacesLeft * [' '] + ['%'] + numSpacesRight * [' ']
        boardText = numRowsAbove * [row] + [fullRow] + numRowsBelow * [row]

        layout = Layout(boardText)

        self.blankGameState = GameStateData()
        self.blankGameState.initialize(layout, 0)
        self.initialize(self.blankGameState)
        title = 'Pacman Plot'
        graphicsUtils.changeText(self.infoPane.scoreText, title)
        graphicsUtils.refresh()

    def plot(self, x, y, weights=None, title='Pacman Plot'):
        """
        Plot the input values x with their corresponding output values y (either true or predicted).
        Also, plot the linear regression line if weights are given; assuming h_w(x) = weights[0]*x + weights[1].

        This will draw on the existing pacman window (clearing it first) or create a new one if no window exists.

        x: array or list of N scalar values.
        y: array or list of N scalar values.
        weights: array or list of 2 values (or if just one value, the bias weight is assumed to be zero). If None,
            no line is drawn. Default: None
        """
        if np.array(x).size == 0:
            return

        if isinstance(x[0], np.ndarray):
            # Scrape the first element of each data point
            x = [data[0] for data in x]

        xmin = int(math.floor(min(x)))
        ymin = int(math.floor(min(y)))
        xmax = int(math.ceil(max(x)))
        ymax = int(math.ceil(max(y)))
        width = xmax - xmin + 3
        height = ymax - ymin + 3
        self.initPlot(xmin, ymin, width, height)

        gameState = self.blankGameState.deepCopy()

        gameState.agentStates = []

        # Add ghost at each point
        for (px, py) in zip(x, y):
            point = (px + self.xShift, py + self.yShift)
            gameState.agentStates.append(
                AgentState(Configuration(point, Directions.STOP), False))

#         self.initialize(gameState)
        graphicsUtils.clear_screen()
        self.infoPane = InfoPane(gameState.layout, self.gridSize)
        self.drawStaticObjects(gameState)
        self.drawAgentObjects(gameState)

        graphicsUtils.changeText(self.infoPane.scoreText, title)
        graphicsUtils.refresh()

    def setWeights(self, weights):
        pass

    def takeControl(self):
        """
        Give full control to the window. Blocks current thread. Program will exit when window is closed.
        """
        mainloop()
Пример #34
0
class GameState:
    """
    A GameState specifies the full game state, including the food, capsules,
    agent configurations and score changes.

    GameStates are used by the Game object to capture the actual state of the game and
    can be used by agents to reason about the game.

    Much of the information in a GameState is stored in a GameStateData object.  We
    strongly suggest that you access that data via the accessor methods below rather
    than referring to the GameStateData object directly.

    Note that in classic Pacman, Pacman is always agent 0.
    """

    ####################################################
    # Accessor methods: use these to access state data #
    ####################################################

    def getLegalActions( self, agentIndex=0 ):
        """
        Returns the legal actions for the agent specified.
        """
        if self.isWin() or self.isLose(): return []

        if agentIndex == 0:  # Pacman is moving
            return PacmanRules.getLegalActions( self )
        else:
            return GhostRules.getLegalActions( self, agentIndex )

    def generateSuccessor( self, agentIndex, action):
        """
        Returns the successor state after the specified agent takes the action.
        """
        # Check that successors exist
        if self.isWin() or self.isLose(): raise Exception('Can\'t generate a successor of a terminal state.')

        # Copy current state
        state = GameState(self)

        # Let agent's logic deal with its action's effects on the board
        if agentIndex == 0:  # Pacman is moving
            state.data._eaten = [False for i in range(state.getNumAgents())]
            PacmanRules.applyAction( state, action )
        else:                # A ghost is moving
            GhostRules.applyAction( state, action, agentIndex )

        # Time passes
        if agentIndex == 0:
            state.data.scoreChange += -TIME_PENALTY # Penalty for waiting around
        else:
            GhostRules.decrementTimer( state.data.agentStates[agentIndex] )

        # Resolve multi-agent effects
        GhostRules.checkDeath( state, agentIndex )

        # Book keeping
        state.data._agentMoved = agentIndex
        state.data.score += state.data.scoreChange
        p = state.getPacmanPosition()

        if agentIndex == self.getNumAgents() - 1:
            state.numMoves += 1
        return state

    def getLegalPacmanActions( self ):
        return self.getLegalActions( 0 )

    def generatePacmanSuccessor( self, action ):
        """
        Generates the successor state after the specified pacman move
        """
        return self.generateSuccessor( 0, action )

    def getPacmanState( self ):
        """
        Returns an AgentState object for pacman (in game.py)

        state.pos gives the current position
        state.direction gives the travel vector
        """
        return self.data.agentStates[0].copy()

    def getPacmanPosition( self ):
        return self.data.agentStates[0].getPosition()

    def getNumAgents( self ):
        return len( self.data.agentStates )

    def getScore( self ):
        return self.data.score

    def getCapsules(self):
        """
        Returns a list of positions (x,y) of the remaining capsules.
        """
        return self.data.capsules

    def getNumFood( self ):
        return self.data.food.count()

    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 call

        currentFood = state.getFood()
        if currentFood[x][y] == True: ...
        """
        return self.data.food

    def getWalls(self):
        """
        Returns a Grid of boolean wall indicator variables.

        Grids can be accessed via list notation, so to check
        if there is food at (x,y), just call

        walls = state.getWalls()
        if walls[x][y] == True: ...
        """
        return self.data.layout.walls

    def hasFood(self, x, y):
        return self.data.food[x][y]

    def hasWall(self, x, y):
        return self.data.layout.walls[x][y]

    ##############################
    # Additions for Busters Pacman #
    ##############################

    def getLivingGhosts(self):
        """
        Returns a list of booleans indicating which ghosts are not yet captured.

        The first entry (a placeholder for Pacman's index) is always False.
        """
        return self.livingGhosts

    def setGhostNotLiving(self, index):
        self.livingGhosts[index] = False

    def isLose( self ):
        return self.maxMoves > 0 and self.numMoves >= self.maxMoves

    def isWin( self ):
        return self.livingGhosts.count(True) == 0



    def getTrueWallPerception(self,location):
        p = []
        x,y = location
        for action in [Directions.NORTH, Directions.SOUTH, Directions.EAST, Directions.WEST]:
            dx, dy = Actions.directionToVector(action)
            nextx, nexty = int(x + dx), int(y + dy)
            p.append( ( action,self.hasWall( nextx, nexty ) ) )

        return tuple(p)

    def getNoisyWalls(self):
        position = self.getPacmanPosition()
        perception = []
        for action in [Directions.NORTH, Directions.SOUTH, Directions.EAST, Directions.WEST]:
            x,y = position
            dx, dy = Actions.directionToVector(action)
            nextx, nexty = int(x + dx), int(y + dy)
            isWall = self.hasWall(nextx,nexty)

            if util.flipCoin(EPSILON): isWall = not isWall

            perception.append( ( action, isWall ) )

        return tuple(perception)

    def getBoardWidth(self):
        return self.getWalls().width

    def getBoardHeight(self):
        return self.getWalls().height



    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__( self, prevState = None ):
        """
        Generates a new state by copying information from its predecessor.
        """
        if prevState != None:
            self.data = GameStateData(prevState.data)
            self.livingGhosts = prevState.livingGhosts[:]
            self.numMoves = prevState.numMoves;
            self.maxMoves = prevState.maxMoves;
        else: # Initial state
            self.data = GameStateData()
            self.numMoves = 0;
            self.maxMoves = -1;


    def deepCopy( self ):
        state = GameState( self )
        state.data = self.data.deepCopy()

        return state

    def __eq__( self, other ):
        """
        Allows two states to be compared.
        """
        return self.data == other.data

    def __hash__( self ):
        """
        Allows states to be keys of dictionaries.
        """
        return hash( str( self ) )

    def __str__( self ):

        return str(self.data)

    def initialize( self, layout, numGhostAgents=1000 ):
        """
        Creates an initial game state from a layout array (see layout.py).
        """
        self.data.initialize(layout, numGhostAgents)
        self.livingGhosts = [False] + [True for i in range(numGhostAgents)]

    def getGhostPosition( self, agentIndex ):
        if agentIndex == 0:
            raise "Pacman's index passed to getGhostPosition"
        return self.data.agentStates[agentIndex].getPosition()

    def getGhostState( self, agentIndex ):
        if agentIndex == 0:
            raise "Pacman's index passed to getGhostPosition"
        return self.data.agentStates[agentIndex]
Пример #35
0
class GameState:
    """
  A GameState specifies the full game state, including the food, capsules, 
  agent configurations and score changes.
  
  GameStates are used by the Game object to capture the actual state of the game and
  can be used by agents to reason about the game.
  
  Much of the information in a GameState is stored in a GameStateData object.  We 
  strongly suggest that you access that data via the accessor methods below rather
  than referring to the GameStateData object directly.
  """

    ####################################################
    # Accessor methods: use these to access state data #
    ####################################################

    def getLegalActions(self, agentIndex=0):
        """
    Returns the legal actions for the agent specified.
    """
        return AgentRules.getLegalActions(self, agentIndex)

    def generateSuccessor(self, agentIndex, action):
        """
    Returns the successor state after the specified agent takes the action.
    """
        # Copy current state
        state = GameState(self)

        # Find appropriate rules for the agent
        AgentRules.applyAction(state, action, agentIndex)
        AgentRules.checkDeath(state, agentIndex)

        # Book keeping
        state.data._agentMoved = agentIndex
        state.data.score += state.data.scoreChange
        return state

    def getAgentState(self, index):
        return self.data.agentStates[index]

    def getAgentPosition(self, index):
        " Note: this could return None if the agent is unobservable "
        agentState = self.data.agentStates[index]
        return agentState.getPosition()

    def getNumAgents(self):
        return len(self.data.agentStates)

    def getScore(self):
        return self.data.score

    def getRedFood(self):
        return halfGrid(self.data.food, red=True)

    def getBlueFood(self):
        return halfGrid(self.data.food, red=False)

    def getWalls(self):
        """
    Just like getFood but for walls
    """
        return self.data.layout.walls

    def hasFood(self, x, y):
        return self.data.food[x][y]

    def hasWall(self, x, y):
        return self.data.layout.walls[x][y]

    def isOver(self):
        return self.data._win

    def getRedTeamIndices(self):
        return self.redTeam[:]

    def getBlueTeamIndices(self):
        return self.blueTeam[:]

    def isOnRedTeam(self, agentIndex):
        return self.teams[agentIndex]

    def getAgentDistances(self):
        "Returns a noisy distance to each agent."
        if 'agentDistances' in dir(self):
            return self.agentDistances
        else:
            return None

    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__(self, prevState=None):
        """ 
    Generates a new state by copying information from its predecessor.
    """
        if prevState != None:  # Initial state
            self.data = GameStateData(prevState.data)
            self.blueTeam = prevState.blueTeam
            self.redTeam = prevState.redTeam
            self.teams = prevState.teams
            self.agentDistances = prevState.agentDistances
        else:
            self.data = GameStateData()
            self.agentDistances = []

    def deepCopy(self):
        state = GameState(self)
        state.data = self.data.deepCopy()
        state.blueTeam = self.blueTeam[:]
        state.redTeam = self.redTeam[:]
        state.teams = self.teams[:]
        state.agentDistances = self.agentDistances[:]
        return state

    def makeObservation(self, index):
        state = self.deepCopy()

        # Adds the sonar signal
        pos = state.getAgentPosition(index)
        n = state.getNumAgents()
        distances = [
            noisyDistance(pos, state.getAgentPosition(i)) for i in range(n)
        ]
        state.agentDistances = distances

        # Remove states of distant opponents
        if index in self.blueTeam:
            team = self.blueTeam
            otherTeam = self.redTeam
        else:
            otherTeam = self.blueTeam
            team = self.redTeam

        for enemy in otherTeam:
            seen = False
            enemyPos = state.getAgentPosition(enemy)
            for teammate in team:
                if util.manhattanDistance(
                        enemyPos,
                        state.getAgentPosition(teammate)) <= SIGHT_RANGE:
                    seen = True
            if not seen: state.data.agentStates[enemy].configuration = None
        return state

    def __eq__(self, other):
        """
    Allows two states to be compared.
    """
        if other == None: return False
        return self.data == other.data

    def __hash__(self):
        """
    Allows states to be keys of dictionaries.
    """
        return int(hash(self.data))

    def __str__(self):

        return str(self.data)

    def initialize(self, layout, numAgents):
        """
    Creates an initial game state from a layout array (see layout.py).
    """
        self.data.initialize(layout, numAgents)
        positions = [a.configuration for a in self.data.agentStates]
        self.blueTeam = [
            i for i, p in enumerate(positions) if not self.isRed(p)
        ]
        self.redTeam = [i for i, p in enumerate(positions) if self.isRed(p)]
        self.teams = [self.isRed(p) for p in positions]

    def isRed(self, configOrPos):
        width = self.data.layout.width
        if type(configOrPos) == type((0, 0)):
            return configOrPos[0] < width / 2
        else:
            return configOrPos.pos[0] < width / 2
Пример #36
0
class GameState:
    """
    A GameState specifies the full game state, including the food, capsules,
    agent configurations and score changes.

    GameStates are used by the Game object to capture the actual state of the game and
    can be used by agents to reason about the game.

    Much of the information in a GameState is stored in a GameStateData object.  We
    strongly suggest that you access that data via the accessor methods below rather
    than referring to the GameStateData object directly.

    Note that in classic Pacman, Pacman is always agent 0.
    """

    ####################################################
    # Accessor methods: use these to access state data #
    ####################################################

    def getLegalActions(self, agentIndex=0):
        """
        Returns the legal actions for the agent specified.
        """
        if self.isWin() or self.isLose(): return []

        if agentIndex == 0:  # Pacman is moving
            return PacmanRules.getLegalActions(self)
        else:
            return GhostRules.getLegalActions(self, agentIndex)

    def getResult(self, agentIndex, action):
        """
        Returns the state after the specified agent takes the action.
        """
        # Check that successors exist
        if self.isWin() or self.isLose():
            raise Exception('Can\'t generate a result of a terminal state.')

        # Copy current state
        state = GameState(self)

        # Let agent's logic deal with its action's effects on the board
        if agentIndex == 0:  # Pacman is moving
            state.data._eaten = [False for i in range(state.getNumAgents())]
            PacmanRules.applyAction(state, action)
        else:  # A ghost is moving
            GhostRules.applyAction(state, action, agentIndex)

        # Time passes
        if agentIndex == 0:
            state.data.scoreChange += -TIME_PENALTY  # Penalty for waiting around
        else:
            GhostRules.decrementTimer(state.data.agentStates[agentIndex])

        # Resolve multi-agent effects
        GhostRules.checkDeath(state, agentIndex)

        # Book keeping
        state.data._agentMoved = agentIndex
        state.data.score += state.data.scoreChange
        p = state.getPacmanPosition()
        state.data.ghostDistances = [
            getNoisyDistance(p, state.getGhostPosition(i))
            for i in range(1, state.getNumAgents())
        ]
        if agentIndex == self.getNumAgents() - 1:
            state.numMoves += 1
        return state

    def getLegalPacmanActions(self):
        return self.getLegalActions(0)

    def getPacmanResult(self, action):
        """
        Generates the result state after the specified pacman action
        """
        return self.getResult(0, action)

    def getPacmanState(self):
        """
        Returns an AgentState object for pacman (in game.py)

        state.pos gives the current position
        state.direction gives the travel vector
        """
        return self.data.agentStates[0].copy()

    def getPacmanPosition(self):
        return self.data.agentStates[0].getPosition()

    def getNumAgents(self):
        return len(self.data.agentStates)

    def getScore(self):
        return self.data.score

    def getCapsules(self):
        """
        Returns a list of positions (x,y) of the remaining capsules.
        """
        return self.data.capsules

    def getNumFood(self):
        return self.data.food.count()

    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 call

        currentFood = state.getFood()
        if currentFood[x][y] == True: ...
        """
        return self.data.food

    def getWalls(self):
        """
        Returns a Grid of boolean wall indicator variables.

        Grids can be accessed via list notation, so to check
        if there is food at (x,y), just call

        walls = state.getWalls()
        if walls[x][y] == True: ...
        """
        return self.data.layout.walls

    def hasFood(self, x, y):
        return self.data.food[x][y]

    def hasWall(self, x, y):
        return self.data.layout.walls[x][y]

    ##############################
    # Additions for Busters Pacman #
    ##############################

    def getLivingGhosts(self):
        """
        Returns a list of booleans indicating which ghosts are not yet captured.

        The first entry (a placeholder for Pacman's index) is always False.
        """
        return self.livingGhosts

    def setGhostNotLiving(self, index):
        self.livingGhosts[index] = False

    def isLose(self):
        return self.maxMoves > 0 and self.numMoves >= self.maxMoves

    def isWin(self):
        return self.livingGhosts.count(True) == 0

    def getNoisyGhostDistances(self):
        """
        Returns a noisy distance to each ghost.
        """
        return self.data.ghostDistances

    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__(self, prevState=None):
        """
        Generates a new state by copying information from its predecessor.
        """
        if prevState != None:
            self.data = GameStateData(prevState.data)
            self.livingGhosts = prevState.livingGhosts[:]
            self.numMoves = prevState.numMoves
            self.maxMoves = prevState.maxMoves
        else:  # Initial state
            self.data = GameStateData()
            self.numMoves = 0
            self.maxMoves = -1
        self.data.ghostDistances = []

    def deepCopy(self):
        state = GameState(self)
        state.data = self.data.deepCopy()
        state.data.ghostDistances = self.data.ghostDistances
        return state

    def __eq__(self, other):
        """
        Allows two states to be compared.
        """
        if other is None:
            return False
        return self.data == other.data

    def __hash__(self):
        """
        Allows states to be keys of dictionaries.
        """
        return hash(str(self))

    def __str__(self):

        return str(self.data)

    def initialize(self, layout, numGhostAgents=1000):
        """
        Creates an initial game state from a layout array (see layout.py).
        """
        self.data.initialize(layout, numGhostAgents)
        self.livingGhosts = [False] + [True for i in range(numGhostAgents)]
        self.data.ghostDistances = [
            getNoisyDistance(self.getPacmanPosition(),
                             self.getGhostPosition(i))
            for i in range(1, self.getNumAgents())
        ]

    def getGhostPosition(self, agentIndex):
        if agentIndex == 0:
            raise "Pacman's index passed to getGhostPosition"
        return self.data.agentStates[agentIndex].getPosition()

    def getGhostState(self, agentIndex):
        if agentIndex == 0:
            raise "Pacman's index passed to getGhostPosition"
        return self.data.agentStates[agentIndex]
Пример #37
0
    def __init__(self,
                 constraints=[],
                 infeasiblePoints=[],
                 feasiblePoints=[],
                 optimalPoint=None,
                 costVector=None,
                 zoom=1.0,
                 frameTime=0.0):
        """
        Create and dispaly a pacman plot figure.
        
        This will draw on the existing pacman window (clearing it first) or create a new one if no window exists.
        
        constraints: list of inequality constraints, where each constraint w1*x + w2*y <= b is represented as a tuple ((w1, w2), b)
        infeasiblePoints (food): list of points where each point is a tuple (x, y)
        feasiblePoints (power): list of points where each point is a tuple (x, y)
        optimalPoint (pacman): optimal point as a tuple (x, y)
        costVector (shading): cost vector represented as a tuple (c1, c2), where cost is c1*x + c2*x
        """
        super(PacmanPlotLP, self).__init__(zoom, frameTime)

        xmin = 100000
        ymin = 100000
        xmax = -100000
        ymax = -100000

        for point in feasiblePoints:
            if point[0] < xmin:
                xmin = point[0]
            if point[0] > xmax:
                xmax = point[0]
            if point[1] < ymin:
                ymin = point[1]
            if point[1] > ymax:
                ymax = point[1]

        if len(feasiblePoints) == 0:
            for point in infeasiblePoints:
                if point[0] < xmin:
                    xmin = point[0]
                if point[0] > xmax:
                    xmax = point[0]
                if point[1] < ymin:
                    ymin = point[1]
                if point[1] > ymax:
                    ymax = point[1]

        xmin = int(math.floor(xmin)) - 3
        ymin = int(math.floor(ymin)) - 3
        xmax = int(math.ceil(xmax)) + 3
        ymax = int(math.ceil(ymax)) + 3
        width = xmax - xmin + 1
        height = ymax - ymin + 1

        #        p = feasiblePoints[2]
        #        print("p={}".format(p))
        #        print("feasible={}".format(self.pointFeasible(p, constraints)))
        #        g = self.cartesianToLayout(xmin, ymin, xmax, ymax, p)
        #        print("g={}".format(g))
        #        gr = (int(round(g[0])), int(round(g[1])))
        #        p2 = self.layoutToCartesian(xmin, ymin, xmax, ymax, gr)
        #        print("p2={}".format(p2))
        #        print("p2 feasible={}".format(self.pointFeasible(p2, constraints)))

        layoutLists = self.blankLayoutLists(width, height)

        self.addInfeasibleGhosts(layoutLists, constraints, xmin, ymin, xmax,
                                 ymax)

        layoutLists = self.changeBorderGhostsToWall(layoutLists)

        for point in infeasiblePoints:
            self.addCartesianPointToLayout(layoutLists, point, '.', xmin, ymin,
                                           xmax, ymax)

        for point in feasiblePoints:
            self.addCartesianPointToLayout(layoutLists, point, 'o', xmin, ymin,
                                           xmax, ymax)

        if optimalPoint is not None:
            self.addCartesianPointToLayout(layoutLists, optimalPoint, 'P',
                                           xmin, ymin, xmax, ymax)

        if graphicsUtils._canvas is not None:
            graphicsUtils.clear_screen()

        # Initialize GameStateData with blank board with axes
        self.width = width
        self.height = height

        self.zoom = min(30.0 / self.width, 20.0 / self.height)
        self.gridSize = graphicsDisplay.DEFAULT_GRID_SIZE * self.zoom

        maxNumGhosts = 10000
        layout = Layout(layoutLists)
        self.blankGameState = GameStateData()
        self.blankGameState.initialize(layout, maxNumGhosts)
        self.initialize(self.blankGameState)
        title = 'Pacman Plot LP'
        graphicsUtils.changeText(self.infoPane.scoreText, title)
        graphicsUtils.refresh()

        if costVector is not None:
            self.shadeCost(layoutLists, constraints, costVector,
                           feasiblePoints, xmin, ymin, xmax, ymax)
Пример #38
0
class GameState:
  """
  A GameState specifies the full game state, including the food, capsules,
  agent configurations and score changes.

  GameStates are used by the Game object to capture the actual state of the game and
  can be used by agents to reason about the game.

  Much of the information in a GameState is stored in a GameStateData object.  We
  strongly suggest that you access that data via the accessor methods below rather
  than referring to the GameStateData object directly.

  Note that in classic Pacman, Pacman is always agent 0.
  """

  ####################################################
  # Accessor methods: use these to access state data #
  ####################################################

  def updateState(self, actions):
    """
    Returns the successor state after the actions of all active agents.
    """
    # Check that successors exist  
    if self.isWin() or self.isLose(): raise Exception('it is terminal state now.')

    self.data.clear()
	
    for agentIndex in range(len(actions)):
      if self.data._eaten[agentIndex] > 0:
        BombermanRules.applyAction( self, actions[agentIndex], agentIndex )

    self.minusOneFrame()
    for counter,position,power,index in self.data.bombs:
      if counter == self.getFramesUntilEnd():
        self.bombExplode(self.data.bombs,position,power)
        if index >= 0:
          self.getAgentState(index).recoverABomb()
    self.data.bombs = [b for b in self.data.bombs if (b[0] != self.getFramesUntilEnd())]

    self.updateBombScore()	
    self.updateMapScore()
	
    self.data.score = self.data._eaten[0]

  
  def getLegalActions( self, agentIndex=0 ):
    """
    Returns the legal actions for the agent specified.
    """
    if self.isWin() or self.isLose(): return []
    return BombermanRules.getLegalActions( self , agentIndex)

  def generateSuccessor( self, agentIndex, action , force = False):
    """
    Returns the successor state after the specified agent takes the action.
    """
    # Check that successors exist
    if self.isWin() or self.isLose(): raise Exception('Can\'t generate a successor of a terminal state.')

    # Copy current state
    state = GameState(self)

    # Let agent's logic deal with its action's effects on the board

    #state.data._eaten = [False for i in range(state.getNumAgents())]
    if state.data._eaten[agentIndex] > 0:
      BombermanRules.applyAction( state, action, agentIndex )

    if force or ( agentIndex == state.getNumAgents() - 1):
      state.minusOneFrame()
      for counter,position,power,index in state.data.bombs:
        if counter == state.getFramesUntilEnd():
          state.bombExplode(state.data.bombs,position,power)
          state.getAgentState(index).recoverABomb()
      state.data.bombs = [b for b in state.data.bombs if (b[0] != state.getFramesUntilEnd())]

    state.updateBombScore()	
    state.updateMapScore()	
    # Time passes
    state.data.scoreChange += -TIME_PENALTY # Penalty for waiting around

    # Resolve multi-agent effects
    #GhostRules.checkDeath( state, agentIndex )

    # Book keeping
    state.data._agentMoved = agentIndex
    state.data.score += state.data.scoreChange
    return state

  def getAgentPosition( self, agentIndex ):
    return self.data.agentStates[agentIndex].getPosition()
	
  def getAgentState(self, agentIndex):
    return 	self.data.agentStates[agentIndex]
	
  def getNumAgents( self ):
    return len( self.data.agentStates )

  def getScore( self ):
    return self.data.score

  def getMapScore(self,x,y=None):
    if y is None:
      try : x,y = x
      except: raise  'incomprehensible coordinates' 
    return self.data.MapScore[x][y]
	
  def getBombScore(self,x,y=None):
    if y is None:
      try : x,y = x
      except: raise  'incomprehensible coordinates' 
    return self.data.BombScore[x][y]
	  
  def hasWall(self, x, y):
    return self.data.map.isWall((x,y))

  def isLose( self ):
    return (self.getNumAgents() == 1 and self.data._eaten[0] == 0) or (self.data._eaten.count(0) == self.getNumAgents())

  def isWin( self ):
    return ( self.getNumAgents()!=1 and self.data._eaten.count(0) is self.getNumAgents()-1 ) 

  def getFramesUntilEnd(self ):
    return self.data.FramesUntilEnd

  def minusOneFrame( self ):
    self.data.FramesUntilEnd = self.data.FramesUntilEnd - 1
    return self.data.FramesUntilEnd

  def layABomb(self,agentIndex,pos):
    self.data._bombLaid.append(pos)
    self.data.map.add_bomb(pos)
    self.getAgentState(agentIndex).minusABomb()
    self.data.bombs.append( (self.data.FramesUntilEnd - BOMB_DURATION , 
                             pos, self.getAgentState(agentIndex).getBombPower() , agentIndex ) )

	
  def bombExplode(self,bombs, position, power):
    x_int, y_int = position
    if not self.data.map.isBomb(position): return
    self.data._bombExplode.append(position)
    self.data.map.remove_object(position)
    fired = [] 
    for i in range(len(self.data._fire)):
       fired +=  self.data._fire[i]
	
    if not position in fired:
      self.checkDie(position)
      self.data._fire[0].append(position)
      fired.append(position)
    for vec in [ v for dir, v in Actions._directionsAsList if ( not dir in  [ Actions.LAY ,Directions.STOP])]:
      isbreak = False
      i = 0
      dx, dy = vec
      next_y, next_x = y_int,x_int
      while not isbreak and i < power:
          i=i+1
          next_y = int(next_y + dy)
          next_x = int(next_x + dx)
          pos = (next_x,next_y)
          if pos in fired: continue
          if self.data.map.isEmpty(pos):
            self.checkDie(pos)
            self.data._fire[i].append(pos)
            fired.append(pos)
          elif self.data.map.isBlock(pos):
            isbreak = True
            self.data._blockBroken.append(pos)
            res = self.data.map.remove_object(pos)
            self.data._fire[i].append(pos)
            fired.append(pos)
            if res != None:
              self.data._itemDrop.append((next_x,next_y,res))
          elif self.data.map.isWall(pos):
            isbreak = True
          elif self.data.map.isItem(pos):
            self.data._itemEaten.append(pos)
            self.data.map.remove_object(pos)
            self.data._fire[i].append(pos)
            fired.append(pos)
            self.checkDie(pos)
          elif self.data.map.isBomb(pos):
            self.checkDie(pos)
            self.data._fire[i].append(pos)
            fired.append(pos)
            bombSweep = [(idx,bomb) for idx,bomb in enumerate(bombs) if (pos in bomb ) and (bomb[0] < self.data.FramesUntilEnd-int(BOMB_DURATION/10)) ]
            if len(bombSweep) is 1:
              bombs[bombSweep[0][0]] = (self.data.FramesUntilEnd-int(BOMB_DURATION/10),)+bombSweep[0][1][1:]
                
            
  def checkDie(self,position):
    x,y = position
    for index,agent in enumerate(self.data.agentStates):
      if self.data._eaten[index] is 0 : continue
      sx,sy = agent.getPosition()
      sx,sy = round(sx),round(sy)
      if manhattanDistance(position,(sx,sy)) <= 0.5:
        self.data._eaten[index] -= 1 
        agent.configuration = agent.start		

  def updateBombScore(self):
    # The change to the BombScore:
    self.data.BombScore.data = [[0 for y in range(self.data.map.height)] for x in range(self.data.map.width)]
    for counter, pos, power, index in self.data.bombs:
      score = self.calBombScore(counter)
      self.data.BombScore[pos[0]][pos[1]] += score
      isbreak = False
      for vec in [v for dir, v in Actions._directionsAsList if ( not dir in  [ Actions.LAY ,Directions.STOP])]:
        isbreak = False
        i = 0
        dx,dy = vec
        next_x,next_y = pos
        while not isbreak and i < power:
          i += 1
          next_x = int(next_x+dx)
          next_y = int(next_y+dy)
          if self.data.map.isBlock((next_x,next_y)) or self.data.map.isWall((next_x,next_y)):
            isbreak = True
          else :
            self.data.BombScore[next_x][next_y] += score-i/5.0

  def updateMapScore(self):
    self.data.MapScore.data = [[0 for y in range(self.data.map.height)] for x in range(self.data.map.width)]
    for x in range(self.data.map.width):
      for y in range(self.data.map.height):
        if not self.data.map.isBlocked((x,y)) or self.data.map.isBomb((x,y)):
          main = [self.data.map.isBlocked((row,col)) for row,col in [(x+1,y),(x-1,y),(x,y+1),(x,y-1)]]
          second = [self.data.map.isBlocked((row,col)) for row,col in [(x+1,y+1),(x-1,y+1),(x+1,y-1),(x-1,y-1)]]
          self.data.MapScore[x][y] = ( main.count(True)*1 + second.count(True)*0.4 )
          if main.count(True) == 4: self.data.MapScore[x][y] = 100
          if self.data.map.isBomb((x,y)): self.data.MapScore[x][y] += 1
		  
  def calBombScore(self, counter):
    if self.getFramesUntilEnd() - 1 == counter:  # next frame would explode
		return 100
		
    return 3*(BOMB_DURATION - (self.getFramesUntilEnd() - counter))

  def getTotalLives(self, indexes):
    return sum([self.data._eaten[index] for index in indexes])
	
  #############################################
  #             Helper methods:               #
  # You shouldn't need to call these directly #
  #############################################

  def __init__( self, prevState = None):
    """
    Generates a new state by copying information from its predecessor.
    """
    if prevState != None: # Initial state
      self.data = GameStateData(prevState.data)
    else:
      self.data = GameStateData()

  def deepCopy( self ):
    state = GameState( self )
    state.data = self.data.deepCopy()
    return state

  def __eq__( self, other ):
    """
    Allows two states to be compared.
    """
    return self.data == other.data

  def __hash__( self ):
    """
    Allows states to be keys of dictionaries.
    """
    return hash( self.data )

  def __str__( self ):

    return str(self.data)

  def initialize( self, layout, numAgents=1000 , timeout = 3000, life = 5 ):
    """
    Creates an initial game state from a layout array (see layout.py).
    """
    self.data.initialize(layout, numAgents, timeout, life , BOMB_DURATION)
Пример #39
0
class GameState:
    """
    A GameState specifies the full game state, including the food, capsules,
    agent configurations and score changes.

    GameStates are used by the Game object to capture the actual state of the game and
    can be used by agents to reason about the game.

    Much of the information in a GameState is stored in a GameStateData object.  We
    strongly suggest that you access that data via the accessor methods below rather
    than referring to the GameStateData object directly.
    """

    ####################################################
    # Accessor methods: use these to access state data #
    ####################################################

    def getLegalActions(self, agentIndex=0):
        """
        Returns the legal actions for the agent specified.
        """
        return AgentRules.getLegalActions(self, agentIndex)

    def generateSuccessor(self, agentIndex, action):
        """
        Returns the successor state (a GameState object) after the specified agent takes the action.
        """
        # Copy current state
        state = GameState(self)

        # Find appropriate rules for the agent
        AgentRules.applyAction(state, action, agentIndex)
        AgentRules.checkDeath(state, agentIndex)
        AgentRules.decrementTimer(state.data.agentStates[agentIndex])

        # Book keeping
        state.data._agentMoved = agentIndex
        state.data.score += state.data.scoreChange
        state.data.timeleft = self.data.timeleft - 1
        return state

    def getAgentState(self, index):
        return self.data.agentStates[index]

    def getAgentPosition(self, index):
        """
        Returns a location tuple if the agent with the given index is observable;
        if the agent is unobservable, returns None.
        """
        agentState = self.data.agentStates[index]
        ret = agentState.getPosition()
        if ret:
            return tuple(int(x) for x in ret)
        return ret

    def getNumAgents(self):
        return len(self.data.agentStates)

    def getScore(self):
        """
        Returns a number corresponding to the current score.
        """
        return self.data.score

    def getRedFood(self):
        """
        Returns a matrix of food that corresponds to the food on the red team's side.
        For the matrix m, m[x][y]=true if there is food in (x,y) that belongs to
        red (meaning red is protecting it, blue is trying to eat it).
        """
        return halfGrid(self.data.food, red=True)

    def getBlueFood(self):
        """
        Returns a matrix of food that corresponds to the food on the blue team's side.
        For the matrix m, m[x][y]=true if there is food in (x,y) that belongs to
        blue (meaning blue is protecting it, red is trying to eat it).
        """
        return halfGrid(self.data.food, red=False)

    def getRedCapsules(self):
        return halfList(self.data.capsules, self.data.food, red=True)

    def getBlueCapsules(self):
        return halfList(self.data.capsules, self.data.food, red=False)

    def getWalls(self):
        """
        Just like getFood but for walls
        """
        return self.data.layout.walls

    def hasFood(self, x, y):
        """
        Returns true if the location (x,y) has food, regardless of
        whether it's blue team food or red team food.
        """
        return self.data.food[x][y]

    def hasWall(self, x, y):
        """
        Returns true if (x,y) has a wall, false otherwise.
        """
        return self.data.layout.walls[x][y]

    def isOver(self):
        return self.data._win

    def getRedTeamIndices(self):
        """
        Returns a list of agent index numbers for the agents on the red team.
        """
        return self.redTeam[:]

    def getBlueTeamIndices(self):
        """
        Returns a list of the agent index numbers for the agents on the blue team.
        """
        return self.blueTeam[:]

    def isOnRedTeam(self, agentIndex):
        """
        Returns true if the agent with the given agentIndex is on the red team.
        """
        return self.teams[agentIndex]

    def getAgentDistances(self):
        """
        Returns a noisy distance to each agent.
        """
        if 'agentDistances' in dir(self):
            return self.agentDistances
        else:
            return None

    def getDistanceProb(self, trueDistance, noisyDistance):
        "Returns the probability of a noisy distance given the true distance"
        if noisyDistance - trueDistance in SONAR_NOISE_VALUES:
            return 1.0 / SONAR_NOISE_RANGE
        else:
            return 0

    def getInitialAgentPosition(self, agentIndex):
        "Returns the initial position of an agent."
        return self.data.layout.agentPositions[agentIndex][1]

    def getCapsules(self):
        """
        Returns a list of positions (x,y) of the remaining capsules.
        """
        return self.data.capsules

    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__(self, prevState=None):
        """
        Generates a new state by copying information from its predecessor.
        """
        if prevState != None:  # Initial state
            self.data = GameStateData(prevState.data)
            self.blueTeam = prevState.blueTeam
            self.redTeam = prevState.redTeam
            self.data.timeleft = prevState.data.timeleft

            self.teams = prevState.teams
            self.agentDistances = prevState.agentDistances
        else:
            self.data = GameStateData()
            self.agentDistances = []

    def deepCopy(self):
        state = GameState(self)
        state.data = self.data.deepCopy()
        state.data.timeleft = self.data.timeleft

        state.blueTeam = self.blueTeam[:]
        state.redTeam = self.redTeam[:]
        state.teams = self.teams[:]
        state.agentDistances = self.agentDistances[:]
        return state

    def makeObservation(self, index):
        state = self.deepCopy()

        # Adds the sonar signal
        pos = state.getAgentPosition(index)
        n = state.getNumAgents()
        distances = [
            noisyDistance(pos, state.getAgentPosition(i)) for i in range(n)
        ]
        state.agentDistances = distances

        # Remove states of distant opponents
        if index in self.blueTeam:
            team = self.blueTeam
            otherTeam = self.redTeam
        else:
            otherTeam = self.blueTeam
            team = self.redTeam

        for enemy in otherTeam:
            seen = False
            enemyPos = state.getAgentPosition(enemy)
            for teammate in team:
                if util.manhattanDistance(
                        enemyPos,
                        state.getAgentPosition(teammate)) <= SIGHT_RANGE:
                    seen = True
            if not seen:
                state.data.agentStates[enemy].configuration = None
        return state

    def __eq__(self, other):
        """
        Allows two states to be compared.
        """
        if other == None:
            return False
        return self.data == other.data

    def __hash__(self):
        """
        Allows states to be keys of dictionaries.
        """
        return int(hash(self.data))

    def __str__(self):

        return str(self.data)

    def initialize(self, layout, numAgents):
        """
        Creates an initial game state from a layout array (see layout.py).
        """
        self.data.initialize(layout, numAgents)
        positions = [a.configuration for a in self.data.agentStates]
        self.blueTeam = [
            i for i, p in enumerate(positions) if not self.isRed(p)
        ]
        self.redTeam = [i for i, p in enumerate(positions) if self.isRed(p)]
        self.teams = [self.isRed(p) for p in positions]
        # This is usually 60 (always 60 with random maps)
        # However, if layout map is specified otherwise, it could be less
        global TOTAL_FOOD
        TOTAL_FOOD = layout.totalFood

    def isRed(self, configOrPos):
        width = self.data.layout.width
        if type(configOrPos) == type((0, 0)):
            return configOrPos[0] < width / 2
        else:
            return configOrPos.pos[0] < width / 2
Пример #40
0
 def __init__(self, layout, agents, display_class, turn=AgentRole.Mr_X):
     self.gameState = GameState(GameStateData(layout, agents))
     self.turn = turn
     # create a new <type>+Display object
     self.display = display_class(self.gameState.data)
     self.MOD = len(agents)  # number of players
Пример #41
0
class GameState:
    """
    A GameState specifies the full game state, including the food, capsules,
    agent configurations and score changes.

    GameStates are used by the Game object to capture the actual state of the game and
    can be used by agents to reason about the game.

    Much of the information in a GameState is stored in a GameStateData object.  We
    strongly suggest that you access that data via the accessor methods below rather
    than referring to the GameStateData object directly.

    Note that in classic Pacman, Pacman is always agent 0.
    """

    ####################################################
    # Accessor methods: use these to access state data #
    ####################################################

    # static variable keeps track of which states have had getLegalActions called
    explored = set()
    def getAndResetExplored():
        tmp = GameState.explored.copy()
        GameState.explored = set()
        return tmp
    getAndResetExplored = staticmethod(getAndResetExplored)

    def getLegalActions( self, agentIndex=0 ):
        """
        Returns the legal actions for the agent specified.
        """
#        GameState.explored.add(self)
        if self.isWin() or self.isLose(): return []

        if agentIndex == 0:  # Pacman is moving
            return PacmanRules.getLegalActions( self )
        else:
            return GhostRules.getLegalActions( self, agentIndex )

    def generateSuccessor( self, agentIndex, action):
        """
        Returns the successor state after the specified agent takes the action.
        """
        # Check that successors exist
        if self.isWin() or self.isLose(): raise Exception('Can\'t generate a successor of a terminal state.')

        # Copy current state
        state = GameState(self)

        # Let agent's logic deal with its action's effects on the board
        if agentIndex == 0:  # Pacman is moving
            PacmanRules.applyAction( state, action )
        else:                # A ghost is moving
            GhostRules.applyAction( state, action, agentIndex )

        # Time passes
        if agentIndex == 0:
            state.data.scoreChange += -TIME_PENALTY # Penalty for waiting around
        else:
            GhostRules.decrementTimer( state.data.agentStates[agentIndex] )

        # Resolve multi-agent effects
        GhostRules.checkDeath( state, agentIndex )

        # Book keeping
        state.data._agentMoved = agentIndex
        state.data.score += state.data.scoreChange
        GameState.explored.add(self)
        GameState.explored.add(state)
        return state

    def getLegalPacmanActions( self ):
        return self.getLegalActions( 0 )

    def generatePacmanSuccessor( self, action ):
        """
        Generates the successor state after the specified pacman move
        """
        return self.generateSuccessor( 0, action )

    def getPacmanState( self ):
        """
        Returns an AgentState object for pacman (in game.py)

        state.pos gives the current position
        state.direction gives the travel vector
        """
        return self.data.agentStates[0].copy()

    def getPacmanPosition( self ):
        return self.data.agentStates[0].getPosition()

    def getGhostStates( self ):
        return self.data.agentStates[1:]

    def getGhostState( self, agentIndex ):
        if agentIndex == 0 or agentIndex >= self.getNumAgents():
            raise Exception("Invalid index passed to getGhostState")
        return self.data.agentStates[agentIndex]

    def getGhostPosition( self, agentIndex ):
        if agentIndex == 0:
            raise Exception("Pacman's index passed to getGhostPosition")
        return self.data.agentStates[agentIndex].getPosition()

    def getGhostPositions(self):
        return [s.getPosition() for s in self.getGhostStates()]

    def getNumAgents( self ):
        return len( self.data.agentStates )

    def getScore( self ):
        return float(self.data.score)

    def getCapsules(self):
        """
        Returns a list of positions (x,y) of the remaining capsules.
        """
        return self.data.capsules

    def getNumFood( self ):
        count = 0
        for x in self.data.food:
            for e in x:
                if e:
                    count += 1
        return count

    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 call

        currentFood = state.getFood()
        if currentFood[x][y] == True: ...
        """
        return self.data.food

    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 call

        walls = state.getWalls()
        if walls[x][y] == True: ...
        """
        return self.data.layout.walls

    def hasFood(self, x, y):
        return self.data.food[x][y]

    def hasWall(self, x, y):
        return self.data.layout.walls[x][y]

    def isLose( self ):
        return self.data._lose

    def isWin( self ):
        return self.data._win

    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__( self, prevState = None ):
        """
        Generates a new state by copying information from its predecessor.
        """
        if prevState != None: # Initial state
            self.data = GameStateData(prevState.data)
        else:
            self.data = GameStateData()

    def deepCopy( self ):
        state = GameState( self )
        state.data = self.data.deepCopy()
        return state

    def __eq__( self, other ):
        """
        Allows two states to be compared.
        """
        return hasattr(other, 'data') and self.data == other.data

    def __hash__( self ):
        """
        Allows states to be keys of dictionaries.
        """
        return hash( self.data )

    def __str__( self ):

        return str(self.data)

    def initialize( self, layout, numGhostAgents=1000 ):
        """
        Creates an initial game state from a layout array (see layout.py).
        """
        self.data.initialize(layout, numGhostAgents)
Пример #42
0
class GameState:##this is called by initState = GameState() in ClassicGameRules.newGame
    """
    A GameState specifies the full game state, including the food, capsules,
    agent configurations and score changes.

    GameStates are used by the Game object to capture the actual state of the game and
    can be used by agents to reason about the game.

    Much of the information in a GameState is stored in a GameStateData object.  We
    strongly suggest that you access that data via the accessor methods below rather
    than referring to the GameStateData object directly.

    Note that in classic Pacman, Pacman is always agent 0.
    """

    ####################################################
    # Accessor methods: use these to access state data #
    ####################################################

    # static variable keeps track of which states have had getLegalActions called
    explored = set() #REFA01
    def getAndResetExplored(): ##this function passes a copy of the explored GameState object to the tmp variable, resets the same object with an empty set. It then returns the tmp
        tmp = GameState.explored.copy() #[REFA01] This is a copy reference to the explored variable which contains an empty set.
        GameState.explored = set() #This re-equipps the explored variable with an empty set.
        return tmp
    getAndResetExplored = staticmethod(getAndResetExplored)
    """
    So, as we can see from usage of staticmethod, we don't have any access to what the class is- it's basically just a function,
    called syntactically like a method, but without access to the object and it's internals (fields and another methods)
    """

    def getLegalActions( self, agentIndex=0 ):
        """
        Returns the legal actions for the agent specified.
        """
        GameState.explored.add(self)
        if self.isWin() or self.isLose(): return []

        if agentIndex == 0:  # Pacman is moving
            return PacmanRules.getLegalActions( self )
        else:
            return GhostRules.getLegalActions( self, agentIndex )

    def generateSuccessor( self, agentIndex, action):
        """
        Returns the successor state after the specified agent takes the action.
        """
        # Check that successors exist
        if self.isWin() or self.isLose(): raise Exception('Can\'t generate a successor of a terminal state.')

        # Copy current state
        state = GameState(self)

        # Let agent's logic deal with its action's effects on the board
        if agentIndex == 0:  # Pacman is moving
            state.data._eaten = [False for i in range(state.getNumAgents())]
            PacmanRules.applyAction( state, action )
        else:                # A ghost is moving
            GhostRules.applyAction( state, action, agentIndex )

        # Time passes
        if agentIndex == 0:
            state.data.scoreChange += -TIME_PENALTY # Penalty for waiting around
        else:
            GhostRules.decrementTimer( state.data.agentStates[agentIndex] )

        # Resolve multi-agent effects
        GhostRules.checkDeath( state, agentIndex )

        # Book keeping
        state.data._agentMoved = agentIndex
        state.data.score += state.data.scoreChange
        return state

    def getLegalPacmanActions( self ):
        return self.getLegalActions( 0 )

    def generatePacmanSuccessor( self, action ):
        """
        Generates the successor state after the specified pacman move
        """
        return self.generateSuccessor( 0, action )

    def getPacmanState( self ):
        """
        Returns an AgentState object for pacman (in game.py)

        state.pos gives the current position
        state.direction gives the travel vector
        """
        return self.data.agentStates[0].copy()

    def getPacmanPosition( self ):
        return self.data.agentStates[0].getPosition()

    def getGhostStates( self ):
        return self.data.agentStates[1:]

    def getGhostState( self, agentIndex ):
        if agentIndex == 0 or agentIndex >= self.getNumAgents():
            raise Exception("Invalid index passed to getGhostState")
        return self.data.agentStates[agentIndex]

    def getGhostPosition( self, agentIndex ):
        if agentIndex == 0:
            raise Exception("Pacman's index passed to getGhostPosition")
        return self.data.agentStates[agentIndex].getPosition()

    def getGhostPositions(self):
        return [s.getPosition() for s in self.getGhostStates()]

    def getNumAgents( self ):
        return len( self.data.agentStates )

    def getScore( self ):
        return self.data.score

    def getCapsules(self):
        """
        Returns a list of positions (x,y) of the remaining capsules.
        """
        return self.data.capsules

    def getNumFood( self ):
        return self.data.food.count()

    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 call

        currentFood = state.getFood()
        if currentFood[x][y] == True: ...
        """
        return self.data.food

    def getWalls(self):
        """
        Returns a Grid of boolean wall indicator variables.

        Grids can be accessed via list notation, so to check
        if there is food at (x,y), just call

        walls = state.getWalls()
        if walls[x][y] == True: ...
        """
        return self.data.layout.walls

    def hasFood(self, x, y):
        return self.data.food[x][y]

    def hasWall(self, x, y):
        return self.data.layout.walls[x][y]

    def isLose( self ):
        return self.data._lose

    def isWin( self ):
        return self.data._win

    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__( self, prevState = None ): ###PLEASE NOTE THIS THAT THE __init__ method is here and this is where GameState() starts
        """
        Generates a new state by copying information from its predecessor.
        """
        if prevState != None: # Initial state
            self.data = GameStateData(prevState.data) ##This statement imports the GameStateData object from the GameStateData class in game.py. This object contains a data packet documenting the state of the game.

        else:
            self.data = GameStateData()
        """
        self._foodEaten = None
        self._capsuleEaten = None
        self._agentMoved = None
        self._lose = False
        self._win = False
        self.scoreChange = 0
        """

    def deepCopy( self ):
        state = GameState( self )
        state.data = self.data.deepCopy()
        return state

    def __eq__( self, other ):
        """
        Allows two states to be compared.
        """
        return self.data == other.data

    def __hash__( self ):
        """
        Allows states to be keys of dictionaries.
        """
        return hash( self.data )

    def __str__( self ):

        return str(self.data)

    def initialize( self, layout, numGhostAgents=1000 ):
        """
        Creates an initial game state from a layout array (see layout.py).

        This is based on:
        self.width = len(layoutText[0])## measures the width of the first element in the layoutText list, which was passed in by the 'tryToLoad' function by initiating the Layout object in the function call below. Open one of the layout files in the 'layouts' folder to understand how the layout works.
        self.height= len(layoutText)   ## measures the hight of the layout by counting the length of the array [line1,line2,line3,line4]
        self.walls = Grid(self.width, self.height, False) ##self.walls contains an object that contains the Grid's width, height and a 2-dimenstional array called self.data that looks something like this:[[False, False, False,False],[False, False, False,False],...]
        self.food = Grid(self.width, self.height, False)  ## same as the line before
        self.capsules = []
        self.agentPositions = []
        self.numGhosts = 0
        self.processLayoutText(layoutText) ## This function takes the symbols contained in the layout files and turns them into coordinates which are then appended or assigned to the several variables that have been initialised in the code above. This happens according to the (x,y) convention used in the 2-dimensonal array that was defined in the Games class.
        self.layoutText = layoutText

        --> The initialize function then calls the self.data object's initialize function. "self.data" contains the GameStateData objec. GameStateData contains an initialize function itself which creates an initial game state from a layout array (see layout.py) (see above).
        
        self.food = layout.food.copy()
        self.capsules = layout.capsules[:]
        self.layout = layout
        self.score = 0
        self.scoreChange = 0

        self.agentStates = []
        numGhosts = 0

        for isPacman, pos in layout.agentPositions:
            if not isPacman:
                if numGhosts == numGhostAgents: continue # Max ghosts reached already
                else: numGhosts += 1
            self.agentStates.append( AgentState( Configuration( pos, Directions.STOP), isPacman) )
        self._eaten = [False for a in self.agentStates]
        """
        self.data.initialize(layout, numGhostAgents) ##self.data is defined in the Grid() class of game.py REF112.It creates an initial game state from a layout array (see layout.py).
Пример #43
0
class GameState:
    """
    A GameState specifies the full game state, including the food, capsules,
    agent configurations and score changes.

    GameStates are used by the Game object to capture the actual state of the game and
    can be used by agents to reason about the game.

    Much of the information in a GameState is stored in a GameStateData object.  We
    strongly suggest that you access that data via the accessor methods below rather
    than referring to the GameStateData object directly.

    Note that in classic Pacman, Pacman is always agent 0.
    """

    ####################################################
    # Accessor methods: use these to access state data #
    ####################################################

    # static variable keeps track of which states have had getLegalActions called
    explored = set()

    def getAndResetExplored():
        tmp = GameState.explored.copy()
        GameState.explored = set()
        return tmp

    getAndResetExplored = staticmethod(getAndResetExplored)

    def getLegalActions(self, agentIndex=0):
        """
        Returns the legal actions for the agent specified.
        """
        #        GameState.explored.add(self)
        if self.isWin() or self.isLose(): return []

        if agentIndex == 0:  # Pacman is moving
            return PacmanRules.getLegalActions(self)
        else:
            return GhostRules.getLegalActions(self, agentIndex)

    def generateSuccessor(self, action):
        """
        Returns the successor state after the specified agent takes the action.
        """
        # Check that successors exist
        if self.isWin() or self.isLose() or self.eventQueue.isEmpty():
            raise Exception('Can\'t generate a successor of a terminal state.')

        time, event = self.eventQueue.peek()
        assert event.isAgentMove(
        ), 'Can only generate successors of a state where an agent is about to move'
        state = self.makeAgentMove(action)
        state.resolveEventsUntilAgentEvent()

        # Book keeping
        GameState.explored.add(self.data)
        GameState.explored.add(state.data)
        return state

    def makeAgentMove(self, action):
        # Copy current state
        state = GameState(self)

        time, event = state.eventQueue.pop()
        agentIndex = event.getAgentIndex()
        agentState = state.data.agentStates[agentIndex]
        state.data.time = time
        delay = agentState.powers.timestepsBetweenMoves
        state.registerEventWithDelay(event, delay)

        # Let agent's logic deal with its action's effects on the board
        if agentIndex == 0:  # Pacman is moving
            state.data._eaten = [False for i in range(state.getNumAgents())]
            PacmanRules.applyAction(state, action)
            state.data.scoreChange -= TIME_PENALTY  # Penalty for waiting around
        else:  # A ghost is moving
            GhostRules.applyAction(state, action, agentIndex)
            GhostRules.decrementTimer(agentState)

        # Resolve multi-agent effects
        GhostRules.checkDeath(state, agentIndex)
        if action == Directions.LASER:
            GhostRules.checkLaserShot(state, agentIndex)
        if action == Directions.BLAST:
            GhostRules.checkBlast(state, agentIndex)

        # Book keeping
        state.data._agentMoved = agentIndex
        # Note:  It is important that the following value accurately
        # reflects when Pacman will make the next move, even if the
        # speed changes (such as a speed-up power pellet).  Otherwise
        # the graphics will do weird things.
        state.data._timeTillAgentMovesAgain = delay
        state.data._action = action
        state.data.score += state.data.scoreChange

        return state

    def runEvent(self):
        # Check that successors exist
        if self.eventQueue.isEmpty():
            raise Exception('Can\'t run an event of a terminal state.')

        time, event = self.eventQueue.pop()
        assert not event.isAgentMove(), 'Can\'t run an AgentMoveEvent'
        self.data.time = time
        event.trigger(self)
        return event

    def getNextEvent(self):
        _, event = self.eventQueue.peek()
        return event

    def getLegalPacmanActions(self):
        return self.getLegalActions(0)

    def getPacmanState(self):
        """
        Returns an AgentState object for pacman (in game.py)

        state.pos gives the current position
        state.direction gives the travel vector
        """
        return self.data.agentStates[0].copy()

    def getPacmanPosition(self):
        return self.data.agentStates[0].getPosition()

    def getPacmanDirection(self):
        return self.data.agentStates[0].getDirection()

    def getGhostStates(self):
        return self.data.agentStates[1:]

    def getGhostState(self, agentIndex):
        if agentIndex == 0 or agentIndex >= self.getNumAgents():
            raise Exception("Invalid index passed to getGhostState")
        return self.data.agentStates[agentIndex]

    def getGhostPosition(self, agentIndex):
        if agentIndex == 0:
            raise Exception("Pacman's index passed to getGhostPosition")
        return self.data.agentStates[agentIndex].getPosition()

    def getGhostPositions(self):
        return [s.getPosition() for s in self.getGhostStates()]

    def getNextAgentIndex(self):
        for time, event in self.eventQueue.getSortedTimesAndEvents():
            if event.isAgentMove():
                return event.getAgentIndex()
        assert False, "No more moves can be made"

    def getAgentMoveTime(self, agentIndex):
        for time, event in self.eventQueue.getSortedTimesAndEvents():
            if event.isAgentMove():
                if event.getAgentIndex() == agentIndex:
                    return time
        assert False, "No more moves can be made by agent " + str(agentIndex)

    def getNumAgents(self):
        return len(self.data.agentStates)

    def getScore(self):
        return float(self.data.score)

    def getCapsules(self):
        """
        Returns a list of positions (x,y) of the remaining capsules.
        """
        return self.data.capsules

    def getNumFood(self):
        return self.data.food.count()

    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 call

        currentFood = state.getFood()
        if currentFood[x][y] == True: ...
        """
        return self.data.food

    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 call

        walls = state.getWalls()
        if walls[x][y] == True: ...
        """
        return self.data.walls

    def hasFood(self, x, y):
        return self.data.food[x][y]

    def hasWall(self, x, y):
        return self.data.walls[x][y]

    def isLose(self):
        return self.data._lose

    def isWin(self):
        return self.data._win

    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__(self, prevState=None):
        """
        Generates a new state by copying information from its predecessor.
        """
        if prevState != None:  # Initial state
            self.data = GameStateData(prevState.data)
            self.eventQueue = prevState.eventQueue.deepCopy()
        else:
            self.data = GameStateData()
            self.eventQueue = EventQueue()

    def resolveEventsUntilAgentEvent(self):
        # Resolve any events until the next agent event
        while not self.eventQueue.isEmpty():
            time, event = self.eventQueue.peek()
            if event.isAgentMove():
                return
            else:
                self.runEvent()

    def registerEventWithDelay(self, event, delay):
        self.eventQueue.registerEventAtTime(event, self.data.time + delay)

    def deepCopy(self):
        state = GameState(self)
        state.data = self.data.deepCopy()
        # Event queue has already been copied in the constructor
        return state

    def __eq__(self, other):
        """
        Allows two states to be compared.
        """
        return hasattr(other, 'data') and self.data == other.data \
            and hasattr(other, 'eventQueue') and self.eventQueue == other.eventQueue \

    def __hash__(self):
        """
        Allows states to be keys of dictionaries.
        """
        return hash((self.data, self.eventQueue))

    def __str__(self):

        return str(self.data)

    def initialize(self,
                   layout,
                   pacmanPowers,
                   ghostPowers,
                   numGhostAgents=1000):
        """
        Creates an initial game state from a layout array (see layout.py).
        """
        self.data.initialize(layout, pacmanPowers, ghostPowers, numGhostAgents)
        numAgents = self.getNumAgents()
        for i in range(numAgents):
            self.registerEventWithDelay(AgentMoveEvent(i), i)
        self.registerEventWithDelay(WallTimerEvent(), 1)
Пример #44
0
class GameState:
    """
    A GameState specifies the full game state, including the food, capsules,
    agent configurations and score changes.

    GameStates are used by the Game object to capture the actual state of the game and
    can be used by agents to reason about the game.

    Much of the information in a GameState is stored in a GameStateData object.

    Note that in classic Pacman, Pacman is always agent 0.
    
    In SLAM inference, you will not have access to any GameState objects.
    """

    ####################################################
    # Accessor methods: use these to access state data #
    ####################################################

    def getLegalActions( self, agentIndex=0 ):
        """
        Returns the legal actions for the agent specified.
        """
        if self.isWin() or self.isLose(): return []

        if agentIndex == 0:  # Pacman is moving
            return PacmanRules.getLegalActions( self )
        else:
            return GhostRules.getLegalActions( self, agentIndex )

    def generateSuccessor( self, agentIndex, action):
        """
        Returns the successor state after the specified agent takes the action.
        """
        # Check that successors exist
        if self.isWin() or self.isLose(): raise Exception('Can\'t generate a successor of a terminal state.')

        # Copy current state
        state = GameState(self)
        # Let agent's logic deal with its action's effects on the board
        if agentIndex == 0:  # Pacman is moving
            state.data._eaten = [False for i in range(state.getNumAgents())]
            PacmanRules.applyAction( state, action )
        else:                # A ghost is moving
            GhostRules.applyAction( state, action, agentIndex )

        # Time passes
        if agentIndex == 0:
            state.data.scoreChange += -TIME_PENALTY # Penalty for waiting around
        else:
            GhostRules.decrementTimer( state.data.agentStates[agentIndex] )

        # Resolve multi-agent effects
        GhostRules.checkDeath( state, agentIndex )

        # Book keeping
        state.data._agentMoved = agentIndex
        state.data.score += state.data.scoreChange
        p = state.getPacmanPosition()
        state.data.ghostDistances = [getNoisyDistance(p, state.getGhostPosition(i)) for i in range(1,state.getNumAgents())]
        if agentIndex == self.getNumAgents() - 1:
            state.numMoves += 1
        return state

    def getLegalPacmanActions( self ):
        return self.getLegalActions( 0 )

    def generatePacmanSuccessor( self, action ):
        """
        Generates the successor state after the specified pacman move
        """
        return self.generateSuccessor( 0, action )

    def getPacmanState( self ):
        """
        Returns an AgentState object for pacman (in game.py)

        state.pos gives the current position
        state.direction gives the travel vector
        """
        return self.data.agentStates[0].copy()

    def getPacmanPosition( self ):
        return self.data.agentStates[0].getPosition()

    def getNumAgents( self ):
        return len( self.data.agentStates )

    def getScore( self ):
        return self.data.score

    def getCapsules(self):
        """
        Returns a list of positions (x,y) of the remaining capsules.
        """
        return self.data.capsules

    def getNumFood( self ):
        return self.data.food.count()

    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 call

        currentFood = state.getFood()
        if currentFood[x][y] == True: ...
        """
        return self.data.food

    def getWalls(self):
        """
        Returns a Grid of boolean wall indicator variables.

        Grids can be accessed via list notation, so to check
        if there is food at (x,y), just call

        walls = state.getWalls()
        if walls[x][y] == True: ...
        """
        return self.data.layout.walls
    
    def getLegalPositions(self):
        """
        Returns all positions that need to be considered for mapping
        (i.e., both walls and walkable positions) 
        """
        l = [p for p in self.getWalls().asList() + self.getWalls().asList(False)]
        return l

    def hasFood(self, x, y):
        return self.data.food[x][y]

    def hasWall(self, x, y):
        return self.data.layout.walls[x][y]

    def isLose( self ):
        """
        Not used by default for SLAM.
        """
        return self.maxMoves > 0 and self.numMoves >= self.maxMoves

    def isWin( self ):
        """
        Not used for SLAM.
        """
        return False
    
    ##############################
    # Additions for Slam Pacman  #
    ##############################
    
    def getNoisyRangeMeasurements(self):
        """
        Return a noisy measurement in each of the four
        directions as a tuple (N, E, S, W).
        """
        x, y = self.getPacmanPosition()
        currentX = x
        currentY = y
        while not self.hasWall(currentX, currentY):
            currentY += 1
        N = getNoisyDistance((x,y), (currentX, currentY))
        currentX = x
        currentY = y
        while not self.hasWall(currentX, currentY):
            currentX += 1
        E = getNoisyDistance((x,y), (currentX, currentY))
        currentX = x
        currentY = y
        while not self.hasWall(currentX, currentY):
            currentY -= 1
        S = getNoisyDistance((x,y), (currentX, currentY))
        currentX = x
        currentY = y
        while not self.hasWall(currentX, currentY):
            currentX -= 1
        W = getNoisyDistance((x,y), (currentX, currentY)) 
        return (N, E, S, W)

    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__( self, prevState = None ):
        """
        Generates a new state by copying information from its predecessor.
        """
        if prevState != None:
            self.data = GameStateData(prevState.data)
            self.livingGhosts = prevState.livingGhosts[:]
            self.numMoves = prevState.numMoves;
            self.maxMoves = prevState.maxMoves;
        else: # Initial state
            self.data = GameStateData()
            self.numMoves = 0;
            self.maxMoves = -1;
        self.data.ghostDistances = []

    def deepCopy( self ):
        state = GameState( self )
        state.data = self.data.deepCopy()
        state.data.ghostDistances = self.data.ghostDistances
        return state

    def __eq__( self, other ):
        """
        Allows two states to be compared.
        """
        return self.data == other.data

    def __hash__( self ):
        """
        Allows states to be keys of dictionaries.
        """
        return hash( str( self ) )

    def __str__( self ):

        return str(self.data)

    def initialize( self, layout, numGhostAgents=1000 ):
        """
        Creates an initial game state from a layout array (see layout.py).
        """
        self.data.initialize(layout, numGhostAgents)
        self.livingGhosts = [False] + [True for i in range(numGhostAgents)]
        self.data.ghostDistances = [getNoisyDistance(self.getPacmanPosition(), self.getGhostPosition(i)) for i in range(1, self.getNumAgents())]

    def getGhostPosition( self, agentIndex ):
        if agentIndex == 0:
            raise "Pacman's index passed to getGhostPosition"
        return self.data.agentStates[agentIndex].getPosition()

    def getGhostState( self, agentIndex ):
        if agentIndex == 0:
            raise "Pacman's index passed to getGhostPosition"
        return self.data.agentStates[agentIndex]
Пример #45
0
class GameState:
  """
  A GameState specifies the full game state, including the food, capsules, 
  agent configurations and score changes.
  
  GameStates are used by the Game object to capture the actual state of the game and
  can be used by agents to reason about the game.
  
  Much of the information in a GameState is stored in a GameStateData object.  We 
  strongly suggest that you access that data via the accessor methods below rather
  than referring to the GameStateData object directly.
  
  Note that in classic Pacman, Pacman is always agent 0.  
  """
  
  ####################################################
  # Accessor methods: use these to access state data #
  ####################################################
  
  def getLegalActions( self, agentIndex=0 ):
    """
    Returns the legal actions for the agent specified.
    """
    if self.isWin() or self.isLose(): return []
    
    if agentIndex == 0:  # Pacman is moving
      return PacmanRules.getLegalActions( self )
    else:
      return GhostRules.getLegalActions( self, agentIndex )
    
  def generateSuccessor( self, agentIndex, action):
    """
    Returns the successor state after the specified agent takes the action.
    """
    # Check that successors exist
    if self.isWin() or self.isLose(): raise Exception('Can\'t generate a successor of a terminal state.')
    
    # Copy current state
    state = GameState(self)

    # Let agent's logic deal with its action's effects on the board
    if agentIndex == 0:  # Pacman is moving
      state.data._eaten = [False for i in range(state.getNumAgents())]
      PacmanRules.applyAction( state, action )
    else:                # A ghost is moving
      GhostRules.applyAction( state, action, agentIndex )
      
    # Time passes
    if agentIndex == 0:
      state.data.scoreChange += -TIME_PENALTY # Penalty for waiting around
    else:
      GhostRules.decrementTimer( state.data.agentStates[agentIndex] )
      
    # Resolve multi-agent effects
    GhostRules.checkDeath( state, agentIndex )

    # Book keeping
    state.data._agentMoved = agentIndex
    state.data.score += state.data.scoreChange
    return state
  
  def getLegalPacmanActions( self ):
    return self.getLegalActions( 0 )
  
  def generatePacmanSuccessor( self, action ):
    """
    Generates the successor state after the specified pacman move
    """
    return self.generateSuccessor( 0, action )
  
  def getPacmanState( self ):
    """
    Returns an AgentState object for pacman (in game.py)
    
    state.pos gives the current position
    state.direction gives the travel vector
    """
    return self.data.agentStates[0].copy()
  
  def getPacmanPosition( self ):
    return self.data.agentStates[0].getPosition()
  
  def getGhostStates( self ):
    return self.data.agentStates[1:]

  def getGhostState( self, agentIndex ):
    if agentIndex == 0 or agentIndex >= self.getNumAgents():
      raise "Invalid index passed to getGhostState"
    return self.data.agentStates[agentIndex]
  
  def getGhostPosition( self, agentIndex ):
    if agentIndex == 0:
      raise "Pacman's index passed to getGhostPosition"
    return self.data.agentStates[agentIndex].getPosition()
  
  def getNumAgents( self ):
    return len( self.data.agentStates )
  
  def getScore( self ):
    return self.data.score
  
  def getCapsules(self):
    """
    Returns a list of positions (x,y) of the remaining capsules.
    """
    return self.data.capsules
  
  def getNumFood( self ):
    return self.data.food.count()
  
  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 call
    
    currentFood = state.getFood()
    if currentFood[x][y] == True: ...
    """
    return self.data.food
  
  def getWalls(self):
    """
    Returns a Grid of boolean wall indicator variables.
    
    Grids can be accessed via list notation, so to check
    if there is food at (x,y), just call
    
    walls = state.getWalls()
    if walls[x][y] == True: ...
    """
    return self.data.layout.walls

  def hasFood(self, x, y):
    return self.data.food[x][y]
  
  def hasWall(self, x, y):
    return self.data.layout.walls[x][y]

  def isLose( self ):
    return self.data._lose
  
  def isWin( self ):
    return self.data._win
  
  #############################################
  #             Helper methods:               #          
  # You shouldn't need to call these directly #
  #############################################
  
  def __init__( self, prevState = None ):
    """ 
    Generates a new state by copying information from its predecessor.
    """
    if prevState != None: # Initial state
      self.data = GameStateData(prevState.data)
    else:
      self.data = GameStateData()
    
  def deepCopy( self ):
    state = GameState( self )
    state.data = self.data.deepCopy()
    return state
    
  def __eq__( self, other ):
    """
    Allows two states to be compared.
    """
    return self.data == other.data
                                                      
  def __hash__( self ):
    """
    Allows states to be keys of dictionaries.
    """
    return hash( str( self ) )

  def __str__( self ):
    
    return str(self.data)
      
  def initialize( self, layout, numGhostAgents=1000 ):
    """
    Creates an initial game state from a layout array (see layout.py).
    """
    self.data.initialize(layout, numGhostAgents)
class GameState:
    """
    A GameState specifies the full game state, including the food, capsules,
    agent configurations and score changes.

    GameStates are used by the Game object to capture the actual state of the game and
    can be used by agents to reason about the game.

    Much of the information in a GameState is stored in a GameStateData object.

    Note that in classic Pacman, Pacman is always agent 0.
    
    In SLAM inference, you will not have access to any GameState objects.
    """

    ####################################################
    # Accessor methods: use these to access state data #
    ####################################################

    def getLegalActions(self, agentIndex=0):
        """
        Returns the legal actions for the agent specified.
        """
        if self.isWin() or self.isLose(): return []

        if agentIndex == 0:  # Pacman is moving
            return PacmanRules.getLegalActions(self)
        else:
            return GhostRules.getLegalActions(self, agentIndex)

    def generateSuccessor(self, agentIndex, action):
        """
        Returns the successor state after the specified agent takes the action.
        """
        # Check that successors exist
        if self.isWin() or self.isLose():
            raise Exception('Can\'t generate a successor of a terminal state.')

        # Copy current state
        state = GameState(self)
        # Let agent's logic deal with its action's effects on the board
        if agentIndex == 0:  # Pacman is moving
            state.data._eaten = [False for i in range(state.getNumAgents())]
            PacmanRules.applyAction(state, action)
        else:  # A ghost is moving
            GhostRules.applyAction(state, action, agentIndex)

        # Time passes
        if agentIndex == 0:
            state.data.scoreChange += -TIME_PENALTY  # Penalty for waiting around
        else:
            GhostRules.decrementTimer(state.data.agentStates[agentIndex])

        # Resolve multi-agent effects
        GhostRules.checkDeath(state, agentIndex)

        # Book keeping
        state.data._agentMoved = agentIndex
        state.data.score += state.data.scoreChange
        p = state.getPacmanPosition()
        state.data.ghostDistances = [
            getNoisyDistance(p, state.getGhostPosition(i))
            for i in range(1, state.getNumAgents())
        ]
        if agentIndex == self.getNumAgents() - 1:
            state.numMoves += 1
        return state

    def getLegalPacmanActions(self):
        return self.getLegalActions(0)

    def generatePacmanSuccessor(self, action):
        """
        Generates the successor state after the specified pacman move
        """
        return self.generateSuccessor(0, action)

    def getPacmanState(self):
        """
        Returns an AgentState object for pacman (in game.py)

        state.pos gives the current position
        state.direction gives the travel vector
        """
        return self.data.agentStates[0].copy()

    def getPacmanPosition(self):
        return self.data.agentStates[0].getPosition()

    def getNumAgents(self):
        return len(self.data.agentStates)

    def getScore(self):
        return self.data.score

    def getCapsules(self):
        """
        Returns a list of positions (x,y) of the remaining capsules.
        """
        return self.data.capsules

    def getNumFood(self):
        return self.data.food.count()

    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 call

        currentFood = state.getFood()
        if currentFood[x][y] == True: ...
        """
        return self.data.food

    def getWalls(self):
        """
        Returns a Grid of boolean wall indicator variables.

        Grids can be accessed via list notation, so to check
        if there is food at (x,y), just call

        walls = state.getWalls()
        if walls[x][y] == True: ...
        """
        return self.data.layout.walls

    def getLegalPositions(self):
        """
        Returns all positions that need to be considered for mapping
        (i.e., both walls and walkable positions) 
        """
        l = [
            p for p in self.getWalls().asList() + self.getWalls().asList(False)
        ]
        return l

    def hasFood(self, x, y):
        return self.data.food[x][y]

    def hasWall(self, x, y):
        return self.data.layout.walls[x][y]

    def isLose(self):
        """
        Not used by default for SLAM.
        """
        return self.maxMoves > 0 and self.numMoves >= self.maxMoves

    def isWin(self):
        """
        Not used for SLAM.
        """
        return False

    ##############################
    # Additions for Slam Pacman  #
    ##############################

    def getNoisyRangeMeasurements(self):
        """
        Return a noisy measurement in each of the four
        directions as a tuple (N, E, S, W).
        """
        x, y = self.getPacmanPosition()
        currentX = x
        currentY = y
        while not self.hasWall(currentX, currentY):
            currentY += 1
        N = getNoisyDistance((x, y), (currentX, currentY))
        currentX = x
        currentY = y
        while not self.hasWall(currentX, currentY):
            currentX += 1
        E = getNoisyDistance((x, y), (currentX, currentY))
        currentX = x
        currentY = y
        while not self.hasWall(currentX, currentY):
            currentY -= 1
        S = getNoisyDistance((x, y), (currentX, currentY))
        currentX = x
        currentY = y
        while not self.hasWall(currentX, currentY):
            currentX -= 1
        W = getNoisyDistance((x, y), (currentX, currentY))
        return (N, E, S, W)

    #############################################
    #             Helper methods:               #
    # You shouldn't need to call these directly #
    #############################################

    def __init__(self, prevState=None):
        """
        Generates a new state by copying information from its predecessor.
        """
        if prevState != None:
            self.data = GameStateData(prevState.data)
            self.livingGhosts = prevState.livingGhosts[:]
            self.numMoves = prevState.numMoves
            self.maxMoves = prevState.maxMoves
        else:  # Initial state
            self.data = GameStateData()
            self.numMoves = 0
            self.maxMoves = -1
        self.data.ghostDistances = []

    def deepCopy(self):
        state = GameState(self)
        state.data = self.data.deepCopy()
        state.data.ghostDistances = self.data.ghostDistances
        return state

    def __eq__(self, other):
        """
        Allows two states to be compared.
        """
        return self.data == other.data

    def __hash__(self):
        """
        Allows states to be keys of dictionaries.
        """
        return hash(str(self))

    def __str__(self):

        return str(self.data)

    def initialize(self, layout, numGhostAgents=1000):
        """
        Creates an initial game state from a layout array (see layout.py).
        """
        self.data.initialize(layout, numGhostAgents)
        self.livingGhosts = [False] + [True for i in range(numGhostAgents)]
        self.data.ghostDistances = [
            getNoisyDistance(self.getPacmanPosition(),
                             self.getGhostPosition(i))
            for i in range(1, self.getNumAgents())
        ]

    def getGhostPosition(self, agentIndex):
        if agentIndex == 0:
            raise "Pacman's index passed to getGhostPosition"
        return self.data.agentStates[agentIndex].getPosition()

    def getGhostState(self, agentIndex):
        if agentIndex == 0:
            raise "Pacman's index passed to getGhostPosition"
        return self.data.agentStates[agentIndex]