Last active
June 22, 2019 06:28
-
-
Save z-------------/a1c01653bad6705774173374bfe83902 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
| """ | |
| Any live cell with fewer than two live neighbours dies, as if by underpopulation. | |
| Any live cell with two or three live neighbours lives on to the next generation. | |
| Any live cell with more than three live neighbours dies, as if by overpopulation. | |
| Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction. | |
| """ | |
| import sys | |
| import time | |
| import re | |
| import argparse | |
| import curses | |
| CHAR_ALIVE = "#" | |
| CHAR_DEAD = " " | |
| height, width, size_x, size_y = -1, -1, -1, -1 | |
| ticks_per_second = 30 | |
| filename = None | |
| neighbors = [ | |
| (-1, -1), (-1, 0), (-1, 1), | |
| (0, -1), (0, 1), | |
| (1, -1), (1, 0), (1, 1) | |
| ] | |
| def cleanup() -> None: | |
| if stdscr: | |
| curses.endwin() | |
| def create_board(size_y: int, size_x: int) -> list: | |
| board = [[0 for _ in range(0, size_x)] for _ in range(0, size_y)] | |
| return board | |
| def print_board(board: list) -> None: | |
| for y in range(0, size_y): | |
| for x in range(0, size_x): | |
| if y is size_y - 1 and x is size_x - 1: | |
| break # curses can't draw bottom right character | |
| stdscr.addch(y, x, CHAR_ALIVE if board[y][x] is 1 else CHAR_DEAD) | |
| stdscr.refresh() | |
| def count_neighbors(board: list, y: int, x: int) -> int: | |
| count = 0 | |
| for neighbor in neighbors: | |
| nx = x + neighbor[1] | |
| ny = y + neighbor[0] | |
| if nx >= 0 and nx < size_x and ny >= 0 and ny < size_y and board[ny][nx] is 1: | |
| count += 1 | |
| return count | |
| def copy_board(board_to: list, board_from: list) -> None: | |
| for y in range(0, size_y): | |
| for x in range(0, size_x): | |
| board_to[y][x] = board_from[y][x] | |
| def update_board(board: list) -> None: | |
| buffer = create_board(size_y, size_x) | |
| for y in range(0, size_y): | |
| for x in range(0, size_x): | |
| n = count_neighbors(board, y, x) | |
| if board[y][x] is 1: | |
| if n < 2: | |
| buffer[y][x] = 0 | |
| elif n is 2 or n is 3: | |
| buffer[y][x] = 1 | |
| elif n > 3: | |
| buffer[y][x] = 0 | |
| else: | |
| if n is 3: | |
| buffer[y][x] = 1 | |
| copy_board(board, buffer) | |
| def tick(board: list) -> None: | |
| update_board(board) | |
| print_board(board) | |
| def main(): | |
| board = create_board(size_y, size_x) | |
| if filename: | |
| pat_int_line = re.compile(r"^\d+$") | |
| offset_y = 0 | |
| offset_y_set = False | |
| offset_x = 0 | |
| offset_x_set = False | |
| with open(filename, "r") as f: | |
| contents = f.read() | |
| lines = contents.split("\n") | |
| for y, line in enumerate(lines): | |
| if line: | |
| if line[0] == "#": | |
| continue | |
| elif pat_int_line.match(line): | |
| n = int(line) | |
| if not offset_y_set: | |
| offset_y = n | |
| offset_y_set = True | |
| elif not offset_x_set: | |
| offset_x = n | |
| offset_x_set = True | |
| for x, c in enumerate(line): | |
| if c == "X": | |
| if y + offset_y < size_y and x + offset_x < size_x: | |
| board[y + offset_y][x + offset_x] = 1 | |
| if ticks_per_second: | |
| while True: | |
| tick(board) | |
| time.sleep(1 / ticks_per_second) | |
| else: | |
| while True: | |
| tick(board) | |
| try: | |
| parser = argparse.ArgumentParser(description="A simple implementation of Conway's Game of Life in Python") | |
| parser.add_argument("file", type=str, nargs="?", | |
| help="name of file from which to load an initial board pattern") | |
| parser.add_argument("--tps", type=int, | |
| help="(ideal) number of ticks per second") | |
| args = parser.parse_args() | |
| if not args.tps is None and args.tps >= 0: | |
| ticks_per_second = args.tps | |
| if args.file: | |
| filename = args.file | |
| stdscr = curses.initscr() | |
| height, width = stdscr.getmaxyx() | |
| size_y = height | |
| size_x = width | |
| main() | |
| except KeyboardInterrupt: | |
| cleanup() | |
| except SystemExit: | |
| exit(0) | |
| except: | |
| cleanup() | |
| exp = sys.exc_info()[0] | |
| print("Exception:", exp.__name__) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment