hackthelobby/libcaca/python/examples/gol.py

172 lines
4.9 KiB
Python
Executable File

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# libcaca Colour ASCII-Art library
# Python language bindings
# Copyright (c) 2010 Alex Foulon <alxf@lavabit.com>
# All Rights Reserved
#
# This library is free software. It comes without any warranty, to
# the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
#
""" Libcaca Python bindings """
import random
import sys
import time
import caca
from caca.canvas import Canvas
from caca.display import Display, Event
class CellArray(object):
def __init__(self, width, height):
self.array = []
self.width = width
self.height = height
for i in range(0, self.height):
self.array.append([])
for j in range(0, self.width):
self.array[i].append([])
def get(self, x, y):
return self.array[x][y]
def set(self, x, y, value):
self.array[x][y] = value
def neighbors(self, x, y):
n = 0
h = self.height
w = self.width
if self.get((x-1)%h, (y-1)%w):
n += 1
if self.get((x-1)%h, y):
n += 1
if self.get((x-1)%h, (y+1)%w):
n += 1
if self.get(x, (y-1)%w):
n += 1
if self.get(x, (y+1)%w):
n += 1
if self.get((x+1)%h, (y-1)%w):
n += 1
if self.get((x+1)%h, y):
n += 1
if self.get((x+1)%h, (y+1)%w):
n += 1
return n
def population(self):
n = 0
for i in range(0, self.height):
for j in range(0, self.width):
if self.get(i, j):
n += 1
return n
class CellApp(object):
def __init__(self, width, height):
self.cycle = 0
self.auto = False
self.width = width
self.height = height
self.ca = CellArray(self.width, self.height)
self.cbuf = CellArray(self.width, self.height)
def nextCycle(self):
self.cycle += 1
for x in range(0, self.ca.height):
for y in range(0, self.ca.width):
if self.ca.get(x, y):
if self.ca.neighbors(x, y) >= 2 and self.ca.neighbors(x, y) <= 3:
self.cbuf.set(x, y, 1)
else:
self.cbuf.set(x, y, 0)
elif not self.ca.get(x, y):
if self.ca.neighbors(x, y) == 3:
self.cbuf.set(x, y, 1)
else:
self.cbuf.set(x, y, 0)
else:
self.cbuf.set(x, y, 0)
for x in range(0, self.ca.height):
for y in range(0, self.ca.width):
self.ca.set(x, y, self.cbuf.get(x, y))
def resetCycle(self):
self.cycle = 0
def randomCells(self):
for x in range(0, self.ca.height):
for y in range(0, self.ca.width):
self.ca.set(x, y, random.randint(0, 1))
def renderCells(self, cv):
cv.clear()
cv.set_color_ansi(caca.COLOR_WHITE, caca.COLOR_BLUE)
cv.put_str(0, 0, " "*cv.get_width())
cv.put_str(0, 0, "s: start, p: pause, n: next, r: random cells, z: reset all")
cv.put_str(0, cv.get_height()-1, " "*cv.get_width())
cv.put_str(0, cv.get_height()-1, "generation: %d, population: %d" % (self.cycle, self.ca.population()))
cv.set_color_ansi(caca.COLOR_DEFAULT, caca.COLOR_BLACK)
posx = (cv.get_height() - self.height) // 2
posy = (cv.get_width() - self.width) // 2
for x in range(0, self.ca.height):
for y in range(0, self.ca.width):
if self.ca.get(x, y):
cv.put_str(posy+y, posx+x, "@")
def zeroCells(self):
for x in range(0, self.ca.height):
for y in range(0, self.ca.width):
self.ca.set(x, y, 0)
if __name__ == "__main__":
cv = Canvas()
dp = Display(cv)
ev = Event()
app = CellApp(80, 20)
app.zeroCells()
while True:
if dp.get_event(caca.EVENT_KEY_PRESS, ev, 2):
ch = ev.get_key_ch()
if ch == ord('q'):
break
elif ch == ord('s'):
app.auto = True
elif ch == ord('n'):
app.nextCycle()
elif ch == ord('r'):
app.randomCells()
elif ch == ord('p'):
if app.auto:
app.auto = False
else:
app.auto = True
elif ch == ord('z'):
app.resetCycle()
app.zeroCells()
app.auto = False
if app.auto:
app.nextCycle()
app.renderCells(cv)
dp.refresh()
time.sleep(0.2)