Last active
April 8, 2021 02:10
-
-
Save ltriant/c2aed6babaacc3679eabb681720eadfe to your computer and use it in GitHub Desktop.
Conway's Game of Life in Zig
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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(¤t_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