diff --git a/res/config.ini b/res/config.ini index 2bd2624..1461a92 100644 --- a/res/config.ini +++ b/res/config.ini @@ -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 diff --git a/src/animations/GameOfLife.zig b/src/animations/GameOfLife.zig index 6e9a16c..9541e78 100644 --- a/src/animations/GameOfLife.zig +++ b/src/animations/GameOfLife.zig @@ -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; } } diff --git a/src/config/Config.zig b/src/config/Config.zig index 2ba8444..946dfae 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -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, diff --git a/src/main.zig b/src/main.zig index 1d0db99..8b16e59 100644 --- a/src/main.zig +++ b/src/main.zig @@ -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(); },