Compare commits

...

10 Commits

4 changed files with 182 additions and 84 deletions

View File

@ -0,0 +1,6 @@
on: [push]
jobs:
test:
runs-on: docker
steps:
- run: echo All Good

View File

@ -29,6 +29,19 @@ pub fn build(b: *std.Build) void {
exe.root_module.addImport("seizer", seizer.module("seizer")); exe.root_module.addImport("seizer", seizer.module("seizer"));
b.installArtifact(exe); b.installArtifact(exe);
// additionally generate an HTML file with the wasm module embedded when we use the wasi target
if (target.result.os.tag == .wasi) {
exe.wasi_exec_model = .reactor;
const bundle_webpage_exe = seizer.artifact("bundle-webpage");
const bundle_webpage = b.addRunArtifact(bundle_webpage_exe);
bundle_webpage.addArtifactArg(exe);
const install_html = b.addInstallFile(bundle_webpage.captureStdOut(), "www/seizer-solitaire.html");
b.getInstallStep().dependOn(&install_html.step);
}
const run_cmd = b.addRunArtifact(exe); const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep()); run_cmd.step.dependOn(b.getInstallStep());

View File

@ -16,8 +16,8 @@
// internet connectivity. // internet connectivity.
.dependencies = .{ .dependencies = .{
.seizer = .{ .seizer = .{
.url = "https://github.com/leroycep/seizer/archive/5dcad668e4b9f873060cbaccaf8a4a1c2f4f0bc8.tar.gz", .url = "https://github.com/leroycep/seizer/archive/54a39bf2c2f867a2caa69c4a63fa4732ebc7ac71.tar.gz",
.hash = "122041f3ceeb4198fcef9edd8c4c377852ab540c94428397dd35236883f4e40b0b9a", .hash = "12208d8ee636719b6b4fbb75014cfaa9aa0d9557d2ca4e160ad245825eaa20849b48",
}, },
}, },
.paths = .{ .paths = .{

View File

@ -1,8 +1,9 @@
pub const main = seizer.main; pub const main = seizer.main;
var gpa: std.mem.Allocator = undefined; const APPNAME = "seizer-solitaire";
var prng: std.rand.DefaultPrng = undefined; var prng: std.rand.DefaultPrng = undefined;
var window_global: *seizer.Window = undefined; var window_global: seizer.Window = undefined;
var canvas: seizer.Canvas = undefined; var canvas: seizer.Canvas = undefined;
var card_tilemap: ?DeckSprites = null; var card_tilemap: ?DeckSprites = null;
@ -30,88 +31,121 @@ const MENU_ITEMS = [_][]const u8{
"Quit", "Quit",
}; };
var app_data_dir: std.fs.Dir = undefined; var win_count: ?u32 = null;
var win_count_file: std.fs.File = undefined;
var win_count: u32 = 0;
var win_triggered: bool = false; var win_triggered: bool = false;
var frame_count: u64 = 0;
pub fn init(context: *seizer.Context) !void { pub fn init() !void {
gpa = context.gpa;
prng = std.rand.DefaultPrng.init(@bitCast(std.time.timestamp())); prng = std.rand.DefaultPrng.init(@bitCast(std.time.timestamp()));
window_global = try context.createWindow(.{ window_global = try seizer.platform.createWindow(.{
.title = "Seizer Solitaire", .title = "Seizer Solitaire",
.on_render = render, .on_render = render,
.on_destroy = destroy, .on_destroy = destroy,
}); });
canvas = try seizer.Canvas.init(context.gpa, .{}); canvas = try seizer.Canvas.init(seizer.platform.allocator(), .{});
errdefer canvas.deinit(); errdefer canvas.deinit();
card_tilemap = try assets.loadSolitaireCards(context.gpa); card_tilemap = try assets.loadSolitaireCards(seizer.platform.allocator());
try resetGame(); try resetGame();
try context.addButtonInput(.{ try seizer.platform.addButtonInput(.{
.title = "move_up", .title = "move_up",
.on_event = moveUp, .on_event = moveUp,
.default_bindings = &.{.dpup}, .default_bindings = &.{
.{ .gamepad = .dpup },
.{ .keyboard = .up },
},
}); });
try context.addButtonInput(.{ try seizer.platform.addButtonInput(.{
.title = "move_down", .title = "move_down",
.on_event = moveDown, .on_event = moveDown,
.default_bindings = &.{.dpdown}, .default_bindings = &.{
.{ .gamepad = .dpdown },
.{ .keyboard = .down },
},
}); });
try context.addButtonInput(.{ try seizer.platform.addButtonInput(.{
.title = "move_left", .title = "move_left",
.on_event = moveLeft, .on_event = moveLeft,
.default_bindings = &.{.dpleft}, .default_bindings = &.{
.{ .gamepad = .dpleft },
.{ .keyboard = .left },
},
}); });
try context.addButtonInput(.{ try seizer.platform.addButtonInput(.{
.title = "move_right", .title = "move_right",
.on_event = moveRight, .on_event = moveRight,
.default_bindings = &.{.dpright}, .default_bindings = &.{
.{ .gamepad = .dpright },
.{ .keyboard = .right },
},
}); });
try context.addButtonInput(.{ try seizer.platform.addButtonInput(.{
.title = "select_or_place", .title = "select_or_place",
.on_event = doSelectOrPlace, .on_event = doSelectOrPlace,
.default_bindings = &.{.a}, .default_bindings = &.{
.{ .gamepad = .a },
.{ .keyboard = .z },
},
}); });
try context.addButtonInput(.{ try seizer.platform.addButtonInput(.{
.title = "deselect", .title = "deselect",
.on_event = deselect, .on_event = deselect,
.default_bindings = &.{.b}, .default_bindings = &.{
.{ .gamepad = .b },
.{ .keyboard = .x },
},
}); });
try context.addButtonInput(.{ try seizer.platform.addButtonInput(.{
.title = "toggle_menu", .title = "toggle_menu",
.on_event = toggleMenu, .on_event = toggleMenu,
.default_bindings = &.{.start}, .default_bindings = &.{
.{ .gamepad = .start },
.{ .keyboard = .esc },
},
}); });
try context.addButtonInput(.{ try seizer.platform.addButtonInput(.{
.title = "undo", .title = "undo",
.on_event = undo, .on_event = undo,
.default_bindings = &.{.x}, .default_bindings = &.{
.{ .gamepad = .x },
.{ .keyboard = .a },
},
}); });
const app_data_dir_path = try std.fs.getAppDataDir(gpa, "seizer-solitaire"); const read_buffer = try seizer.platform.allocator().alloc(u8, @sizeOf(u32));
defer gpa.free(app_data_dir_path); seizer.platform.readFile(.{
.appname = APPNAME,
.path = "win_count.bin",
.buffer = read_buffer,
.callback = onWinCountRead,
.userdata = read_buffer.ptr,
});
}
app_data_dir = try std.fs.cwd().makeOpenPath(app_data_dir_path, .{}); fn onWinCountRead(userdata: ?*anyopaque, result: seizer.Platform.FileError![]const u8) void {
win_count_file = try app_data_dir.createFile("win_count.bin", .{ .read = true, .truncate = false }); const buffer: *[4]u8 = @ptrCast(userdata);
defer seizer.platform.allocator().free(buffer);
var win_count_buffer: [4]u8 = undefined; if (result) |bytes| {
const bytes_read = try win_count_file.preadAll(&win_count_buffer, 0); if (bytes.len >= @sizeOf(u32)) {
if (bytes_read < win_count_buffer.len) { win_count = std.mem.readInt(u32, bytes[0..4], .little);
win_count = 0; }
std.mem.writeInt(u32, &win_count_buffer, win_count, .little); } else |_| {}
try win_count_file.pwriteAll(&win_count_buffer, 0); }
} else {
win_count = std.mem.readInt(u32, &win_count_buffer, .little); fn onWinCountWritten(userdata: ?*anyopaque, result: seizer.Platform.FileError!void) void {
} const buffer: *u32 = @ptrCast(@alignCast(userdata));
defer seizer.platform.allocator().destroy(buffer);
_ = result catch {};
} }
fn resetGame() !void { fn resetGame() !void {
draw_pile.deinit(gpa); resetHistory();
draw_pile.deinit(seizer.platform.allocator());
draw_pile_exhausted = false; draw_pile_exhausted = false;
drawn_cards.shrinkRetainingCapacity(0); drawn_cards.shrinkRetainingCapacity(0);
for (&stacks) |*stack| { for (&stacks) |*stack| {
@ -129,13 +163,13 @@ fn resetGame() !void {
selected_deck = null; selected_deck = null;
selected_card = 0; selected_card = 0;
draw_pile = std.ArrayListUnmanaged(Card).fromOwnedSlice(try makeStandardDeck(gpa)); draw_pile = std.ArrayListUnmanaged(Card).fromOwnedSlice(try makeStandardDeck(seizer.platform.allocator()));
prng.random().shuffle(Card, draw_pile.items); prng.random().shuffle(Card, draw_pile.items);
for (&stacks, 0..) |*stack, i| { for (&stacks, 0..) |*stack, i| {
for (0..i + 1) |_| { for (0..i + 1) |_| {
const drawn_card = draw_pile.pop(); const drawn_card = draw_pile.pop();
try stack.append(gpa, drawn_card); try stack.append(seizer.platform.allocator(), drawn_card);
} }
} }
@ -149,31 +183,42 @@ fn resetHistory() void {
history.shrinkRetainingCapacity(0); history.shrinkRetainingCapacity(0);
} }
fn destroy(window: *seizer.Window) void { fn destroy(window: seizer.Window) void {
_ = window; _ = window;
draw_pile.deinit(gpa); for (history.items) |*snapshot| {
drawn_cards.deinit(gpa); snapshot.deinit();
}
history.deinit(seizer.platform.allocator());
draw_pile.deinit(seizer.platform.allocator());
drawn_cards.deinit(seizer.platform.allocator());
for (&stacks) |*stack| { for (&stacks) |*stack| {
stack.deinit(gpa); stack.deinit(seizer.platform.allocator());
} }
for (&foundations) |*foundation| { for (&foundations) |*foundation| {
foundation.deinit(gpa); foundation.deinit(seizer.platform.allocator());
} }
if (card_tilemap) |*ct| { if (card_tilemap) |*ct| {
ct.deinit(gpa); ct.deinit(seizer.platform.allocator());
card_tilemap = null; card_tilemap = null;
} }
canvas.deinit(); canvas.deinit();
} }
fn render(window: *seizer.Window) !void { fn render(window: seizer.Window) !void {
if (haveWon() and !win_triggered) { if (haveWon() and !win_triggered and win_count != null) {
win_count += 1; win_count.? += 1;
var win_count_buffer: [4]u8 = undefined; const win_count_write_buffer = try seizer.platform.allocator().create(u32);
std.mem.writeInt(u32, &win_count_buffer, win_count, .little); std.mem.writeInt(u32, std.mem.asBytes(win_count_write_buffer), win_count.?, .little);
try win_count_file.pwriteAll(&win_count_buffer, 0); seizer.platform.writeFile(.{
.appname = APPNAME,
.path = "win_count.bin",
.data = std.mem.asBytes(win_count_write_buffer),
.callback = onWinCountWritten,
.userdata = win_count_write_buffer,
});
resetHistory(); resetHistory();
win_triggered = true; win_triggered = true;
@ -210,18 +255,39 @@ fn render(window: *seizer.Window) !void {
@floatFromInt(2 * margin + 5 * (margin + tile_size[1])), @floatFromInt(2 * margin + 5 * (margin + tile_size[1])),
}; };
const board_offset = [2]f32{ const board_offset = [2]f32{
(canvas.window_size[0] - space_taken_by_board[0]) / 2, @floor((canvas.window_size[0] - space_taken_by_board[0]) / 2),
(canvas.window_size[1] - space_taken_by_board[1]) / 2, @floor((canvas.window_size[1] - space_taken_by_board[1]) / 2),
}; };
{ if (win_count) |w| {
_ = canvas.printText( _ = canvas.printText(
.{ .{
canvas.window_size[0] - board_offset[0] - marginf - hand_offsetf[0], canvas.window_size[0] - board_offset[0] - marginf - hand_offsetf[0],
board_offset[1] + marginf + hand_offsetf[1], board_offset[1] + marginf + hand_offsetf[1],
}, },
"Win Count: {}", "Win Count: {}",
.{win_count}, .{w},
.{ .@"align" = .right, .scale = scalef },
);
} else {
const throbber_character: u8 = switch ((frame_count / 5) % 8) {
0 => '-',
1 => '\\',
2 => '|',
3 => '/',
4 => '-',
5 => '\\',
6 => '|',
7 => '/',
else => unreachable,
};
_ = canvas.printText(
.{
canvas.window_size[0] - board_offset[0] - marginf - hand_offsetf[0],
board_offset[1] + marginf + hand_offsetf[1],
},
"Win Count: [{c}]",
.{throbber_character},
.{ .@"align" = .right, .scale = scalef }, .{ .@"align" = .right, .scale = scalef },
); );
} }
@ -379,6 +445,8 @@ fn render(window: *seizer.Window) !void {
} }
canvas.end(); canvas.end();
frame_count +%= 1;
} }
pub fn haveWon() bool { pub fn haveWon() bool {
@ -432,7 +500,7 @@ pub fn doSelectOrPlace(pressed: bool) !void {
if (selected_deck == null) { if (selected_deck == null) {
if (hovered_deck == &draw_pile and !draw_pile_exhausted) { if (hovered_deck == &draw_pile and !draw_pile_exhausted) {
resetHistory(); resetHistory();
drawn_cards.ensureUnusedCapacity(gpa, 3) catch return; drawn_cards.ensureUnusedCapacity(seizer.platform.allocator(), 3) catch return;
for (0..3) |_| { for (0..3) |_| {
if (draw_pile.popOrNull()) |card| drawn_cards.appendAssumeCapacity(card); if (draw_pile.popOrNull()) |card| drawn_cards.appendAssumeCapacity(card);
} }
@ -454,7 +522,7 @@ pub fn doSelectOrPlace(pressed: bool) !void {
} }
} }
} else if (hovered_deck == selected_deck) { } else if (hovered_deck == selected_deck) {
const snapshot = try Snapshot.initFromCurrentGlobalState(); var snapshot = try Snapshot.initFromCurrentGlobalState();
const selected_substack = selected_deck.?.items[selected_card..]; const selected_substack = selected_deck.?.items[selected_card..];
// try to move all selected cards into the foundations // try to move all selected cards into the foundations
@ -470,7 +538,7 @@ pub fn doSelectOrPlace(pressed: bool) !void {
const suit_matches = !empty and foundation.items[foundation.items.len - 1].suit == selected_deck.?.items[selected_deck.?.items.len - 1].suit; const suit_matches = !empty and foundation.items[foundation.items.len - 1].suit == selected_deck.?.items[selected_deck.?.items.len - 1].suit;
const is_next_rank = !empty and foundation.items[foundation.items.len - 1].rank + 1 == selected_deck.?.items[selected_deck.?.items.len - 1].rank; const is_next_rank = !empty and foundation.items[foundation.items.len - 1].rank + 1 == selected_deck.?.items[selected_deck.?.items.len - 1].rank;
if ((empty and ace) or (suit_matches and is_next_rank)) { if ((empty and ace) or (suit_matches and is_next_rank)) {
foundation.ensureUnusedCapacity(gpa, 1) catch continue; foundation.ensureUnusedCapacity(seizer.platform.allocator(), 1) catch continue;
foundation.appendAssumeCapacity(selected_deck.?.pop()); foundation.appendAssumeCapacity(selected_deck.?.pop());
hovered_card = if (hovered_deck.? == &drawn_cards) hovered_card = if (hovered_deck.? == &drawn_cards)
@ -487,13 +555,15 @@ pub fn doSelectOrPlace(pressed: bool) !void {
} }
if (cards_moved) { if (cards_moved) {
try history.append(gpa, snapshot); try history.append(seizer.platform.allocator(), snapshot);
} else {
snapshot.deinit();
} }
selected_deck = null; selected_deck = null;
} else { } else {
var cards_moved = false; var cards_moved = false;
const snapshot = try Snapshot.initFromCurrentGlobalState(); var snapshot = try Snapshot.initFromCurrentGlobalState();
if (selected_deck) |selected| move_from_selected_to_hovered: { if (selected_deck) |selected| move_from_selected_to_hovered: {
const selected_substack = selected.items[selected_card..]; const selected_substack = selected.items[selected_card..];
if (selected_substack.len == 0) break :move_from_selected_to_hovered; if (selected_substack.len == 0) break :move_from_selected_to_hovered;
@ -503,7 +573,7 @@ pub fn doSelectOrPlace(pressed: bool) !void {
if (hovered.items.len == 0) { if (hovered.items.len == 0) {
for (stacks[0..]) |*stack| { for (stacks[0..]) |*stack| {
if (hovered != stack) continue; if (hovered != stack) continue;
hovered.ensureUnusedCapacity(gpa, selected_substack.len) catch break :move_from_selected_to_hovered; hovered.ensureUnusedCapacity(seizer.platform.allocator(), selected_substack.len) catch break :move_from_selected_to_hovered;
hovered.appendSliceAssumeCapacity(selected_substack); hovered.appendSliceAssumeCapacity(selected_substack);
selected.shrinkRetainingCapacity(selected.items.len - selected_substack.len); selected.shrinkRetainingCapacity(selected.items.len - selected_substack.len);
hovered_card = indexOfTopOfStack(hovered_deck.?.items); hovered_card = indexOfTopOfStack(hovered_deck.?.items);
@ -513,10 +583,10 @@ pub fn doSelectOrPlace(pressed: bool) !void {
if (selected_substack.len == 1) { if (selected_substack.len == 1) {
if (draw_pile_exhausted and hovered == &draw_pile and draw_pile.items.len == 0) { if (draw_pile_exhausted and hovered == &draw_pile and draw_pile.items.len == 0) {
hovered.ensureUnusedCapacity(gpa, 1) catch break :move_from_selected_to_hovered; hovered.ensureUnusedCapacity(seizer.platform.allocator(), 1) catch break :move_from_selected_to_hovered;
hovered.appendAssumeCapacity(selected_deck.?.pop()); hovered.appendAssumeCapacity(selected_deck.?.pop());
hovered_card = indexOfTopOfStack(hovered_deck.?.items); hovered_card = indexOfTopOfStack(hovered_deck.?.items);
try history.append(gpa, snapshot); cards_moved = true;
break :move_from_selected_to_hovered; break :move_from_selected_to_hovered;
} else for (foundations[0..]) |*foundation| { } else for (foundations[0..]) |*foundation| {
if (foundation != selected) continue; if (foundation != selected) continue;
@ -525,7 +595,7 @@ pub fn doSelectOrPlace(pressed: bool) !void {
const suit_matches = !empty and foundation.items[foundation.items.len - 1].suit == selected_deck.?.items[selected_deck.?.items.len - 1].suit; const suit_matches = !empty and foundation.items[foundation.items.len - 1].suit == selected_deck.?.items[selected_deck.?.items.len - 1].suit;
const is_next_rank = !empty and foundation.items[foundation.items.len - 1].rank + 1 == selected_deck.?.items[selected_deck.?.items.len - 1].rank; const is_next_rank = !empty and foundation.items[foundation.items.len - 1].rank + 1 == selected_deck.?.items[selected_deck.?.items.len - 1].rank;
if ((empty and ace) or (suit_matches and is_next_rank)) { if ((empty and ace) or (suit_matches and is_next_rank)) {
foundation.ensureUnusedCapacity(gpa, 1) catch continue; foundation.ensureUnusedCapacity(seizer.platform.allocator(), 1) catch continue;
foundation.appendAssumeCapacity(selected_deck.?.pop()); foundation.appendAssumeCapacity(selected_deck.?.pop());
hovered_card = indexOfTopOfStack(hovered_deck.?.items); hovered_card = indexOfTopOfStack(hovered_deck.?.items);
cards_moved = true; cards_moved = true;
@ -542,14 +612,16 @@ pub fn doSelectOrPlace(pressed: bool) !void {
{ {
break :move_from_selected_to_hovered; break :move_from_selected_to_hovered;
} }
hovered.ensureUnusedCapacity(gpa, selected_substack.len) catch break :move_from_selected_to_hovered; hovered.ensureUnusedCapacity(seizer.platform.allocator(), selected_substack.len) catch break :move_from_selected_to_hovered;
hovered.appendSliceAssumeCapacity(selected_substack); hovered.appendSliceAssumeCapacity(selected_substack);
selected.shrinkRetainingCapacity(selected.items.len - selected_substack.len); selected.shrinkRetainingCapacity(selected.items.len - selected_substack.len);
hovered_card = indexOfTopOfStack(hovered_deck.?.items); hovered_card = indexOfTopOfStack(hovered_deck.?.items);
cards_moved = true; cards_moved = true;
} }
if (cards_moved) { if (cards_moved) {
try history.append(gpa, snapshot); try history.append(seizer.platform.allocator(), snapshot);
} else {
snapshot.deinit();
} }
selected_deck = null; selected_deck = null;
} }
@ -670,7 +742,7 @@ pub fn moveDown(pressed: bool) !void {
if (!pressed) return; if (!pressed) return;
if (show_menu) { if (show_menu) {
menu_item_selected += 1; menu_item_selected += 1;
menu_item_selected %= MENU_ITEMS.len; menu_item_selected %= @intCast(MENU_ITEMS.len);
} else if (hovered_deck == null) { } else if (hovered_deck == null) {
hovered_deck = &draw_pile; hovered_deck = &draw_pile;
hovered_card = 0; hovered_card = 0;
@ -749,19 +821,19 @@ const Snapshot = struct {
pub fn initFromCurrentGlobalState() !Snapshot { pub fn initFromCurrentGlobalState() !Snapshot {
const snapshot_selected_deck = selected_deck orelse return error.InvalidSelectionForSnapshot; const snapshot_selected_deck = selected_deck orelse return error.InvalidSelectionForSnapshot;
const snapshot_draw_pile = try gpa.dupe(Card, draw_pile.items); const snapshot_draw_pile = try seizer.platform.allocator().dupe(Card, draw_pile.items);
errdefer gpa.free(snapshot_draw_pile); errdefer seizer.platform.allocator().free(snapshot_draw_pile);
const snapshot_drawn_cards = try gpa.dupe(Card, drawn_cards.items); const snapshot_drawn_cards = try seizer.platform.allocator().dupe(Card, drawn_cards.items);
errdefer gpa.free(snapshot_drawn_cards); errdefer seizer.platform.allocator().free(snapshot_drawn_cards);
var snapshot_stacks: [7][]Card = undefined; var snapshot_stacks: [7][]Card = undefined;
for (&snapshot_stacks, &stacks) |*snapshot_stack, stack| { for (&snapshot_stacks, &stacks) |*snapshot_stack, stack| {
snapshot_stack.* = try gpa.dupe(Card, stack.items); snapshot_stack.* = try seizer.platform.allocator().dupe(Card, stack.items);
} }
var snapshot_foundations: [4][]Card = undefined; var snapshot_foundations: [4][]Card = undefined;
for (&snapshot_foundations, &foundations) |*snapshot_foundation, foundation| { for (&snapshot_foundations, &foundations) |*snapshot_foundation, foundation| {
snapshot_foundation.* = try gpa.dupe(Card, foundation.items); snapshot_foundation.* = try seizer.platform.allocator().dupe(Card, foundation.items);
} }
return Snapshot{ return Snapshot{
@ -776,19 +848,25 @@ const Snapshot = struct {
} }
pub fn deinit(snapshot: *@This()) void { pub fn deinit(snapshot: *@This()) void {
gpa.free(snapshot.draw_pile); seizer.platform.allocator().free(snapshot.draw_pile);
gpa.free(snapshot.drawn_cards); seizer.platform.allocator().free(snapshot.drawn_cards);
for (snapshot.stacks) |stack| {
seizer.platform.allocator().free(stack);
}
for (snapshot.foundations) |foundation| {
seizer.platform.allocator().free(foundation);
}
} }
pub fn restore(snapshot: @This()) !void { pub fn restore(snapshot: @This()) !void {
// ensure there is enough space for all the cards // ensure there is enough space for all the cards
try draw_pile.ensureTotalCapacity(gpa, snapshot.draw_pile.len); try draw_pile.ensureTotalCapacity(seizer.platform.allocator(), snapshot.draw_pile.len);
try drawn_cards.ensureTotalCapacity(gpa, snapshot.drawn_cards.len); try drawn_cards.ensureTotalCapacity(seizer.platform.allocator(), snapshot.drawn_cards.len);
for (&snapshot.stacks, &stacks) |snapshot_stack, *stack| { for (&snapshot.stacks, &stacks) |snapshot_stack, *stack| {
try stack.ensureTotalCapacity(gpa, snapshot_stack.len); try stack.ensureTotalCapacity(seizer.platform.allocator(), snapshot_stack.len);
} }
for (&snapshot.foundations, &foundations) |snapshot_foundation, *foundation| { for (&snapshot.foundations, &foundations) |snapshot_foundation, *foundation| {
try foundation.ensureTotalCapacity(gpa, snapshot_foundation.len); try foundation.ensureTotalCapacity(seizer.platform.allocator(), snapshot_foundation.len);
} }
// reset the state // reset the state
@ -821,6 +899,7 @@ const DeckSprites = assets.DeckSprites;
const Card = assets.Card; const Card = assets.Card;
const assets = @import("./assets.zig"); const assets = @import("./assets.zig");
const builtin = @import("builtin");
const seizer = @import("seizer"); const seizer = @import("seizer");
const gl = seizer.gl; const gl = seizer.gl;
const ecs = seizer.flecs; const ecs = seizer.flecs;