// A console conway's game of life program by Bruce Hill // Released under the MIT license, see LICENSE for details. // This file contains the main code for the table viewer. #include #include #include #include #include #include #ifndef bool typedef char bool; #endif static bool survive[9] = {0,0,1,1,0,0,0,0,0}; static bool birth[9] = {0,0,0,1,0,0,0,0,0}; static void update(const bool *cells, bool *future_cells) { int W = tb_width()/2, H = tb_height(); for (int y = 0; y < H; y++) { for (int x = 0; x < W; x++) { int neighbors = ( cells[(y-1 % H)*W + (x-1 % W)] + cells[(y-1 % H)*W + (x % W)] + cells[(y-1 % H)*W + (x+1 % W)] + cells[y*W + (x-1 % W)] + cells[y*W + (x+1 % W)] + cells[(y+1 % H)*W + (x-1 % W)] + cells[(y+1 % H)*W + (x % W)] + cells[(y+1 % H)*W + (x+1 % W)] ); future_cells[y*W + x] = cells[y*W + x] ? survive[neighbors] : birth[neighbors]; if (future_cells[y*W + x] != cells[y*W + x]) { tb_change_cell(2*x, y, ' ', 0, future_cells[y*W + x] ? 8 : 0); tb_change_cell(2*x+1, y, ' ', 0, future_cells[y*W + x] ? 8 : 0); } } } } int main(int argc, char **argv) { for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "--help") == 0) { printf("Conway's Game of Life Viewer\nUsage: conway [-S012345678] [-B012345678]\n"); return 0; } else if (strncmp(argv[i], "-B", 2) == 0) { memset(birth, 0, sizeof(birth)); for (char *p = &argv[i][2]; *p; p++) { if ('0' <= *p && *p <= '8') birth[*p - '0'] = 1; } } else if (strncmp(argv[i], "-S", 2) == 0) { memset(survive, 0, sizeof(survive)); for (char *p = &argv[i][2]; *p; p++) { if ('0' <= *p && *p <= '8') survive[*p - '0'] = 1; } } } int ret = tb_init(); if (ret) { fprintf(stderr, "tb_init() failed with error code %d\n", ret); return 1; } tb_select_input_mode(TB_INPUT_MOUSE); int flipflop = 0; int W = tb_width()/2, H = tb_height(); bool *buffers[2]; resize: buffers[0] = calloc(W*H, sizeof(bool)); buffers[1] = calloc(W*H, sizeof(bool)); for (int x = 0; x < W; x++) { for (int y = 0; y < H; y++) { buffers[flipflop][y*W+x] = random() % 2; } } tb_clear(); while (1) { update(buffers[flipflop], buffers[!flipflop]); flipflop = !flipflop; tb_present(); usleep(60000); struct tb_event ev; while (tb_peek_event(&ev, 0)) { switch (ev.type) { case TB_EVENT_RESIZE: W = tb_width()/2, H = tb_height(); goto resize; case TB_EVENT_KEY: switch (ev.key) { case TB_KEY_ESC: if (tb_peek_event(&ev, 50) == 0) goto done; else break; } switch (ev.ch) { case 'q': goto done; } break; case TB_EVENT_MOUSE: buffers[flipflop][ev.y*W + ev.x/2] = !buffers[flipflop][ev.y*W + ev.x/2]; tb_change_cell(2*(ev.x/2), ev.y, ' ', 0, buffers[flipflop][ev.y*W + ev.x/2] ? 8 : 0); tb_change_cell(2*(ev.x/2)+1, ev.y, ' ', 0, buffers[flipflop][ev.y*W + ev.x/2] ? 8 : 0); tb_present(); usleep(10000); break; } } } done: tb_shutdown(); return 0; }