import random NEARBY = (None,None,None,None,None,None,None,None) GLOBAL_TEMP_FACTOR = 0.2 MAXX = 190 MAXY = 190 MINY = 10 toremove = [] changed = [] changedempty = [] class Element(object): moverate = 0.5 specific_heat = 1 conductivity = 1 basecolor = (255,255,255) name = "Base Element" gravity = 0 density = 100 liquid = False removed = False def __init__(self,x,y,grid,active,temperature=295.0): self.x, self.y = x,y self.temperature=temperature self.grid = grid self.active = active self.on_create() def on_create(self): pass def register(self): global changed self.active.append(self) self.grid[self.x][self.y] = self changed += [(self.x,self.y)] def remove(self): global changedempty changedempty += [(self.x,self.y)] self.grid[self.x][self.y] = None toremove.append(self) self.removed = True if self in self.active: self.active.remove(self) def transform(self,final): new = final(self.x,self.y,self.grid,self.active,self.temperature) new.register() self.remove() def position(self): return (self.x,self.y) def move(self,direction=(0,1),gravity=True): '''sets a new x&y position based on a direction tuple''' global changed global changedempty if self.removed: return oldx = self.x oldy = self.y self.x = self.x + direction[0] self.y = self.y + direction[1] if self.x <= 1: self.x = 2 elif self.x >= (MAXX +1): self.x = MAXX self.grid[oldx][oldy] = None self.grid[self.x][self.y] = self if self.y <= MINY: self.remove() return elif self.y >= (MAXY): self.remove() return changed.append((self.x,self.y)) changedempty.append((oldx,oldy)) def act(self): '''does stuff based on what is around this item. nearby is a tuple containing a clockwise list of elements next to this one starting at the top left 0 1 2 7 x 3 6 5 4 ''' nearby = self.nearby() nb = [n for n in nearby if n is not None and n is not BOUNDARY] for n in nb: self.temperate(n) nb = [n for n in nearby if n is not BOUNDARY] for n in nb: self.reaction(n) if all(nearby): return if self.gravity > 0: if random.random() < self.moverate: if nearby[5] is None: self.move((0,1)) elif nearby[5] is not BOUNDARY and self.name != nearby[5].name: self.densitycheck(nearby[5]) elif nearby[6] is None: self.move((-1,1)) elif nearby[4] is None: self.move((1,1)) elif nearby[7] is None and self.liquid: self.move((-1,0)) elif nearby[3] is None and self.liquid: self.move((1,0)) elif self.gravity < 0: if random.random() < self.moverate: if nearby[1] is None: self.move((0,-1)) elif nearby[0] is None: self.move((-1,-1)) elif nearby[2] is None: self.move((1,-1)) elif nearby[7] is None and self.liquid: self.move((-1,0)) elif nearby[3] is None and self.liquid: self.move((1,0)) else: pass def last_thing(): pass def temperate(self,touching): kc = min(self.conductivity,touching.conductivity) dt = (self.temperature-touching.temperature)*kc*GLOBAL_TEMP_FACTOR self.temperature -= dt touching.temperature += dt self.temp_action() def densitycheck(self,item): '''checks density of what's below to see if it can take its place''' if item.density < self.density: x0 = self.x y0 = self.y x1 = item.x y1 = item.y self.x = x1 self.y = y1 item.x = x0 item.y = y0 self.grid[self.x][self.y] = self self.grid[item.x][item.y] = item def temp_action(self): pass def color(self): return self.basecolor def nearby(self): x = self.x y = self.y grid = self.grid n0 = grid[x-1][y-1] n1 = grid[x][y-1] n2 = grid[x+1][y-1] n3 = grid[x+1][y] n4 = grid[x+1][y+1] n5 = grid[x][y+1] n6 = grid[x-1][y+1] n7 = grid[x-1][y] return (n0,n1,n2,n3,n4,n5,n6,n7) def reaction(self,touching): pass class Boundary(Element): name = 'boundary' basecolor = (255,255,255) moverate = 0 gravity = 0 density = 1000 liquid = False def __init__(self,x=0,y=0,grid=None,active=None,temperature=295.0): self.x, self.y = x,y self.temperature=temperature self.grid = grid self.active = active BOUNDARY = Boundary() class Water(Element): name = "Water" basecolor = (50,50,255) specific_heat = 100 moverate = .7 gravity = 1 density = 20 liquid = True def temp_action(self): if self.temperature > 378: if random.random() < .5: self.transform(Steam) class Oil(Element): name = 'Oil' basecolor = (180,180,180) moverate = .2 gravity = 1 density = 10 specific_heat = 50 liquid = True def temp_action(self): if self.temperature > 500: if random.random() < .2: self.transform(Fire) class Steam(Element): name = "Steam" basecolor = (50,50,150) moverate = .8 gravity = -1 density = 1 specific_heat = 120 liquid = True def temp_action(self): if self.temperature < 370: if random.random() < .5: self.transform(Water) class Wall(Element): name = "Wall" basecolor = (100,100,100) moverate = .5 gravity = 0 liquid = False density = 100 specific_heat = 30 def color(self): return (max(100,min(self.temperature/2,255)),100,100) class Fire(Element): name = 'Fire' basecolor = (200,50,50) moverate = .5 gravity = -1 density = 1 liquid = True specific_heat = 100 def on_create(self): self.temperature = 1000 def temp_action(self): if random.random() > .99: self.remove()