import random from event import TickEvent, SimulationStartedEvent, EnvironmentBuiltEvent, AgentPlacedEvent, AgentMoveRequest, AgentMovedEvent (DIRECTION_UP, DIRECTION_DOWN, DIRECTION_LEFT, DIRECTION_RIGHT, DIRECTION_UPLEFT, DIRECTION_UPRIGHT, DIRECTION_DOWNLEFT, DIRECTION_DOWNRIGHT) = range(8) def reverse_dir(dir): return {DIRECTION_UP: DIRECTION_DOWN, DIRECTION_DOWN: DIRECTION_UP, DIRECTION_LEFT: DIRECTION_RIGHT, DIRECTION_RIGHT: DIRECTION_LEFT, DIRECTION_UPLEFT: DIRECTION_DOWNRIGHT, DIRECTION_UPRIGHT: DIRECTION_DOWNLEFT, DIRECTION_DOWNLEFT: DIRECTION_UPRIGHT, DIRECTION_DOWNRIGHT: DIRECTION_UPLEFT}[dir] class Sector: def __init__(self, disp, i, j): self.pos = (i, j) self.neighbors = range(8) for i in range(8): self.neighbors[i] = None self.occupant = None def __repr__(self): return str(self.pos) def get_neighbors(self): res = [] for i in range(8): if self.neighbors[i] != None: res.append(self.neighbors[i]) return res def move_possible(self, dir): if self.neighbors[dir] != None: if self.neighbors[dir].occupant == None: return True return False class Environment: def __init__(self, disp, w, h): disp.register(self) self.disp = disp self.w = w self.h = h self.sectors = range(h) for i in range(h): self.sectors[i] = range(w) def build(self, do_diags=True): # Instanciate sectors for i in range(self.h): for j in range(self.w): self.sectors[i][j] = Sector(self.disp, i, j) # Link them for i in range(self.h): for j in range(self.w): if i > 0: self.sectors[i][j].neighbors[DIRECTION_UP] = self.sectors[i-1][j] if i < self.h-1: self.sectors[i][j].neighbors[DIRECTION_DOWN] = self.sectors[i+1][j] if j > 0: self.sectors[i][j].neighbors[DIRECTION_LEFT] = self.sectors[i][j-1] if j < self.w-1: self.sectors[i][j].neighbors[DIRECTION_RIGHT] = self.sectors[i][j+1] if do_diags: # Diagonals if i > 0 and j > 0: self.sectors[i][j].neighbors[DIRECTION_UPLEFT] = self.sectors[i-1][j-1] if i < (self.h - 1) and j < (self.w - 1): self.sectors[i][j].neighbors[DIRECTION_DOWNRIGHT] = self.sectors[i+1][j+1] if i > 0 and j < (self.w - 1): self.sectors[i][j].neighbors[DIRECTION_UPRIGHT] = self.sectors[i-1][j+1] if j > 0 and i < (self.h - 1): self.sectors[i][j].neighbors[DIRECTION_DOWNLEFT] = self.sectors[i+1][j-1] self.disp.post(EnvironmentBuiltEvent(self)) # Build list of free sectors and return it def get_free_sectors(self): free_sectors = [] for l in self.sectors: for c in l: if c.occupant == None: free_sectors.append(c) return free_sectors def notify(self, e): pass class ToricEnvironment(Environment): def __init__(self, disp, w, h): Environment.__init__(self, disp, w, h) def build(self, do_diags=True): # Instanciate sectors for i in range(self.h): for j in range(self.w): self.sectors[i][j] = Sector(self.disp, i, j) # Link them for i in range(self.h): for j in range(self.w): self.sectors[i][j].neighbors[DIRECTION_UP] = self.sectors[(i-1)%self.h][j] self.sectors[i][j].neighbors[DIRECTION_DOWN] = self.sectors[(i+1)%self.h][j] self.sectors[i][j].neighbors[DIRECTION_LEFT] = self.sectors[i][(j-1)%self.w] self.sectors[i][j].neighbors[DIRECTION_RIGHT] = self.sectors[i][(j+1)%self.w] if do_diags: self.sectors[i][j].neighbors[DIRECTION_UPLEFT] = self.sectors[(i-1)%self.h][(j-1)%self.w] self.sectors[i][j].neighbors[DIRECTION_DOWNRIGHT] = self.sectors[(i+1)%self.h][(j+1)%self.w] self.sectors[i][j].neighbors[DIRECTION_UPRIGHT] = self.sectors[(i-1)%self.h][(j+1)%self.w] self.sectors[i][j].neighbors[DIRECTION_DOWNLEFT] = self.sectors[(i+1)%self.h][(j-1)%self.w] self.disp.post(EnvironmentBuiltEvent(self)) class Agent: def __init__(self, disp): disp.register(self) self.disp = disp self.sector = None def place(self, sector): self.sector = sector self.sector.occupant = self self.disp.post(AgentPlacedEvent(self)) def move(self): print "Agent::move not implemented!" def notify(self, e): print "Agent::notify not implemented!" def __repr__(self): return "Agent@(Sector = %s)" % self.sector class Simulation: STOPPED = 0 RUNNING = 1 def __init__(self, disp, env): disp.register(self) self.disp = disp self.state = Simulation.STOPPED self.env = env def start(self): self.env.build() self.disp.post(SimulationStartedEvent(self)) self.state = Simulation.RUNNING def notify(self, e): if isinstance(e, TickEvent): if self.state == Simulation.STOPPED: print "Starting simulation..." self.start()