Editing User:Danf/TurtleGraphics
Jump to navigation
Jump to search
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision | Your text | ||
Line 1: | Line 1: | ||
python turtle module -> Conway's Game of Life ... and stuff. | |||
experimental work in progress, needs to be cleaned up and refactored a bit ... | |||
<pre> | <pre> | ||
# turtlife.py - Artistic License w/ Attribution -> "(evil) Dan of MOISEBRIDGE" | # turtlife.py - Artistic License w/ Attribution -> "(evil) Dan of MOISEBRIDGE" | ||
# note: press 'n' to advance frame, 'r' to run, 'p' to pause | # note: press 'n' to advance frame, 'r' to run, 'p' to pause, 'x' to re-randomize | ||
from turtle import Screen, Turtle, mainloop | from turtle import Screen, Turtle, mainloop | ||
from itertools import | from itertools import islice, product, repeat, starmap | ||
from random import randint | |||
from random import | |||
from time import sleep | from time import sleep | ||
class Cell(object): | class Cell(object): | ||
Line 52: | Line 17: | ||
self.row = row | self.row = row | ||
self.col = col | self.col = col | ||
self. | self.val = 0 | ||
self. | self.extra = 0 | ||
self. | self.rules = colony.rules | ||
self._neighbors = None | self._neighbors = None | ||
def neighbors(self): | def neighbors(self): | ||
if self._neighbors is None: | if self._neighbors is None: | ||
self._neighbors = list( | self._neighbors = list(self.colony.neighbormap(self, self.colony.cells)) | ||
return self._neighbors | return self._neighbors | ||
def neighborsum(self): | def neighborsum(self): | ||
return sum(o. | return sum(o.val for o in self.neighbors()) | ||
def destiny(self): | def destiny(self): | ||
n = self.neighborsum() | |||
return ( | if self.rules == 'prime': | ||
def | return ((self.val if (n == 5 or n == 7) else 1 if (n == 2 or n == 3) else 0), n) | ||
if | elif self.rules == 'life': | ||
self. | return ((self.val if (n == 2) else 1 if (n == 3) else 0), n) | ||
if | def value(self, val=None, extra=None): | ||
self. | if val is not None: | ||
return self. | self.val = val | ||
if extra is not None: | |||
self.extra = extra | |||
return self.val | |||
def valchar(self): | |||
return (' ', 'o')[self.val] | |||
class | class Raster(object): | ||
def __init__(self, rules, displaymode, rows, cols): | def __init__(self, rules, displaymode, rows, cols): | ||
self. | self.rules = rules | ||
self.displaymode = displaymode | |||
self.rows = rows | self.rows = rows | ||
self.cols = cols | self.cols = cols | ||
Line 82: | Line 51: | ||
lambda x, y: Cell(self, x, y), | lambda x, y: Cell(self, x, y), | ||
product(range(rows), range(cols)) )) | product(range(rows), range(cols)) )) | ||
self. | self.turtles = None | ||
self. | def rowslice(self, r): | ||
i = r * self.cols | |||
return islice(self.cells, i, i + self.cols) | |||
def neighborhood(self, row, col): | def neighborhood(self, row, col): | ||
up = row - 1 if row else self.rows - 1 | up = row - 1 if row else self.rows - 1 | ||
Line 92: | Line 63: | ||
(row, left), (row, right), | (row, left), (row, right), | ||
(down, left), (down, col), (down, right) ) | (down, left), (down, col), (down, right) ) | ||
def | def neighbormap(self, o, sq): | ||
return starmap( | |||
lambda x, y: sq[x * self.cols + y], | |||
self.neighborhood(o.row, o.col) ) | |||
lambda x, y: | |||
def turtledisplay(self): | def turtledisplay(self): | ||
if self.turtles is None: | |||
self.turtles = list(CellularTurtle(self, row, col) for row in range(self.rows) for col in range(self.cols)) | |||
for c, t in zip(self.cells, self.turtles): | for c, t in zip(self.cells, self.turtles): | ||
if c. | if c.val: | ||
if c. | if c.extra == 2: | ||
t. | t.rgb = list(t.colors['blue']) | ||
elif c. | elif c.extra == 3: | ||
t. | t.rgb = list(t.colors['green']) | ||
elif c. | elif c.extra == 5: | ||
t. | t.rgb = list(t.colors['yellow']) | ||
elif c. | elif c.extra == 7: | ||
t. | t.rgb = list(t.colors['red']) | ||
else: | else: | ||
if self.displaymode == 'ambient': | if self.displaymode == 'ambient': | ||
t. | t.rgb = list(t.ambience()) | ||
elif self.displaymode == 'fade': | elif self.displaymode == 'fade': | ||
t. | for i in range(3): | ||
t.rgb[i] *= 0.618 | |||
else: | else: | ||
t. | t.rgb = list(t.colors['black']) | ||
t.color(t.rgb) | |||
def textdisplay(self): | |||
for r in range(self.rows): | |||
print(''.join(map(lambda x: x.valchar(), self.rowslice(r)))) | |||
def display(self): | |||
self.turtledisplay() | |||
self.textdisplay() | |||
def | |||
for | |||
def | |||
class | class CellularTurtle(Turtle): | ||
def __init__(self, colony, row, col): | def __init__(self, colony, row, col): | ||
Turtle.__init__(self) | Turtle.__init__(self) | ||
Line 227: | Line 103: | ||
self.col = col | self.col = col | ||
self.speed(0) | self.speed(0) | ||
self.shape(" | # self.hideturtle() | ||
self.settiltangle( | self.shape("circle") | ||
# self.settiltangle(90) | |||
self.resizemode("user") | self.resizemode("user") | ||
self.shapesize( | self.shapesize(2, 2, 0) | ||
self. | self.pu() | ||
self.setx(col) | self.setx(col) | ||
self.sety(row) | self.sety(row) | ||
Line 242: | Line 119: | ||
( 'green', (0.0, 0.7, 0.0) ), | ( 'green', (0.0, 0.7, 0.0) ), | ||
( 'blue', (0.0, 0.0, 0.7) ) ) ) | ( 'blue', (0.0, 0.0, 0.7) ) ) ) | ||
self. | self.rgb = list(self.colors['black']) | ||
self.color(self.rgb) | |||
self._neighbors = None | self._neighbors = None | ||
def neighbors(self): | def neighbors(self): | ||
if self._neighbors is None: | if self._neighbors is None: | ||
self._neighbors = list( | self._neighbors = list(self.colony.neighbormap(self, self.colony.turtles)) | ||
return self._neighbors | return self._neighbors | ||
def avg_rgb(self, turtles): | def avg_rgb(self, turtles): | ||
rgb = [0.0, 0.0, 0.0] | rgb = [0.0, 0.0, 0.0] | ||
Line 269: | Line 135: | ||
def ambience(self): | def ambience(self): | ||
return self.avg_rgb(self.neighbors()) | return self.avg_rgb(self.neighbors()) | ||
class CellRunner(object): | |||
def __init__(self, rules, displaymode, rows, cols): | |||
self.raster = Raster(rules, displaymode, rows, cols) | |||
self.randomize() | |||
def randomize(self): | |||
list(map(lambda x: x.value(randint(0, 1)), self.raster.cells)) | |||
def update(self, sync=True): | |||
dst = map(lambda x: x.destiny(), self.raster.cells) | |||
if sync: | |||
dst = list(dst) | |||
list(starmap( | |||
lambda x, y: x.value(*y), | |||
zip(self.raster.cells, dst) )) | |||
self.raster.display() | |||
def run(self, n=0, delay=0.1): | |||
f = (lambda: repeat(1, n)) if n else (lambda: repeat(1)) | |||
for x in f(): | |||
try: | |||
self.update(sync=True) | |||
if(delay): | |||
sleep(delay) | |||
except: | |||
break | |||
class ScreenRunner(object): | class ScreenRunner(object): | ||
def __init__(self, rules='prime', displaymode='ambient' | def __init__(self, rules='prime', displaymode='ambient', rows=16, cols=32): | ||
self.screen = self.initscreen(rows, cols) | self.screen = self.initscreen(rows, cols) | ||
self. | self.cellrunner = CellRunner(rules, displaymode, rows, cols) | ||
self. | self.running = False | ||
self. | self.next() | ||
def initscreen(self, rows, cols): | def initscreen(self, rows, cols): | ||
screen = Screen() | screen = Screen() | ||
Line 287: | Line 176: | ||
return screen | return screen | ||
def bindkeys(self, screen): | def bindkeys(self, screen): | ||
screen.onkey(self. | screen.onkey(self.randomize, 'x') | ||
screen.onkey(self.next, 'n') | screen.onkey(self.next, 'n') | ||
screen.onkey(self.run, 'r') | |||
screen.onkey(self.save, 's') | |||
screen.onkey(self.pause, 'p') | screen.onkey(self.pause, 'p') | ||
screen.onkey(self.quit, 'q') | screen.onkey(self.quit, 'q') | ||
screen.listen() | screen.listen() | ||
def | def randomize(self): | ||
self.cellrunner.randomize() | |||
self.next() | |||
self. | |||
def next(self): | def next(self): | ||
self. | self.cellrunner.run(1, 0) | ||
def run(self): | def run(self): | ||
self.running = True | self.running = True | ||
self.timer() | self.timer() | ||
def | def save(self): | ||
self. | self.pause(r) | ||
def | s = ''.join(str(o.val) for o in self.cellrunner.raster.cells) | ||
self. | print(s) | ||
def pause(self): | |||
self.running = False | |||
def quit(self): | def quit(self): | ||
exit() | exit() | ||
def timer(self, delay= | def timer(self, delay=100): | ||
if self.running: | if self.running: | ||
self.next() | self.next() | ||
Line 327: | Line 205: | ||
def main(): | def main(): | ||
ScreenRunner(rules=' | sr = ScreenRunner(rules='life', displaymode='fade', rows=7, cols=11) | ||
return "EVENTLOOP" | return "EVENTLOOP" | ||
Line 334: | Line 212: | ||
print(msg) | print(msg) | ||
mainloop() | mainloop() | ||