life.c (3324B)
1 #define TB_IMPL 2 #include <inttypes.h> 3 #include <termbox.h> 4 #include <stdio.h> 5 #include <stddef.h> 6 #include <stdint.h> 7 #include <string.h> 8 #include <sys/stat.h> 9 #include <unistd.h> 10 11 #include "print_box.h" 12 13 14 #define WIDTH(x) sizeof(x[0]) * 8 15 #define MAX_ROWS 24 16 17 #define BOARD gosper 18 19 void print_board(uint64_t board[], int rows, int cols) { 20 print_box(rows, cols*2); 21 22 for(int y=0; y < rows; y++) { 23 uint64_t leftBit = 1ULL << (cols - 1); 24 uint64_t bit=leftBit; 25 for(int x=1; x <= cols*2; bit=bit>>1, x+=2) { 26 if (board[y] & bit) { 27 print_bw(x, y+1, ' '); 28 print_bw(x+1, y+1, ' '); 29 } 30 } 31 } 32 tb_present(); 33 } 34 35 void get_next_state(uint64_t *newBoard, uint64_t board[], int rows, int cols) { 36 uint64_t m[MAX_ROWS]; 37 for(int r=0; r < rows; r++) { 38 uint64_t newRow = board[r]; 39 /* For a single byte for example, this value will be 1000 0000.*/ 40 uint64_t leftBit = (uint64_t)(1ULL << (cols - 1)); 41 for(uint64_t bit=(uint64_t)leftBit, col=0; col < cols; bit=leftBit>>++col) { 42 /* Get neighbors in previous row, current row, next row. 43 Ignore nonexistent rows. */ 44 int neighbors = 0; 45 for(int a = -1; a <= 1; a++) { 46 if(r+a < 0 || r+a >= rows) continue; 47 uint64_t row = board[r+a]; 48 if(col > 0 && (row & bit<<1)) neighbors++; 49 /* Skip current cell */ 50 if(a != 0 && (row & bit)) neighbors++; 51 if(col < (cols - 1) && (row & bit>>1)) neighbors++; 52 if(neighbors > 3) break; 53 } 54 switch(neighbors) { 55 case 2: 56 //stay the same 57 break; 58 case 3: 59 //alive 60 newRow |= bit; 61 break; 62 default: 63 //dead 64 newRow &= ~bit; 65 break; 66 } 67 } 68 m[r] = newRow; 69 } 70 memcpy(newBoard, m, sizeof m); 71 } 72 73 size_t save_board_to_file(uint64_t *board) { 74 FILE *file = fopen("gghh1", "wb"); 75 if(!file) return -1; 76 size_t z = fwrite(board, sizeof(uint64_t), MAX_ROWS, file); 77 fclose(file); 78 return z; 79 } 80 81 void play(uint64_t board[], int rows, int cols) { 82 struct tb_event ev; 83 tb_init(); 84 while(1) { 85 tb_clear(); 86 print_board(board, rows, cols); 87 if (tb_peek_event(&ev, 300) == TB_OK && ev.type == TB_EVENT_KEY) 88 switch(ev.key) { 89 case TB_KEY_CTRL_C: 90 return; 91 case TB_KEY_CTRL_S: 92 save_board_to_file(board); 93 } 94 get_next_state(board, board, rows, cols); 95 } 96 } 97 98 size_t load_board_from_file(uint64_t **board, char *filename) { 99 *board = calloc(MAX_ROWS, sizeof(uint64_t)); 100 FILE *file = fopen(filename, "rb"); 101 if(!file) return -1; 102 size_t z = fread(*board, sizeof(uint64_t), MAX_ROWS, file); 103 fclose(file); 104 return z; 105 } 106 107 int main() { 108 uint64_t *board = 0; 109 char *filename = "mbytes"; 110 const size_t rows = MAX_ROWS; 111 const size_t cols = sizeof board[0] * 8; 112 113 if(load_board_from_file(&board, filename) < 1) { 114 printf("FATAL: Failed to load board from file %s.\n", filename); 115 return 1; 116 } 117 118 play(board, rows, cols); 119 tb_shutdown(); 120 return 0; 121 }