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 tester(buffer_size, rps, num_packets=100, num_tests=1000): # we are testing in milliseconds # or milli unit time, as it can be scaled naturally. lam = rps / 1000 # beta is average time interval between two arrival events. (measured compared to processing speed) beta = 1 / lam # just using Rayleigh distribution for processing time of requests. # Can play around with other distributions such as Maxwell-Boltzmann. arrival_times = np.random.exponential(beta, (num_tests, num_packets)) process_times = np.random.rayleigh(1, (num_tests, num_packets)) buffer = Buffer(buffer_size) dropped = np.zeros(num_tests) for i in range(num_tests): arrival_time = 0 Q = EventQueue() for j in range(num_packets): arrival_time += arrival_times[i, j] process_time = process_times[i, j] Q.insert(arrival(arrival_time, process_time)) while Q.notEmpty(): e = Q.next() e.action(Q, buffer) dropped[i] = buffer.num_dropped() buffer.reset() # restarting buffer for next test. Q.reset() # restarting queue for next test. return dropped
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()
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)
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)