From 6d7c4d8b7474d3b08bb265cbaa9798518433a6b2 Mon Sep 17 00:00:00 2001 From: geemili Date: Thu, 29 Feb 2024 13:40:43 -0700 Subject: [PATCH] feat: marking cards no longer clogs the undo history --- src/main.zig | 49 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/src/main.zig b/src/main.zig index c2c96bd..0a63850 100644 --- a/src/main.zig +++ b/src/main.zig @@ -11,9 +11,20 @@ const Response = union(enum) { page: Element, transition: struct { game_state: GameState, - can_undo: bool, + history_type: HistoryType, reset_selection: bool = false, }, + + pub const HistoryType = enum { + /// This game state should act as the start of history, and all previous history should + /// be removed. + start, + /// This game state shouldn't be added to the history. + transient, + /// This game state should be added to the history, as a point in time that can be reverted + /// to. + important, + }; }; const GameState = struct { @@ -204,6 +215,7 @@ pub fn main() !void { history.deinit(); } try history.append(try GameState.init(gpa.allocator(), std.crypto.random.int(u64), 1)); + var history_type = Response.HistoryType.start; var root_element: ?Element = null; var response_arena = std.heap.ArenaAllocator.init(gpa.allocator()); @@ -312,6 +324,7 @@ pub fn main() !void { if (input_state.undo and history.items.len > 1) { var discarded_state = history.pop(); + history_type = .important; discarded_state.deinit(); root_element = null; hovered_action = null; @@ -369,13 +382,25 @@ pub fn main() !void { if (transition.reset_selection) { hovered_action = null; } - if (!transition.can_undo) { - for (history.items) |*state| { - state.deinit(); - } - history.clearRetainingCapacity(); + const new_game_state = try transition.game_state.clone(gpa.allocator()); + if (history_type == .transient) { + var transient_state = history.pop(); + transient_state.deinit(); } - try history.append(try transition.game_state.clone(gpa.allocator())); + switch (transition.history_type) { + .start => { + for (history.items) |*state| { + state.deinit(); + } + history.clearRetainingCapacity(); + try history.append(new_game_state); + }, + .important => try history.append(new_game_state), + .transient => { + try history.append(new_game_state); + }, + } + history_type = transition.history_type; if (request_command) |command| gpa.allocator().free(command); request_command = null; @@ -1021,7 +1046,7 @@ fn drawCardHandler(arena: std.mem.Allocator, request: Request) HandlerError!Resp new_game_state.handler = &playerTurnHandler; return Response{ .transition = .{ .game_state = new_game_state, - .can_undo = false, + .history_type = .start, } }; } else if (std.mem.eql(u8, command, "draw discard_pile")) { var new_game_state = try request.game_state.clone(arena); @@ -1029,7 +1054,7 @@ fn drawCardHandler(arena: std.mem.Allocator, request: Request) HandlerError!Resp new_game_state.handler = &playerTurnHandler; return Response{ .transition = .{ .game_state = new_game_state, - .can_undo = true, + .history_type = .important, } }; } } @@ -1085,7 +1110,7 @@ fn playerTurnHandler(arena: std.mem.Allocator, request: Request) HandlerError!Re return Response{ .transition = .{ .game_state = new_game_state, - .can_undo = true, + .history_type = .transient, .reset_selection = false, } }; } else if (std.mem.eql(u8, command, "discard")) { @@ -1109,7 +1134,7 @@ fn playerTurnHandler(arena: std.mem.Allocator, request: Request) HandlerError!Re return Response{ .transition = .{ .game_state = new_game_state, - .can_undo = true, + .history_type = .important, .reset_selection = false, } }; } @@ -1165,7 +1190,7 @@ fn endOfTurnConfirmHandler(arena: std.mem.Allocator, request: Request) HandlerEr return Response{ .transition = .{ .game_state = new_game_state, - .can_undo = false, + .history_type = .start, } }; } }