Skip to content

Instantly share code, notes, and snippets.

@ltriant
Last active April 8, 2021 02:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ltriant/c2aed6babaacc3679eabb681720eadfe to your computer and use it in GitHub Desktop.
Save ltriant/c2aed6babaacc3679eabb681720eadfe to your computer and use it in GitHub Desktop.
Conway's Game of Life in Zig
// Conway's Game of Life
//
// Initialises the canvas randomly
//
// zig run life.zig -isystem /usr/local/include --library sdl2
const std = @import("std");
const os = std.os;
const warn = std.debug.warn;
const c = @cImport({
@cInclude("stdlib.h");
@cInclude("SDL2/SDL.h");
});
const ErrorSet = error{SDLError};
const ScreenWidth = 256;
const ScreenHeight = 240;
fn initRandom(canvas: *[ScreenHeight][ScreenWidth]bool) void {
for (canvas) |row, y| {
for (row) |_, x| {
var b: [1]u8 = undefined;
os.getrandom(&b) catch |err| {
warn("unable to getrandom: {}\n", .{err});
return;
};
canvas[y][x] = b[0] < 128;
}
}
}
fn nextStep(canvas: [ScreenHeight][ScreenWidth]bool, x: usize, y: usize) bool {
var on: usize = 0;
// Vertical neighbors
if (y > 0 and canvas[y - 1][x])
on += 1;
if ((y < ScreenHeight - 1) and canvas[y + 1][x])
on += 1;
// Horizontal neighbors
if (x > 0 and canvas[y][x - 1])
on += 1;
if ((x < ScreenWidth - 1) and canvas[y][x + 1])
on += 1;
// Diagonally adjacent neighbors
if (x > 0 and y > 0 and canvas[y - 1][x - 1])
on += 1;
if ((x < ScreenWidth - 1) and (y < ScreenHeight - 1) and canvas[y + 1][x + 1])
on += 1;
if (x > 0 and (y < ScreenHeight - 1) and canvas[y + 1][x - 1])
on += 1;
if ((x < ScreenWidth - 1) and y > 0 and canvas[y - 1][x + 1])
on += 1;
// Conway's Game of Life rules
if (canvas[y][x]) {
switch (on) {
1 => {
return false;
},
2, 3 => {
return true;
},
4 => {
return false;
},
else => {},
}
} else {
if (on == 3)
return true;
}
return false;
}
pub fn main() !void {
if (c.SDL_Init(c.SDL_INIT_VIDEO) != 0) {
warn("Unable to initialise SDL: {}\n", .{c.SDL_GetError()});
return ErrorSet.SDLError;
}
defer c.SDL_Quit();
var window = c.SDL_CreateWindow("Game of Life", 100, 100, ScreenWidth * 2, ScreenHeight * 2, c.SDL_WINDOW_SHOWN);
if (window == null) {
warn("Unable to create window: {}\n", .{c.SDL_GetError()});
return ErrorSet.SDLError;
}
defer c.SDL_DestroyWindow(window);
var surface = c.SDL_GetWindowSurface(window);
var event: c.SDL_Event = undefined;
var quit = false;
var current_canvas: [ScreenHeight][ScreenWidth]bool = undefined;
var next_canvas: [ScreenHeight][ScreenWidth]bool = undefined;
initRandom(&current_canvas);
while (!quit) {
while (c.SDL_PollEvent(&event) != 0) {
switch (event.type) {
c.SDL_QUIT => {
quit = true;
},
else => {},
}
}
for (current_canvas) |row, y| {
for (row) |_, x| {
var onoff = nextStep(current_canvas, x, y);
var rgb: u8 = if (onoff) 0x00 else 0xff;
next_canvas[y][x] = onoff;
var rect = c.SDL_Rect{
.x = @intCast(c_int, x * 2),
.y = @intCast(c_int, y * 2),
.w = 2,
.h = 2,
};
var rv = c.SDL_FillRect(surface, &rect, c.SDL_MapRGB(surface.*.format, rgb, rgb, rgb));
if (rv != 0) {
warn("Failed to fill rect: {}\n", .{c.SDL_GetError()});
return ErrorSet.SDLError;
}
}
}
current_canvas = next_canvas;
if (c.SDL_UpdateWindowSurface(window) != 0) {
warn("Failed to update window surface: {}\n", .{c.SDL_GetError()});
return ErrorSet.SDLError;
}
c.SDL_Delay(100);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment