diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/frontend/ncurses.zig | 4 | ||||
-rw-r--r-- | src/frontend/stub.zig | 57 | ||||
-rw-r--r-- | src/main.zig | 43 | ||||
-rw-r--r-- | src/root.zig | 2 | ||||
-rw-r--r-- | src/run.zig | 93 |
5 files changed, 168 insertions, 31 deletions
diff --git a/src/frontend/ncurses.zig b/src/frontend/ncurses.zig index fd58cf1..d9b99fe 100644 --- a/src/frontend/ncurses.zig +++ b/src/frontend/ncurses.zig @@ -239,8 +239,7 @@ pub const IO = struct { pub fn init(allocator: std.mem.Allocator) !IOInterface { _ = locale.setlocale(locale.LC_ALL, ""); - const io_ptr = try allocator.alloc(IO, 1); - var io = &io_ptr[0]; + var io = try allocator.create(IO); io.allocator = allocator; io.inst = null; io.msgs = null; @@ -292,5 +291,6 @@ pub const IO = struct { pub fn deinit(self: *IO) void { self.deleteWindows(); _ = ncurses.endwin(); + self.allocator.destroy(self); } }; diff --git a/src/frontend/stub.zig b/src/frontend/stub.zig new file mode 100644 index 0000000..d6e7fc8 --- /dev/null +++ b/src/frontend/stub.zig @@ -0,0 +1,57 @@ +const std = @import("std"); +const Action = @import("../actions.zig").Action; +const IOInterface = @import("io_interface.zig").IOInterface; + +pub const ActionStack = struct { + stream: std.ArrayList(Action), + + pub fn init(allocator: std.mem.Allocator) ActionStack { + return ActionStack{ + .stream = std.ArrayList(Action).init(allocator), + }; + } + + pub fn deinit(self: *ActionStack) void { + self.stream.deinit(); + } + + pub fn scheduleAction(self: *ActionStack, action: Action) !void { + try self.stream.append(action); + } + + pub fn next(self: *ActionStack) ?Action { + return self.stream.popOrNull(); + } +}; + +pub const IO = struct { + allocator: std.mem.Allocator, + as: ActionStack, + out_as: ActionStack, + + pub fn displayMessage(self: *IO, str: []const u8) anyerror!void { + _ = self; + std.log.info("{s}\n", .{str}); + } + + pub fn waitForTick(self: *IO) anyerror!Action { + const a = self.as.next() orelse return error.NoAvailableAction; + + try self.out_as.scheduleAction(a); + + return a; + } + + pub fn init(allocator: std.mem.Allocator, as: ActionStack) !IOInterface { + var io = try allocator.create(IO); + io.allocator = allocator; + io.as = as; + io.out_as = ActionStack.init(allocator); + return IOInterface.init(io); + } + + pub fn deinit(self: *IO) void { + self.out_as.deinit(); + self.allocator.destroy(self); + } +}; diff --git a/src/main.zig b/src/main.zig index f55935d..9584038 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,38 +1,23 @@ const std = @import("std"); const IO = @import("frontend/ncurses.zig").IO; -const Action = @import("actions.zig").Action; +const run = @import("run.zig"); -fn run(allocator: std.mem.Allocator) !void { - var io = try IO.init(allocator); - defer { - io.deinit(); - } - - try io.displayMessage("Initialized"); - - var action = Action.illegal; - var tick_count: usize = 0; - while (action != Action.exit) { - const str = try std.fmt.allocPrint(allocator, "{}", .{tick_count}); - defer allocator.free(str); - try io.displayMessage(str); +pub fn main() u8 { + var status: u8 = 0; - action = try io.waitForTick(); - switch (action) { - Action.tick => { - tick_count += 1; - }, - else => {}, + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + const allocator = gpa.allocator(); + defer { + const deinit_status = gpa.deinit(); + if (deinit_status == .leak) { + status = 1; } } -} -pub fn main() u8 { - var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - const allocator = gpa.allocator(); - run(allocator) catch { - return 1; - }; + var io = IO.init(allocator) catch return 1; + defer io.deinit(); + + run.run(allocator, &io) catch return 1; - return 0; + return status; } diff --git a/src/root.zig b/src/root.zig index 330b6ba..60a4df4 100644 --- a/src/root.zig +++ b/src/root.zig @@ -3,8 +3,10 @@ const testing = std.testing; const component = @import("ecs/component.zig"); const ecs = @import("ecs/ecs.zig"); +const run = @import("run.zig"); test { _ = component; _ = ecs; + _ = run; } diff --git a/src/run.zig b/src/run.zig new file mode 100644 index 0000000..e20d9b5 --- /dev/null +++ b/src/run.zig @@ -0,0 +1,93 @@ +const std = @import("std"); +const stub = @import("frontend/stub.zig"); +const IO = @import("frontend/io_interface.zig").IOInterface; +const Action = @import("actions.zig").Action; + +pub fn run(allocator: std.mem.Allocator, io: *IO) !void { + try io.displayMessage("Initialized"); + + var action = Action.illegal; + var tick_count: usize = 0; + while (action != Action.exit) { + const str = try std.fmt.allocPrint(allocator, "{}", .{tick_count}); + defer allocator.free(str); + try io.displayMessage(str); + + action = try io.waitForTick(); + switch (action) { + Action.tick => { + tick_count += 1; + }, + else => {}, + } + } +} + +test "can run game" { + const allocator = std.testing.allocator; + + var as = stub.ActionStack.init(allocator); + defer as.deinit(); + + var io = try stub.IO.init(allocator, as); + defer io.deinit(); + + var res: ?anyerror = null; + run(allocator, &io) catch |err| { + res = err; + }; + try std.testing.expect(res != null); + try std.testing.expectEqual(error.NoAvailableAction, res.?); +} + +test "game exits on Action.exit" { + const allocator = std.testing.allocator; + + var as = stub.ActionStack.init(allocator); + defer as.deinit(); + try as.scheduleAction(Action.exit); + + var io = try stub.IO.init(allocator, as); + defer io.deinit(); + + try run(allocator, &io); + const io_obj: *const stub.IO = @ptrCast(@alignCast(io.ptr)); + var actions = io_obj.out_as; + + const act = actions.next().?; + try std.testing.expectEqual(Action.exit, act); +} + +test "game processes stream of actions" { + const allocator = std.testing.allocator; + + var as = stub.ActionStack.init(allocator); + defer as.deinit(); + + try as.scheduleAction(Action.exit); + try as.scheduleAction(Action.move_right); + try as.scheduleAction(Action.move_left); + try as.scheduleAction(Action.move_down); + try as.scheduleAction(Action.move_up); + try as.scheduleAction(Action.tick); + + var io = try stub.IO.init(allocator, as); + defer io.deinit(); + + try run(allocator, &io); + const io_obj: *const stub.IO = @ptrCast(@alignCast(io.ptr)); + var actions = io_obj.out_as; + + var act = actions.next().?; + try std.testing.expectEqual(Action.exit, act); + act = actions.next().?; + try std.testing.expectEqual(Action.move_right, act); + act = actions.next().?; + try std.testing.expectEqual(Action.move_left, act); + act = actions.next().?; + try std.testing.expectEqual(Action.move_down, act); + act = actions.next().?; + try std.testing.expectEqual(Action.move_up, act); + act = actions.next().?; + try std.testing.expectEqual(Action.tick, act); +} |