feat(gameoflife): allow for variations to game of life

This commit is contained in:
RadsammyT 2026-08-14 23:33:04 -04:00
commit da07a9e607
No known key found for this signature in database
4 changed files with 37 additions and 5 deletions

View file

@ -287,6 +287,18 @@ gameoflife_frame_delay = 6
# 0.7+ -> Dense, chaotic patterns
gameoflife_initial_density = 0.4
# Sets the multiple amounts of neighbors needed for a cell to survive.
# Each numerical digit from 0 to 8 inclusive in this string becomes
# one of the targets required for this cell to survive.
# Example: a string of "23" makes the cell survive on 2 or 3 neighbors
gameoflife_param_survival = "23"
# Sets the multiple amounts of neighbors needed for a cell to be born.
# Each numerical digit from 0 to 8 inclusive in this string becomes
# one of the targets required for this cell to be born.
# Example: a string of "3" makes the cell be born on 3 neighbors
gameoflife_param_birth = "3"
# Remove main box borders
hide_borders = false

View file

@ -39,6 +39,11 @@ animation_frame_delay: u16,
dead_cell: Cell,
width: usize,
height: usize,
// Where N is the amount of neighbors, determines if the cell can survive/be born
// by checking if the Nth bit (where if N == 0, it is the least significant bit,
// or 2 to the power of 0) is set to 1.
cell_survival: u9,
cell_birth: u9,
pub fn init(
allocator: Allocator,
@ -50,6 +55,8 @@ pub fn init(
animate: *bool,
timeout_sec: u12,
animation_frame_delay: u16,
string_cell_survival: []const u8,
string_cell_birth: []const u8,
) !GameOfLife {
const width = terminal_buffer.width;
const height = terminal_buffer.height;
@ -77,6 +84,16 @@ pub fn init(
.dead_cell = .{ .ch = DEAD_CHAR, .fg = @intCast(TerminalBuffer.Color.DEFAULT), .bg = terminal_buffer.bg },
.width = width,
.height = height,
.cell_birth = 0,
.cell_survival = 0,
};
for (string_cell_survival) |c| switch (c) {
'0'...'8' => game.cell_survival |= (@as(u9, 1) << @truncate(@as(u9, c - '0'))),
else => {},
};
for (string_cell_birth) |c| switch (c) {
'0'...'8' => game.cell_birth |= (@as(u9, 1) << @truncate(@as(u9, c - '0'))),
else => {},
};
// Initialize grid
@ -173,11 +190,10 @@ fn updateGeneration(self: *GameOfLife) void {
const is_alive = self.current_grid[index];
// Optimized rule application
self.next_grid[index] = switch (neighbors) {
2 => is_alive,
3 => true,
else => false,
};
self.next_grid[index] = if (is_alive)
self.cell_survival & (@as(u9, 1) << @truncate(neighbors)) != 0
else
self.cell_birth & (@as(u9, 1) << @truncate(neighbors)) != 0;
}
}

View file

@ -64,6 +64,8 @@ gameoflife_fg: u32 = 0x0000FF00,
gameoflife_entropy_interval: usize = 10,
gameoflife_frame_delay: usize = 6,
gameoflife_initial_density: f32 = 0.4,
gameoflife_param_birth: []const u8 = "3",
gameoflife_param_survival: []const u8 = "23",
hide_borders: bool = false,
inactivity_cmd: ?[]const u8 = null,
inactivity_delay: u16 = 0,

View file

@ -1063,6 +1063,8 @@ pub fn main(init: std.process.Init) !void {
&state.animate,
state.config.animation_timeout_sec,
state.config.animation_frame_delay,
state.config.gameoflife_param_survival,
state.config.gameoflife_param_birth,
);
animation = game_of_life.widget();
},