life

The "Game of Life" written in C.
Log | Files | Refs

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 }