Exemplo n.º 1
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()
Exemplo n.º 2
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.data.timeleft = prevState.data.timeleft

            self.teams = prevState.teams
            self.agentDistances = prevState.agentDistances
        else:
            self.data = GameStateData()
            self.agentDistances = []
Exemplo n.º 3
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: int = 0) -> List[str]:
        """
    Returns the legal actions for the agent specified.
    """
        return AgentRules.getLegalActions(self, agentIndex)

    def generateSuccessor(self, agentIndex: int, action: str) -> 'GameState':
        """
    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])
        AgentRules.incrementTimer(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: int) -> AgentState:
        return self.data.agentStates[index]

    def getAgentPosition(self, index: int) -> Tuple[int, int]:
        """
    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) -> int:
        return len(self.data.agentStates)

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

    def getRedFood(self) -> Grid:
        """
    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) -> Grid:
        """
    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) -> Grid:
        return halfList(self.data.capsules, self.data.food, red=True)

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

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

    def hasFood(self, x: int, y: int) -> bool:
        """
    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: int, y: int) -> bool:
        """
    Returns true if (x,y) has a wall, false otherwise.
    """
        return self.data.layout.walls[x][y]

    def isOver(self) -> bool:
        return self.data._win

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

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

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

    def getAgentDistances(self) -> List[int]:
        """
    Returns a noisy distance to each agent.
    """
        if 'agentDistances' in dir(self):
            return self.agentDistances
        else:
            return None

    def getDistanceProb(self, trueDistance: int, noisyDistance: int) -> float:
        "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: int):
        "Returns the initial position of an agent."
        return self.data.layout.agentPositions[agentIndex][1]

    def getCapsules(self) -> List[Tuple[int, int]]:
        """
    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: int) -> object:
        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)
            pos = state.data.agentStates[enemy].configuration.pos
            state.data.agentStates[enemy].configuration.pos = noisyPos(
                pos, self.data.layout)
        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: Layout, numAgents: int) -> None:
        """
    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) -> bool:
        width = self.data.layout.width
        if type(configOrPos) == type((0, 0)):
            return configOrPos[0] < width / 2
        else:
            return configOrPos.pos[0] < width / 2
Exemplo n.º 4
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

    #############################################
    #             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)