Created
November 23, 2016 14:51
-
-
Save mousetail/8a0e91d794d7167e02f5b92048849f04 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#2d_anim.py | |
#Maurits van Riezen (mousetail) | |
#23 November 2015 | |
#Requires python 3 and pygame for python 3 | |
import pygame | |
import random | |
import itertools | |
import os | |
class Item(object): | |
def __init__(self, position): | |
self.color=random.choice(((0, 0, 0),(255,255,255))) | |
self.borderColor=tuple(255-i for i in self.color) | |
self.circle=random.choice((True,False)) | |
self.position=list(position) #Position is used for external reference only, it is not ever used | |
def draw(self, surface, position): | |
if self.circle: | |
pygame.draw.circle(surface, self.color, position, 8, 0) | |
pygame.draw.circle(surface, self.borderColor, position, 8, 2) | |
else: | |
pygame.draw.rect(surface, self.color, (position[0]-8,position[1]-8,16,16)) | |
pygame.draw.rect(surface, self.borderColor, (position[0]-8,position[1]-8,16,16), 2) | |
class Game(object): | |
WIDTH=8 | |
HEIGHT=6 | |
SPEED=180 | |
def __init__(self): | |
self.screen=pygame.display.set_mode((128*self.WIDTH, self.HEIGHT*128)) | |
self.generate() | |
self.drawGUI=True | |
self.holeIndex=0 | |
self.recording=False | |
self.draw() | |
self.check() | |
for iteration in range(4): | |
for i in range(len(self.machines)): | |
for j in range(len(self.machines[i])): | |
if random.randint(0,2)==1: | |
done=False | |
for x in range(-1,2): | |
for y in range(-1, 2): | |
if ((x==0) ^ (y==0)) and self.machines[i][j].__class__.getInputSides(x,y): | |
self.machines[i][j].addItem(Item((0,64)),(x, y)) | |
done=True | |
break | |
if done: | |
break | |
for i in range(random.randint(12,48)): | |
self.update() | |
def generate(self): | |
mainClasses=[] | |
midClasses=[] | |
junkClasses=[] | |
self.whiteHoles=[] | |
mainClasses.append(splitterMerger(((-1,0),(1,0)),((0,-1),(0,1)))) | |
mainClasses.append(splitterMerger(((0,-1),(0,1)),((-1,0),(1,0)))) | |
x=0 | |
y=1 | |
for direct in range(4): | |
directions=((x,y),(y,-x),(-x,-y),(-y,x)) | |
gr=(random.choice((mainClasses,midClasses,midClasses,midClasses)) for i in range(3)) | |
next(gr).append(bend(directions[0],directions[1])) | |
next(gr).append(bend(directions[1], directions[0])) | |
next(gr).append(bend(directions[0], directions[2])) | |
for i in range(-1,2): | |
for j in range(-1,2): | |
for k in range(-1,2): | |
if (j>i and k>i and k>=j): | |
if (j!=k): | |
l=merger((directions[i],directions[j],directions[k]), | |
directions[2]) | |
l2=splitter((directions[i],directions[j],directions[k]), | |
directions[2]) | |
else: | |
l=merger((directions[i],directions[k]),directions[2]) | |
l2=splitter((directions[i],directions[k]),directions[2]) | |
if j==k and random.randint(0,10)==1: | |
mainClasses.append(l2) | |
mainClasses.append(l) | |
else: | |
midClasses.append(l2) | |
midClasses.append(l) | |
midClasses.append(crosser(directions[0],directions[1],directions[3],directions[2])) | |
if direct==1 or direct==2: | |
midClasses.append(crosser(directions[0],directions[1],directions[2], | |
directions[3])) | |
x, y=directions[1] | |
for i in range(2): | |
for j in range(2): | |
for k in range(2): | |
for l in range(2): | |
dirs=(0,1),(1,0),(-1,0),(0,-1) | |
if (i or j or k or l): | |
junkClasses.append(whiteHole(tuple(dirs[m] for m in range(4) if (i,j,k,l)[m]))) | |
junkClasses.append(blackHole(tuple(dirs[m] for m in range(4) if (i,j,k,l)[m]))) | |
self.machines=[] | |
for i in range(self.WIDTH): | |
self.machines.append([None,]*self.HEIGHT) | |
for i in range(30): | |
x=random.randint(0,len(self.machines)-1) | |
y=random.randint(0,len(self.machines[x])-1) | |
if self.machines[x][y] is None: | |
self.machines[x][y]=self.findMachine(x,y,mainClasses,30) | |
for x in range(len(self.machines)): | |
for y in range(len(self.machines[0])): | |
if (self.machines[x][y] is None): | |
self.machines[x][y]=self.findMachine(x,y,mainClasses,30) | |
#if self.machines[x][y]!=None: print ("first try",(x,y)) | |
if (self.machines[x][y] is None): | |
self.machines[x][y]=self.findMachine(x,y,midClasses,480) | |
#if self.machines[x][y]!=None: print ("second try",(x,y)) | |
if (self.machines[x][y] is None): | |
self.machines[x][y]=self.findMachine(x,y,mainClasses,400) | |
#if self.machines[x][y]!=None: print ("third try",(x,y)) | |
if self.machines[x][y] is None: | |
self.machines[x][y]=self.findMachine(x,y,junkClasses,660) | |
#if self.machines[x][y]!=None: print ("fourth try",(x,y)) | |
if self.machines[x][y] is None: | |
#print ("giving up",(x,y)) | |
self.machines[x][y]=junkClasses[-1]() | |
if self.machines[x][y].getInputSides(0,0): | |
self.whiteHoles.append(self.machines[x][y]) | |
#print (x,y,self.machines[x][y]) | |
def findMachine(self, x, y, group, numiterations=60): | |
dirs=(0,1),(1,0),(0,-1),(-1,0) | |
for i in range(numiterations): | |
machine=random.choice(group) | |
done=True | |
for k in range(4): | |
oldMachine=self.getMachineAt((x,y),dirs[k]) | |
if oldMachine is None: | |
pass | |
elif ((machine.getOutputSides(*dirs[k]) and not oldMachine.getInputSides(*dirs[k-2])) or | |
(machine.getInputSides(*dirs[k]) and not oldMachine.getOutputSides(*dirs[k-2])) or | |
(oldMachine.getOutputSides(*dirs[k-2]) and not machine.getInputSides(*dirs[k])) or | |
(oldMachine.getInputSides(*dirs[k-2]) and not machine.getOutputSides(*dirs[k]))): | |
done=False | |
done=False | |
if done: | |
for dx, dy in dirs: | |
if self.getMachineAt((x,y),(dx,dy)) is None: | |
pass | |
elif machine.getOutputSides(dx,dy):\ | |
assert self.getMachineAt((x,y),(dx,dy)).getInputSides(-dx,-dy), str((x,y))+str((dx,dy)) | |
elif machine.getInputSides(dx,dy): | |
assert self.getMachineAt((x,y),(dx,dy)).getOutputSides(-dx,-dy), str((x,y))+str((dx,dy)) | |
elif not machine.getInputSides(dx, dy) and not machine.getInputSides(dx, dy): | |
assert (not self.getMachineAt((x,y),(dx,dy)).getOutputSides(-dx,-dy) and | |
not self.getMachineAt((x,y),(dx,dy)).getInputSides(-dx,-dy)), str((x,y))+str((dx,dy)) | |
#print ("took",i,"iterations ",(x,y)) | |
return machine() | |
return None | |
def check(self): | |
dirs=(0,1),(1,0),(0,-1),(-1,0) | |
for x, i in enumerate(self.machines): | |
for y, j in enumerate(i): | |
assert self.getMachineAt((x,y),(0,0))!=None, str(x,y) | |
for dx, dy in dirs: | |
if self.getMachineAt((x,y),(0,0)).getOutputSides(dx,dy): | |
assert self.getMachineAt((x,y),(dx,dy)).getInputSides(-dx,-dy), str((x,y))+str((dx,dy)) | |
if self.getMachineAt((x,y),(0,0)).getInputSides(dx,dy): | |
assert self.getMachineAt((x,y),(dx,dy)).getOutputSides(-dx,-dy), str((x,y))+str((dx,dy)) | |
def getMachineAt(self, pos, rel=(0,0)): | |
return self.machines[(pos[0]+rel[0])%len(self.machines)][(pos[1]+rel[1])%len(self.machines[0])] | |
def update(self): | |
items=[] | |
for x, column in enumerate(self.machines): | |
for y, machine in enumerate(column): | |
items.extend((x+dx,y+dy, (-dx, -dy), item) for ((dx, dy), item) in machine.update()) | |
for x, y, direction, item in items: | |
if direction!=(0,0): | |
self.getMachineAt((x,y),(0,0)).addItem(item, direction) | |
else: | |
self.holeIndex+=1 | |
if self.holeIndex>=len(self.whiteHoles): | |
self.holeIndex=0 | |
if len(self.whiteHoles)>0: | |
self.whiteHoles[self.holeIndex].addItem(item, direction) | |
def draw(self): | |
self.screen.fill((0,0,0)) | |
if self.drawGUI: | |
for x, i in enumerate(self.machines): | |
for y, j in enumerate(i): | |
j.drawBack(self.screen, (128*x, 128*y)) | |
for x, i in enumerate(self.machines): | |
for y, j in enumerate(i): | |
j.draw(self.screen, (128*x, 128*y)) | |
pygame.display.flip() | |
def event(self): | |
for event in pygame.event.get(): | |
if event.type==pygame.QUIT: | |
self.running=False | |
elif event.type==pygame.KEYDOWN: | |
if event.key==pygame.K_g: | |
self.drawGUI=not self.drawGUI | |
elif event.key==pygame.K_r: | |
if self.recording: | |
self.stopRecording() | |
else: | |
self.startRecording() | |
#print ("QUIT") | |
def run(self): | |
clock=pygame.time.Clock() | |
self.running=True | |
while self.running: | |
clock.tick(self.SPEED) | |
self.update() | |
self.draw() | |
if self.recording: | |
self.record() | |
self.event() | |
def startRecording(self): | |
index=0 | |
while os.path.exists(str(index)): | |
index+=1 | |
os.mkdir(str(index)) | |
self.recorddir=str(index) | |
self.recording=True | |
self.framenumber=0 | |
def record(self): | |
if framenumber%2==0: | |
pygame.image.save(self.screen, self.recorddir+"/"+str(self.framenumber)+".png") | |
self.framenumber+=1 | |
def stopRecording(self): | |
self.recording=False | |
class Machine(object): | |
@staticmethod | |
def getInputSides(xoffset, yoffset): | |
return False | |
@staticmethod | |
def getOutputSides(xoffset, yoffset): | |
return False | |
###### | |
#There are a total of 81 combinations: | |
#so far, I have | |
# 1 straigt (/4) | 1-1 | |
# 8 bends (out of 8) | 1-1 | |
#16 mergers | 3-1 2-1 | |
#16 splitters | 1-3 1-2 | |
#I need: | |
# 6 crossings | 2-2 | |
#16 black holes | 1-0 2-0 3-0 4-0 | |
#16 white holes | 0-1 0-2 0-3 0-4 | |
class ConveyorBelt(Machine): | |
@staticmethod | |
def getInputSides(xoffset, yoffset): | |
return yoffset==0 and xoffset==-1 | |
@staticmethod | |
def getOutputSides(xoffset, yoffset): | |
return yoffset==0 and xoffset==1 | |
def __init__(self): | |
self.items=[] | |
def update(self): | |
out=[] | |
for i in self.items: | |
i.position[0]+=1 | |
if i.position[0]>128: | |
out.append(i) | |
return (self.items.remove(i) or ((1,0),i) for i in out) | |
def addItem(self, item, direction): | |
if direction==(-1,0): | |
self.items.append(item) | |
item.position[0]=0 | |
item.position[1]=64 | |
else: | |
raise ValueError(direction) | |
def draw(self, surface, position): | |
for i in self.items: | |
assert -64<=i.position[0]<=64 and -64<=i.position[1]<=64, "position is "+str(i.position) | |
i.draw(surface, (position[0]+i.position[0], position[1]+i.position[1])) | |
def bend(inSide, outSide): | |
class ActualBend(Machine): | |
@staticmethod | |
def getInputSides(xoffset, yoffset): | |
return xoffset==inSide[0] and yoffset==inSide[1] | |
@staticmethod | |
def getOutputSides(xoffset, yoffset): | |
return xoffset==outSide[0] and yoffset==outSide[1] | |
def __init__(self): | |
self.items=[] | |
def update(self): | |
out=[] | |
for i in self.items: | |
if ((inSide[0]!=0 and i.position[0]//inSide[0]>0) or | |
inSide[1]!=0 and i.position[1]//inSide[1]>0): | |
i.position[0]-=inSide[0] | |
i.position[1]-=inSide[1] | |
else: | |
i.position[0]+=outSide[0] | |
i.position[1]+=outSide[1] | |
if (outSide[0]!=0 and i.position[0]//outSide[0]==64) or (outSide[1]!=0 and i.position[1]//outSide[1]==64): | |
out.append(i) | |
return (self.items.remove(i) or (outSide,i) for i in out) | |
def addItem(self, item, direction): | |
self.items.append(item) | |
if inSide[0]!=0: | |
item.position[0]=inSide[0]*64 | |
item.position[1]=0 | |
elif inSide[1]!=0: | |
item.position[1]=inSide[1]*64 | |
item.position[0]=0 | |
def drawBack(self, surface, position): | |
pygame.draw.lines(surface, (0,0,0), 0, ((position[0]+64+inSide[0]*64, position[1]+64+inSide[1]*64), | |
(position[0]+64, position[1]+64), | |
(position[0]+64+outSide[0]*64, position[1]+64+outSide[1]*64)),4) | |
pygame.draw.lines(surface, (255,255,255), 0, ((position[0]+64+inSide[0]*64, position[1]+64+inSide[1]*64), | |
(position[0]+64, position[1]+64), | |
(position[0]+64+outSide[0]*64, position[1]+64+outSide[1]*64))) | |
def draw(self, surface, position): | |
for i in self.items: | |
assert -64<=i.position[0]<=64 and -64<=i.position[1]<=64, "position is "+str(i.position) | |
i.draw(surface, (position[0]+i.position[0]+64, position[1]+i.position[1]+64)) | |
return ActualBend | |
def merger(entrances, exit): | |
class ActualMerger(Machine): | |
@staticmethod | |
def getInputSides(xoffset, yoffset): | |
for entrance in entrances: | |
if (xoffset==entrance[0] and yoffset==entrance[1]) : | |
return True | |
return False | |
@staticmethod | |
def getOutputSides(xoffset, yoffset): | |
return xoffset==exit[0] and yoffset==exit[1] | |
def __init__(self): | |
self.quiers=tuple((i,[]) for i in entrances) | |
self.exitquier=[] | |
self.quirpos=0 | |
def update(self): | |
out=[] | |
for item in self.exitquier: | |
if (item.position[0]==0 and exit[0]==0): | |
item.position[1]+=exit[1] | |
elif (item.position[1]==0 and exit[1]==0): | |
item.position[0]+=exit[0] | |
elif (item.position[0]<0 and exit[0]==0): | |
item.position[0]+=1 | |
elif (item.position[0]>0 and exit[0]==0): | |
item.position[0]-=1 | |
elif (item.position[1]<0 and exit[1]==0): | |
item.position[1]+=1 | |
elif (item.position[1]>0 and exit[1]==0): | |
item.position[1]-=1 | |
if abs(item.position[0])==64 or abs(item.position[1])==64: | |
out.append(item) | |
assert abs(item.position[0]<=64) and abs(item.position[1])<=64, item.position | |
if (len(self.exitquier)==0 or | |
(exit[0]!=0 and abs(self.exitquier[-1].position[0])>=16) or | |
(exit[1]!=0 and abs(self.exitquier[-1].position[1])>=16)): | |
startf=self.quirpos | |
self.quirpos+=1 | |
if self.quirpos>=len(self.quiers): | |
self.quirpos=0 | |
f=self.quiers[self.quirpos] | |
while startf!=self.quirpos and (len(f[1])==0 or abs(f[1][0].position[0])>16 or abs(f[1][0].position[1])>16): | |
self.quirpos+=1 | |
if self.quirpos>=len(self.quiers): | |
self.quirpos=0 | |
f=self.quiers[self.quirpos] | |
if len(f[1])!=0: | |
item=f[1][0] | |
if (abs(item.position[0])<=16 and abs(item.position[1])<=16): | |
self.exitquier.append(f[1].pop(0)) | |
for key, value in self.quiers: | |
for index, item in enumerate(value): | |
if ((index!=0 and (abs(item.position[0]-value[index-1].position[0]+item.position[1]-value[index-1].position[1])>16)) or | |
(index==0)) and (abs(item.position[0])>=16 or abs(item.position[1])>=16): | |
item.position[0]-=key[0] | |
item.position[1]-=key[1] | |
assert abs(item.position[0]<=64) and abs(item.position[1])<=64, item.position | |
return (self.exitquier.remove(i) or (exit, i) for i in out) | |
def addItem(self, item, direction): | |
self.quiers[entrances.index(tuple(direction))][1].append(item) | |
item.position[0]=direction[0]*64 | |
item.position[1]=direction[1]*64 | |
assert abs(item.position[0]<=64) and abs(item.position[1])<=64 | |
def drawBack(self, surface, position): | |
pygame.draw.line(surface, (100,0,0), (position[0]+64, position[1]+64), | |
(position[0]+64+64*exit[0], position[1]+64+64*exit[1]),3) | |
for i in entrances: | |
pygame.draw.line(surface, (100,0,0), (position[0]+64, position[1]+64), | |
(position[0]+64+64*i[0], position[1]+64+64*i[1])) | |
def draw(self, surface, position): | |
for i in itertools.chain(self.exitquier, *(item for key, item in self.quiers)): | |
assert -64<=i.position[0]<=64 and -64<=i.position[1]<=64, "position is "+str(i.position) | |
i.draw(surface, (position[0]+i.position[0]+64, position[1]+i.position[1]+64)) | |
return ActualMerger | |
def splitter(exits, entrance): | |
assert (entrance[0]==0) ^ (entrance[1]==0) | |
class ActualSplitter(Machine): | |
@staticmethod | |
def getOutputSides(xoffset, yoffset): | |
for exit in exits: | |
if (xoffset==exit[0] and yoffset==exit[1]) : | |
return True | |
return False | |
@staticmethod | |
def getInputSides(xoffset, yoffset): | |
return xoffset==entrance[0] and yoffset==entrance[1] | |
def __init__(self): | |
self.quiers=[(i,[]) for i in exits] | |
self.entrancequier=[] | |
self.currentQuirePos=0 | |
def update(self): | |
out=[] | |
toremove=[] | |
for item in self.entrancequier: | |
item.position[0]-=entrance[0] | |
item.position[1]-=entrance[1] | |
assert -64<=item.position[0]<=64 and -64<=item.position[1]<=64, "position is "+str(item.position) | |
if item.position[0]==0 and item.position[1]==0: | |
self.quiers[self.currentQuirePos][1].append(item) | |
toremove.append(item) | |
self.currentQuirePos+=1 | |
if self.currentQuirePos>=len(self.quiers): | |
self.currentQuirePos=0 | |
for i in toremove: | |
self.entrancequier.remove(i) | |
for key, value in self.quiers: | |
for index, item in enumerate(value): | |
item.position[0]+=key[0] | |
item.position[1]+=key[1] | |
assert -64<=item.position[0]<=64 and -64<=item.position[1]<=64, "position is "+str(item.position)+" key is "+str(key) | |
if abs(item.position[0])==64 or abs(item.position[1])==64: | |
out.append((key, item)) | |
for key, value in out: | |
suc=False | |
for i in self.quiers: | |
if i[0]==key: | |
i[1].remove(value) | |
suc=True | |
break | |
if not suc: | |
print ("Can't find quire to remove "+str(value)+" from") | |
return out | |
def addItem(self, item, direction): | |
assert direction[0]==entrance[0] and direction[1]==entrance[1], "direction="+str(direction)+"output="+str(entrance) | |
self.entrancequier.append(item) | |
item.position[0]=entrance[0]*64 | |
item.position[1]=entrance[1]*64 | |
def drawBack(self, surface, position): | |
pygame.draw.line(surface, (255,0,0), (position[0]+64, position[1]+64), | |
(position[0]+64+64*entrance[0], position[1]+64+64*entrance[1]),3) | |
for i in exits: | |
pygame.draw.line(surface, (255,0,0), (position[0]+64, position[1]+64), | |
(position[0]+64+64*i[0], position[1]+64+64*i[1])) | |
def draw(self, surface, position): | |
for i in itertools.chain(self.entrancequier, *(i[1] for i in self.quiers)): | |
assert -64<=i.position[0]<=64 and -64<=i.position[1]<=64, "position is "+str(i.position) | |
i.draw(surface, (position[0]+i.position[0]+64, position[1]+i.position[1]+64)) | |
return ActualSplitter | |
def splitterMerger(ins, outs): | |
class ActualSplitterMerger(Machine): | |
def __init__(self): | |
self.input=[[],[]] | |
self.output=[[],[]] | |
self.limbo=None | |
self.limbodir=None | |
self.inIndex=0 | |
self.outIndex=0 | |
@staticmethod | |
def getOutputSides(xoffset, yoffset): | |
for exit in outs: | |
if (xoffset==exit[0] and yoffset==exit[1]) : | |
return True | |
return False | |
@staticmethod | |
def getInputSides(xoffset, yoffset): | |
for entrance in ins: | |
if (xoffset==entrance[0] and yoffset==entrance[1]): | |
return True | |
return False | |
def update(self): | |
out=[] | |
for dir, lis in enumerate(self.output): | |
toRemove=[] | |
for itm in lis: | |
itm.position[0]+=outs[dir][0] | |
itm.position[1]+=outs[dir][1] | |
if abs(itm.position[0])==64 or abs(itm.position[1])==64: | |
out.append((outs[dir], itm)) | |
toRemove.append(itm) | |
for i in toRemove: | |
lis.remove(i) | |
if self.limbo is None: | |
start=self.inIndex | |
self.incrementInIndex() | |
while (self.inIndex!=start and (len(self.input[self.inIndex])==0 or | |
(abs(self.input[self.inIndex][0].position[0])!=16 | |
and abs(self.input[self.inIndex][0].position[1])!=16))): | |
self.incrementInIndex() | |
if (len(self.input[self.inIndex])>0 and | |
((abs(self.input[self.inIndex][0].position[0])==16 or | |
abs(self.input[self.inIndex][0].position[1])==16))): | |
self.limbo=self.input[self.inIndex][0] | |
self.input[self.inIndex].pop(0) | |
self.incrementOutIndex() | |
self.limbodir=tuple(outs[self.outIndex][i]-ins[self.inIndex][i] for i in (0,1)) | |
if self.limbo is not None: | |
self.limbo.position[0]+=self.limbodir[0] | |
self.limbo.position[1]+=self.limbodir[1] | |
if ((abs(self.limbo.position[0])==16 or abs(self.limbo.position[1])==16)): | |
self.output[self.outIndex].append(self.limbo) | |
self.limbo=None | |
for dir, lst in enumerate(self.input): | |
for index, itm in enumerate(lst): | |
if (index==0 or abs(lst[index-1].position[0]-itm.position[0])>16 | |
or abs(lst[index-1].position[1]-itm.position[1])>16) and ( | |
abs(itm.position[0])>16 or abs(itm.position[1])>16): | |
itm.position[0]-=ins[dir][0] | |
itm.position[1]-=ins[dir][1] | |
return out | |
def incrementInIndex(self): | |
self.inIndex+=1 | |
if self.inIndex>=len(ins): | |
self.inIndex=0 | |
def incrementOutIndex(self): | |
self.outIndex+=1 | |
if self.outIndex>=len(outs): | |
self.outIndex=0 | |
def addItem(self, itm, direction): | |
self.input[ins.index(direction)].append(itm) | |
itm.position[0]=64*direction[0] | |
itm.position[1]=64*direction[1] | |
def drawBack(self, surface, position): | |
for x, y in ins: | |
pygame.draw.line(surface, (0, 225, 0), (x*64+64+position[0],y*64+64+position[1]),(position[0]+64,position[1]+64)) | |
for x, y in outs: | |
pygame.draw.line(surface, (0, 0, 225), (x*64+64+position[0],y*64+64+position[1]),(position[0]+64,position[1]+64)) | |
def draw(self, surface, position): | |
for i in itertools.chain((self.limbo,), *itertools.chain(self.input,self.output)): | |
if i: | |
assert -64<=i.position[0]<=64 and -64<=i.position[1]<=64, "position is "+str(i.position) | |
i.draw(surface, (position[0]+i.position[0]+64, position[1]+i.position[1]+64)) | |
return ActualSplitterMerger | |
def crosser(inOne, outOne, inTwo, outTwo): | |
class ActualCrosser(Machine): | |
@staticmethod | |
def getOutputSides(xoffset, yoffset): | |
return (xoffset==outOne[0] and yoffset==outOne[1]) or (xoffset==outTwo[0] and yoffset==outTwo[1]) | |
@staticmethod | |
def getInputSides(xoffset, yoffset): | |
return (xoffset==inOne[0] and yoffset==inOne[1]) or (xoffset==inTwo[0] and yoffset==inTwo[1]) | |
def __init__(self): | |
self.trackOneStart=[] | |
self.trackOneMid=[] | |
self.trackOneEnd=[] | |
self.trackTwoStart=[] | |
self.trackTwoMid=[] | |
self.trackTwoEnd=[] | |
def update(self): | |
toRemove=[] | |
out=[] | |
for inp, outp, start, mid, end in ((inOne, outOne, self.trackOneStart, self.trackOneMid, self.trackOneEnd), | |
(inTwo, outTwo, self.trackTwoStart, self.trackTwoMid, self.trackTwoEnd)): | |
toRemove.clear() | |
for item in start: | |
item.position[0]-=inp[0] | |
item.position[1]-=inp[1] | |
if abs(item.position[0])==32 or abs(item.position[1])==32: | |
toRemove.append(item) | |
mid.append(item) | |
for itm in toRemove: | |
start.remove(itm) | |
toRemove.clear() | |
for item in mid: | |
item.position[0]+=outp[0]-inp[0] | |
item.position[1]+=outp[1]-inp[1] | |
if abs(item.position[0])==32 or abs(item.position[1])==32: | |
toRemove.append(item) | |
end.append(item) | |
for item in toRemove: | |
mid.remove(item) | |
toRemove.clear() | |
for item in end: | |
item.position[0]+=outp[0] | |
item.position[1]+=outp[1] | |
if abs(item.position[0])==64 or abs(item.position[1])==64: | |
toRemove.append(item) | |
out.append((outp,item)) | |
for item in toRemove: | |
end.remove(item) | |
return out | |
def addItem(self, item, direction): | |
if (direction==inOne): | |
item.position[0]=inOne[0]*64 | |
item.position[1]=inOne[1]*64 | |
self.trackOneStart.append(item) | |
elif (direction==inTwo): | |
item.position[0]=inTwo[0]*64 | |
item.position[1]=inTwo[1]*64 | |
self.trackTwoStart.append(item) | |
else: | |
raise ValueError(direction) | |
def drawBack(self, surface, position): | |
for ((x1, y1), (x2,y2)) in ((inOne, outOne), (inTwo, outTwo)): | |
pygame.draw.lines(surface, (0,100,0), 0, | |
((position[0]+64+x1*64, position[1]+64+y1*64), | |
(position[0]+64+x1*32, position[1]+64+y1*32), | |
(position[0]+64+x2*32, position[1]+64+y2*32), | |
(position[0]+64+x2*64, position[1]+64+y2*64)) | |
) | |
def draw(self, surface, position): | |
for item in itertools.chain(self.trackOneStart, self.trackOneMid, self.trackOneEnd, self.trackTwoStart, self.trackTwoMid, self.trackTwoEnd): | |
assert -64<=item.position[0]<=64 and -64<=item.position[1]<=64, "position is "+str(item.position) | |
item.draw(surface, (position[0]+64+item.position[0], position[1]+64+item.position[1])) | |
return ActualCrosser | |
def blackHole(entrances): | |
class ActualBlackHole(Machine): | |
@staticmethod | |
def getOutputSides(xoffset, yoffset): | |
return xoffset==(0,0) and yoffset==(0,0) | |
@staticmethod | |
def getInputSides(xoffset, yoffset): | |
return (xoffset, yoffset) in entrances | |
def __init__(self): | |
self.items=[] | |
def update(self): | |
l=tuple(((0,0), i) for i in self.items) | |
self.items.clear() | |
return l | |
def addItem(self, item, direction): | |
self.items.append(item) | |
def draw(self, surface, position): | |
pass | |
def drawBack(self, surface, position): | |
pygame.draw.circle(surface, (0,0,0), (position[0]+64,position[1]+64), 64) | |
pygame.draw.circle(surface, (255,255,255), (position[0]+64,position[1]+64), 64,2) | |
return ActualBlackHole | |
def whiteHole(entrances): | |
class ActualWhiteHole(Machine): | |
@staticmethod | |
def getOutputSides(xoffset, yoffset): | |
return (xoffset, yoffset) in entrances | |
@staticmethod | |
def getInputSides(xoffset, yoffset): | |
return xoffset==0 and yoffset==0 | |
def __init__(self): | |
self.items=[] | |
self.exitIndex=0 | |
def update(self): | |
itemscopy=self.items | |
self.items=[] | |
out=[] | |
for i in itemscopy: | |
self.exitIndex+=1 | |
if self.exitIndex>=len(entrances): | |
self.exitIndex=0 | |
out.append((entrances[self.exitIndex],i)) | |
return out | |
def addItem(self, item, direction): | |
self.items.append(item) | |
def drawBack(self, surface, position): | |
pygame.draw.circle(surface, (255,255,255), (position[0]+64,position[1]+64), 62, 0) | |
def draw(self, surface, position): | |
pass | |
return ActualWhiteHole | |
if __name__=="__main__": | |
Game().run() | |
pygame.quit() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment