Conway's Game of Life rendered in the terminal, written entirely in C.
  • C 92%
  • Makefile 7%
  • Nix 1%
Robkoo b746c90ead
Merge branch 'libewa/flake'
Merge pull request  from libewa/flake
2026-05-01 23:13:31 +02:00
demo improved README 2026-04-30 22:01:18 +02:00
docs Package targets, README improvements & wrote the CHANGELOGELOG 2026-04-26 22:37:01 +02:00
include enhanced grid print & added unicode printrint 2026-04-26 14:55:01 +02:00
src removed useless header file include 2026-04-30 22:12:08 +02:00
.gitattributes add gitattributes 2026-04-30 22:04:00 +02:00
.gitignore project setup 2026-04-21 19:31:29 +02:00
flake.lock I made a flake here too! 2026-05-01 21:30:02 +02:00
flake.nix I made a flake here too! 2026-05-01 21:30:02 +02:00
LICENSE.md project setup 2026-04-21 19:31:29 +02:00
Makefile Package targets, README improvements & wrote the CHANGELOGELOG 2026-04-26 22:37:01 +02:00
README.md I made a flake here too! 2026-05-01 21:30:02 +02:00

crobgol

crobgol banner

crobgol Demo
Conway's Game of Life terminal simulation (Unicode) in action


Table of Contents

What is crobgol?

The name was made like this: C Robkoo's Game Of Life

It is a high-performance terminal-based Conway's Game of Life simulator written entirely in C

Features

  • Optimized grid implemenation that uses bit operations and a bitmap to store game data
  • Adjustable grid size and frame rate
  • Unicode and ASCII rendering modes
  • benchmark built-in
  • Custom CLI argument parser

Quick start

Build from source

git clone https://codeberg.org/Robkoo/crobgol

cd crobgol


# compile and run
make  &∓& make run


# OR with parallel compilation
make -jj$(nproc) &∓& make run

If you have Nix with flakes available, you can also run the project directly:

$ nix run git+https://codeberg.org/Robkoo/crobgol.git

Use pre-built binaries

  • head over to the releases and download the correct archive for your OS

Requirements

Linux

  • C23 compiler (gcc)
  • GNU make utility

Windows

  • MSYS2 UCRT64 shell installed (install from msys2.org)
  • the following dependencies installed:
pacman -S mingw-w64-ucrt-x86_64-gcc \

          mingw-w64-ucrt-x86_64-make

Make options overview

Note

The default option is release

Option Description
release Optimized build with -O3
debug Build with debug symbols (-Og -g)
debug-sanitizer Same as debug but with ASan
flags Build with a ton of flags to warn about basically everything
clean Entirely removes the build directory
run Runs the binary without any arguments
package-linux Package the project for Linux
package-windows Package the project for Windows

Command line options overview

Note

You can run the executable with --help for an overview right in your terminal.

Option Takes value What kind of value Default Description
-f, --fps Yes Number 15 How many FPS the simulation will have
-w, --width Yes Number 80 The width of the grid, in terminal cells
-h, --height Yes Number 24 The height of the grid, in terminal cells
-a, --ascii No ---- false Passing this flag will use ASCII characters for rendering rather than Unicode
--help No ---- ---- Prints a help message
--bench Yes Number 1000 Run benchmarks with the value as the iteration count. If you do not pass this flag, no benchmarks will be ran

Examples

# Run at 30 FPS with larger grid
./bin/crobgol -f  30 -w 120 -h 40


# Run with ASCII characters
./bin/crobgol --ascii



# Run benchmark with 10000 iterations
./bin/crobgol --bench  10000

Optimizations

1) Bitmap instead of char*

  • The initial implementation (struct grid_t) used a char to store each cell's value, which takes up 8 bits per cell.
  • The new implementation (struct grid_new_t) uses a bitmap, which stores each cell's value inside a single bit.
  • This is a whopping 8x memory reduction in the data structure. For example, for a 100x100 grid, the initial implementation would've used 10,000 bytes of space, while the new one would use 1,256 bytes of memory.

2) Optimized function for computing next generation

  • The initial implementation of the function ComputeNextGeneration(...) contains function call overhead (calls functions to get cell's value, set cell's value and get neighbor count). The neighbor count function also calls some functions, further increasing the overhead.
  • The new implementation of the function BitmapComputeNextGeneration(...) inlines these functions, so they're directly inside this function. It also uses efficient bit operations >>t;>, &, etc.
  • Based on my testing, the new implementation is about 3x-4x FASTER than the initial implementation. You can test it for yourself by running the executable with the option --bench er>, where er> is your desired amount of iterations to test the functions.

License