#!/usr/bin/python3 # -*- coding: utf-8 -*- """Simple implementation of the Game of Life. The very clever idea of using a Python set of 2-tuples for this is not original to me. It gives us reasonably efficient membership tests, iteration over members, and full-board-state comparisons. """ import sys import time def show(b): "ANSI-art render of a board that is a set of (x, y) tuples on stdout." if not b: return x0 = min(x for x, y in b) xn = max(x for x, y in b) y0 = min(y for x, y in b) yn = max(y for x, y in b) sys.stdout.write('\033[H') for y in range(y0 - y0%8, yn+2): print(''.join('\033[44;34m##\033[0m' if (x, y) in b else ' ' for x in range(x0 - x0%8, xn+2)) + '\033[K') # erase-to-end-of-line ANSI escape sequence def succ(board): "Calculate the successor of a Life board." return {pos for pos in {n for cell in board for n in neighborhood(*cell)} for t in [sum(n in board for n in neighborhood(*pos))] if pos in board and t in (3, 4) # not 2,3 because center included or pos not in board and t == 3 } def neighborhood(x, y): "Return the coordinates of the 3×3 Moore neighborhood, including center." return [(x+dx, y+dy) for dx in [-1, 0, 1] for dy in [-1, 0, 1]] def main(me, *args): if not args: sys.stderr.write("Usage: {} 1,0 2,0 0,1 1,1 1,2 # e.g.\n".format(me)) return -1 old = board = {(int(x), int(y)) for a in args for x, y in [a.split(',')]} t = 0 while True: show(board) board = succ(board) time.sleep(.0167) if t % 2: # detect infinite loops, though not gliders old = succ(old) if old == board: print("(and so on)") break t += 1 if __name__ == '__main__': try: sys.exit(main(*sys.argv)) finally: sys.stdout.write("\033[0m")