Last active
July 7, 2016 09:20
-
-
Save codekansas/e0a94b5a5670e0a1228395885d618bb2 to your computer and use it in GitHub Desktop.
My implementation of Wireworld in Python
This file contains 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
from __future__ import print_function | |
from time import sleep | |
import os | |
type_to_rep = { | |
'empty': '.', | |
'head': 'H', | |
'tail': 'T', | |
'conductor': '=', | |
'invalid': 'X', | |
} | |
rep_to_type = dict((v, k) for k, v in type_to_rep.items()) | |
class Engine: | |
def __init__(self, width=None, height=None, text=None, step_time=0.2): | |
assert (width is not None and height is not None) or text is not None | |
self.step_time = step_time | |
if width is not None and height is not None: | |
self.width = width | |
self.height = height | |
self._data = [[type_to_rep['empty']] * height for _ in range(width)] | |
else: | |
self.load_from_text(text) | |
self.width = len(self._data) | |
self.height = len(self._data[0]) | |
self.x_off = [-1, -1, -1, 0, 0, 1, 1, 1] | |
self.y_off = [-1, 0, 1, -1, 1, -1, 0, 1] | |
def load_from_text(self, s): | |
self._data = [[i for i in j.split(' ')] for j in s.split('\n')] | |
def dump_to_text(self): | |
return '\n'.join(' '.join([str(i) for i in b]) for b in self._data) | |
def __setitem__(self, key, item): | |
assert isinstance(key, tuple) and len(key) == 2, 'Must provide x and y coordinates for lookup' | |
if isinstance(key[0], int): | |
key = (slice(key[0], key[0]+1, None), key[1]) | |
if isinstance(key[1], int): | |
key = (key[0], slice(key[1], key[1]+1, None)) | |
if isinstance(item, str) and item in type_to_rep: | |
item = type_to_rep[item] | |
for i in self._data[key[0]]: | |
i[key[1]] = [item] * len(i[key[1]]) | |
def __getitem__(self, key): | |
assert isinstance(key, tuple) and len(key) == 2, 'Must provide x and y coordinates for lookup' | |
if isinstance(key[0], int) and isinstance(key[1], int): | |
if key[0] < 0 or key[0] >= self.width or key[1] < 0 or key[1] >= self.height: | |
return 'invalid' | |
return rep_to_type[self._data[key[0]][key[1]]] | |
if isinstance(key[0], int): | |
key = (slice(key[0], key[0]+1, None), key[1]) | |
if isinstance(key[1], int): | |
key = (key[0], slice(key[1], key[1]+1, None)) | |
return [[i for i in d[key[1]]] for d in self._data[key[0]]] | |
def clear_screen(self): | |
os.system('cls' if os.name == 'nt' else 'clear') | |
def count_neighbors_of_type(self, t, x, y, ignore): | |
c = 0 | |
for x_shift, y_shift in zip(self.x_off, self.y_off): | |
if self[x+x_shift, y+y_shift] == t and (x+x_shift, y+y_shift) not in ignore: | |
c += 1 | |
return c | |
def __repr__(self): | |
message = ' ' + ' '.join([str(i)[-1] for i, _ in enumerate(self._data[0])]) + '\n' | |
message += '\n'.join(str(c)[-1] + ' ' + ' '.join([str(i) for i in b]) + ' ' + str(c)[-1] for c, b in enumerate(self._data)) | |
message += '\n ' + ' '.join([str(i)[-1] for i, _ in enumerate(self._data[0])]) | |
return message | |
def step(self): | |
self.clear_screen() | |
changed = set() | |
for x in range(self.width): | |
for y in range(self.height): | |
if self[x, y] == 'conductor': | |
if self.count_neighbors_of_type('head', x, y, changed) in [1, 2]: | |
self[x, y] = 'head' | |
changed.add((x, y)) | |
for x in range(self.width): | |
for y in range(self.height): | |
if self[x, y] == 'head' and (x, y) not in changed: | |
self[x, y] = 'tail' | |
changed.add((x, y)) | |
elif self[x, y] == 'tail' and (x, y) not in changed: | |
self[x, y] = 'conductor' | |
changed.add((x, y)) | |
print(self) | |
def run(self, n_steps=-1): | |
if n_steps == -1: | |
while True: | |
self.step() | |
sleep(self.step_time) | |
for i in range(n_steps): | |
self.step() | |
sleep(self.step_time) | |
if __name__ == '__main__': | |
# coincidence detector | |
engine = Engine(text='''. . . . . . . . . . . . . . . . . . . . . . . . | |
. . . . . . . . . . . = = . = = = = = = = . . . | |
. . . = = = = = = = = . = . = . = . . . . = . . | |
. = = . . . . . . . . = = = = = = . . . . = . . | |
= . . = = . . . = = = . . = . . . . . . . = . . | |
= . . . . = . = . . . . = = = . . . . . = . . . | |
= . . . . = . = . . . = . . . = = = . = . = = . | |
= . . . . . = . . . . . = T H . . . = . . . . = | |
= . . = = = . = = = = . . . . . . = . . . . . = | |
= . = . . . . . . . . = = = = = = . . . . . . = | |
= . . = = = T H = = = . . . . . . = . . = = = . | |
= . . . . . . . . . . = = = = = = . . = . . . = | |
. = = = = = = = = = = . . . . . . . . . = T H .''') | |
# print(engine) | |
engine.run() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment