ASCII Game of Life in Zig !
Table of contents
After 7 years of code, 2 of which professionally, one might think I would have already done it, but no... I was today years old when I made my first game of life project!
I wanted to explore Zig and become better at it, so I decided to play a bit with it.
Why Zig ?
Well, I tried C, Rust, and Nim, but C was too hard for me to want to keep coding with it until it wasn't anymore. Rust seemed nice, but I'm not a fan of the Something<> syntax, and it didn't click for me. Nim was my favorite one, but resources were hard to find. When I first tried Zig (0.9.0), I fell in love with the idea of not having any hidden control flow. I could see everything and understand anything just by looking at it long enough. The compiler is easy to use, and the comptime feature is very nice and intuitive; it just clicked.
Ziglings and the Zig Discord
I already had the basics down in C and understood the stack and heap, so it was fairly easy to pick up. However, to stay motivated to continue, I needed quick wins. In order to get my quick wins I did the [Ziglings Exercices](https://codeberg.org/ziglings/exercises/). I struggled with one of the exercises and was introduced to the Ziglang Discord server. I submitted a ticket with the exercise and some code samples (after checking for duplicates), and within 2 minutes, 3 people were explaining to me how slices and arrays are implemented and used in Zig.
The Game Of Life !
All motivated, I decided to build a game of life in the terminal, and I'm really proud of the result! I put margins all around a frame that I was drawing in order to not deal with the edges in my computations.
I struggled for two days because the neighbor count was correct, the logic was correct, but somehow a three # high horizontal bar would turn into a 2x3 C.
The culprit? I did not initialize my next_state
to false
, so it was undefined the first time and then kept the last computation as a base point.
//...
// Not actual Golang but the syntax highlight is near
var current_index: usize = undefined;
var neigbhour_count: usize = undefined;
var next_state: bool = undefined;
while (true) {
// Changes buf 2 based on buff 1 data
for (start_row..start_row + frame.height) |row| {
for (start_col..start_col + frame.width) |col| {
current_index = row * w.col + col;
// The neighbour counts the right number and the right neighbour
neigbhour_count = 0;
for ((current_index - 1)..(current_index + 2)) |i| {
if (buffer[i - w.col] == @intFromEnum(chars.FILLED)) neigbhour_count += 1;
if (buffer[i + w.col] == @intFromEnum(chars.FILLED)) neigbhour_count += 1;
if (current_index == i) continue;
if (buffer[i] == @intFromEnum(chars.FILLED)) neigbhour_count += 1;
}
// This is the culprit
next_state = false; // from here
// The logic is the good one :3
if (neigbhour_count < 2 or neigbhour_count > 3) {
next_state = false;
} else if (neigbhour_count == 2 and buffer[current_index] == @intFromEnum(chars.FILLED)) {
next_state = true;
} else if (neigbhour_count == 3) {
next_state = true;
}
buffer2[current_index] = if (next_state) @intFromEnum(chars.FILLED) else @intFromEnum(chars.EMPTY);
// to here
}
}
Conclusion
There really isn't a conclusion except that Zig is easier to pick up than C and Rust. While writing the article, I noticed I could just have the from here
to here
as a one-liner. That's the type of thing I usually only get to do in my Python CodinGame sessions :3
buffer2[current_index] = if (neigbhour_count == 2 and
buffer[current_index] == @intFromEnum(chars.FILLED) or
neigbhour_count == 3) @intFromEnum(chars.FILLED) else @intFromEnum(chars.EMPTY);
Subscribe to my newsletter
Read articles from Tristan Duret directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Tristan Duret
Tristan Duret
I like to code in my spare time. I'd like to get better with wasm currently ! I love seeing new languages and frameworks. I at least know how to hello world on all the low level stuff in my tech stack and how to make a simple user CRUD + Search with the web things. I like learning stuff, it makes me feel smart and likely useful for most cases.