From f219f0c5ce65f96051af3eafa9e1a9f5628609af Mon Sep 17 00:00:00 2001 From: Squibid Date: Tue, 23 Dec 2025 12:39:16 -0500 Subject: [PATCH] switch to zig build system and add conways game of life --- .gitignore | 2 + .gitmodules | 9 ---- build.zig | 81 ++++++++++++++++++++++++++++ build.zig.zon | 20 +++++++ include/subcmds.h | 1 + lib/cargs | 1 - lib/ds | 1 - lib/log.c | 1 - meson.build | 60 --------------------- src/main.c | 1 + src/subcmds/clock.c | 2 +- src/subcmds/games.zig | 121 ++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 227 insertions(+), 73 deletions(-) delete mode 100644 .gitmodules create mode 100644 build.zig create mode 100644 build.zig.zon delete mode 160000 lib/cargs delete mode 160000 lib/ds delete mode 160000 lib/log.c delete mode 100644 meson.build create mode 100644 src/subcmds/games.zig diff --git a/.gitignore b/.gitignore index f5341b5..cac4223 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ compile_commands.json .cache +.zig-cache +zig-out diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index f246ab5..0000000 --- a/.gitmodules +++ /dev/null @@ -1,9 +0,0 @@ -[submodule "lib/log.c"] - path = lib/log.c - url = https://github.com/rxi/log.c -[submodule "lib/ds"] - path = lib/ds - url = https://git.squi.bid/squibid/ds -[submodule "lib/cargs"] - path = lib/cargs - url = https://github.com/likle/cargs diff --git a/build.zig b/build.zig new file mode 100644 index 0000000..234e844 --- /dev/null +++ b/build.zig @@ -0,0 +1,81 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + const ds = b.dependency("ds", .{}); + const cargs = b.dependency("cargs", .{}); + const log = b.dependency("log.c", .{}); + + const exe = b.addExecutable(.{ + .name = "wom", + .root_module = b.createModule(.{ + .target = target, + .optimize = optimize, + .link_libc = true, + }), + }); + + const games = b.addLibrary(.{ + .name = "games", + .linkage = .static, + .root_module = b.createModule(.{ + .root_source_file = b.path("src/subcmds/games.zig"), + .target = target, + .optimize = optimize, + .link_libc = true, + }), + }); + games.pie = true; + + exe.root_module.addCSourceFiles(.{ + .files = &.{ + "src/main.c", + "src/conf.c", + "src/api.c", + + "src/subcmds/clock.c", + "src/subcmds/dev.c", + "src/subcmds/motd.c", + "src/subcmds/project.c", + "src/subcmds/subcmds.c", + + "src/lua/wom.c", + "src/lua/wom_fs.c", + }, + .flags = &.{ + "-DVERSION=\"hi\"", + "-std=c23", + "-D_GNU_SOURCE", + "-MJ compile_commands.json", + } + }); + + exe.root_module.linkLibrary(games); + exe.root_module.linkSystemLibrary("lua", .{}); + + exe.root_module.addIncludePath(b.path("include")); + exe.root_module.addLibraryPath(ds.path(".")); + exe.root_module.addLibraryPath(cargs.path("src")); + exe.root_module.addLibraryPath(log.path("src")); + + exe.addCSourceFile(.{ .file = ds.builder.path("./ds.c") }); + exe.addCSourceFile(.{ .file = cargs.builder.path("src/cargs.c") }); + exe.addCSourceFile(.{ .file = log.builder.path("./src/log.c") }); + + exe.root_module.addIncludePath(ds.path(".")); + exe.root_module.addIncludePath(cargs.path("include")); + exe.root_module.addIncludePath(log.path("src")); + b.installArtifact(exe); + + const run_cmd = b.addRunArtifact(exe); + run_cmd.step.dependOn(b.getInstallStep()); + + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/build.zig.zon b/build.zig.zon new file mode 100644 index 0000000..497007f --- /dev/null +++ b/build.zig.zon @@ -0,0 +1,20 @@ +.{ + .name = .womblic, + .version = "0.15.2", + .dependencies = .{ + .ds = .{ + .url = "git+https://git.squi.bid/squibid/ds#758edf9d3049c61aa0036c8239f9fa922905a387", + .hash = "N-V-__8AALpEAACaGIC6yceiHvUlUJ-DX3QMaZ9I6uiDgclh", + }, + .cargs = .{ + .url = "git+https://github.com/likle/cargs#0698c3f90333446d0fc2745c1e9ce10dd4a9497a", + .hash = "N-V-__8AAPD5AQDYgLFfeI5K_q70qlurwjhY_e403fseMs3O", + }, + .@"log.c" = .{ + .url = "git+https://github.com/rxi/log.c#f9ea34994bd58ed342d2245cd4110bb5c6790153", + .hash = "N-V-__8AAJ8jAAAVkKD-RFvNLcnmi3SJZWigTFePQTb0sG-u", + }, + }, + .paths = .{""}, + .fingerprint = 0x9cc5d26802316aa6, +} diff --git a/include/subcmds.h b/include/subcmds.h index e99c66d..a2ec9c0 100644 --- a/include/subcmds.h +++ b/include/subcmds.h @@ -9,4 +9,5 @@ void timer_subcmd(void *, int argc, char *argv[]); void stopwatch_subcmd(void *, int argc, char *argv[]); void subcmds_dev(void *, int argc, char *argv[]); void motd_subcmd(void *, int argc, char *argv[]); +void games_subcmd(void *, int argc, char *argv[]); void subcmds_subcmd(void *, int argc, char *argv[]); diff --git a/lib/cargs b/lib/cargs deleted file mode 160000 index 0698c3f..0000000 --- a/lib/cargs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0698c3f90333446d0fc2745c1e9ce10dd4a9497a diff --git a/lib/ds b/lib/ds deleted file mode 160000 index 5e4ae41..0000000 --- a/lib/ds +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5e4ae41113e63004bd131010853e5265b31302d3 diff --git a/lib/log.c b/lib/log.c deleted file mode 160000 index f9ea349..0000000 --- a/lib/log.c +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f9ea34994bd58ed342d2245cd4110bb5c6790153 diff --git a/meson.build b/meson.build deleted file mode 100644 index eebb62b..0000000 --- a/meson.build +++ /dev/null @@ -1,60 +0,0 @@ -project('womblic', 'c', - version: '0.0.1', - license: 'GPLv3') - -add_project_arguments([ - '-DVERSION="@0@"'.format(meson.project_version()), - '-DLOG_USE_COLOR' # enable colored logs -], language: 'c') - -# get all the source files for the executable -luafiles = files( - 'src/lua/wom.c', - 'src/lua/wom_fs.c' -) - -subcmds = files( - 'src/subcmds/clock.c', - 'src/subcmds/dev.c', - 'src/subcmds/motd.c', - 'src/subcmds/project.c', - 'src/subcmds/subcmds.c', -) - -srcfiles = files( - 'src/main.c', - 'src/api.c', - 'src/conf.c' -) + luafiles + subcmds - -cc = meson.get_compiler('c') -math_dep = cc.find_library('m', required: true) - -# build the executable -executable('wom', srcfiles, - dependencies: [ - dependency('lua', version: '>=5.1 <6.0'), - math_dep, - ], - include_directories: [ - include_directories('include'), - - include_directories('lib/log.c/src'), - include_directories('lib/ds'), - include_directories('lib/cargs/include'), - ], - link_with: [ - static_library('ds', 'lib/ds/ds.c', - include_directories: 'lib/ds'), - - static_library('log.c', 'lib/log.c/src/log.c', - include_directories: 'lib/log.c/src'), - - static_library('cargs', 'lib/cargs/src/cargs.c', - include_directories: 'lib/cargs/include'), - ], - install: true -) -install_data('completions/_wom.zsh', - install_dir: '/usr/local/share/zsh/site-functions/' -) diff --git a/src/main.c b/src/main.c index 3e820dc..999ce5a 100644 --- a/src/main.c +++ b/src/main.c @@ -100,6 +100,7 @@ main(int argc, char *argv[]) register_subcmd("stopwatch", stopwatch_subcmd, NULL); register_subcmd("subcmds", subcmds_subcmd, NULL); register_subcmd("dev", subcmds_dev, NULL); + register_subcmd("games", games_subcmd, NULL); /* if the user didn't specify a config path */ if (!config_path) { diff --git a/src/subcmds/clock.c b/src/subcmds/clock.c index 8403bf9..bbe006c 100644 --- a/src/subcmds/clock.c +++ b/src/subcmds/clock.c @@ -344,7 +344,7 @@ stopwatch_subcmd(void *, int argc, char *argv[]) if (pfd.revents & POLLIN) { read(pfd.fd, buf, PATH_MAX); - ds_dll_insert(laps, (void *)(long)i); + ds_dll_append(laps, (void *)(long)i); up++; } diff --git a/src/subcmds/games.zig b/src/subcmds/games.zig new file mode 100644 index 0000000..7f30f85 --- /dev/null +++ b/src/subcmds/games.zig @@ -0,0 +1,121 @@ +const std = @import("std"); +const gpa = std.heap.page_allocator; + +const Conway = struct { + generation: u64 = 0, + width: u64, + height: u64, + world: [][]*Cell, + + const Cell = struct { + /// storage of neighbors + /// ? 0 ? + /// 1 x 2 + /// ? 3 ? + /// instead of storing all 8 neighbors I've decided to contact them + /// through our other neighbors. + neighbors: [4]?*Cell = .{ null, null, null, null }, + /// the state on the current generation + alive: bool = false, + /// the state on the next generation + will_live: bool = false, + }; + + pub fn init(width: u64, height: u64) !Conway { + var self: Conway = .{ + .width = width, + .height = height, + .world = undefined, + }; + + // create the world and the cells + self.world = try gpa.alloc([]*Cell, width); + for (self.world, 0..) |col, i| { + self.world[i] = try gpa.alloc(*Cell, height); + for (col, 0..) |_, j| { + if (j >= height) break; + self.world[i][j] = try gpa.create(Cell); + } + } + + // initialize all the cell properties + for (self.world, 0..) |col, i| for (col, 0..) |cell, j| { + // the top row has nothing above it + cell.neighbors[0] = if (j == 0) null else self.world[i][j - 1]; + // the left column has nothing on the left + cell.neighbors[1] = if (i == 0) null else self.world[i - 1][j]; + // the right row has nothing on the right + cell.neighbors[2] = if (i == width - 1) null else self.world[i + 1][j]; + // the bottom row has nothing below it + cell.neighbors[3] = if (j == height - 1) null else self.world[i][j + 1]; + cell.alive = false; + }; + + return self; + } + + pub fn step(self: *Conway) void { + for (self.world) |col| for (col) |cell| { + var alive_neighbors: u4 = 0; + + // count the neighbors + for (cell.neighbors, 0..) |n, i| { + if (n == null) continue; + if (i == 0 or i == 3) { + if (n.?.neighbors[1]) |nn| if (nn.alive) { + alive_neighbors += 1; + }; + if (n.?.neighbors[2]) |nn| if (nn.alive) { + alive_neighbors += 1; + }; + } + if (n.?.alive) alive_neighbors += 1; + } + + // rules + if (cell.alive) { + cell.will_live = switch (alive_neighbors) { + 2, 3 => true, + else => false + }; + } else if (alive_neighbors == 3) cell.will_live = true; + }; + + for (self.world) |col| for (col) |cell| { + cell.alive = cell.will_live; + }; + } + + pub fn print(self: *Conway) void { + for (self.world) |col| { + for (col) |cell| { + std.debug.print("{s}", .{if (cell.alive) "x" else " "}); + } + std.debug.print("\n", .{}); + } + } +}; + +pub export fn games_subcmd(_: *anyopaque, argc: c_int, argv: [*c]u8) callconv(.c) void { + _ = argc; + _ = argv; + + var con = Conway.init(40, 40) catch unreachable; + con.world[4][2].alive = true; + con.world[4][3].alive = true; + con.world[4][4].alive = true; + con.world[4][5].alive = true; + con.world[4][6].alive = true; + con.world[4][7].alive = true; + con.world[5][2].alive = true; + con.world[5][3].alive = true; + con.world[5][4].alive = true; + con.world[5][5].alive = true; + con.world[5][6].alive = true; + + while (true) : (con.step()) { + con.print(); + std.posix.nanosleep(0, 250000000); + std.debug.print("\x1B[{}A", .{con.height}); + } +}