feat: marking cards no longer clogs the undo history

dev
LeRoyce Pearson 2024-02-29 13:40:43 -07:00
parent a14e5c3839
commit 6d7c4d8b74
1 changed files with 37 additions and 12 deletions

View File

@ -11,9 +11,20 @@ const Response = union(enum) {
page: Element, page: Element,
transition: struct { transition: struct {
game_state: GameState, game_state: GameState,
can_undo: bool, history_type: HistoryType,
reset_selection: bool = false, 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 { const GameState = struct {
@ -204,6 +215,7 @@ pub fn main() !void {
history.deinit(); history.deinit();
} }
try history.append(try GameState.init(gpa.allocator(), std.crypto.random.int(u64), 1)); 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 root_element: ?Element = null;
var response_arena = std.heap.ArenaAllocator.init(gpa.allocator()); 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) { if (input_state.undo and history.items.len > 1) {
var discarded_state = history.pop(); var discarded_state = history.pop();
history_type = .important;
discarded_state.deinit(); discarded_state.deinit();
root_element = null; root_element = null;
hovered_action = null; hovered_action = null;
@ -369,13 +382,25 @@ pub fn main() !void {
if (transition.reset_selection) { if (transition.reset_selection) {
hovered_action = null; hovered_action = null;
} }
if (!transition.can_undo) { const new_game_state = try transition.game_state.clone(gpa.allocator());
if (history_type == .transient) {
var transient_state = history.pop();
transient_state.deinit();
}
switch (transition.history_type) {
.start => {
for (history.items) |*state| { for (history.items) |*state| {
state.deinit(); state.deinit();
} }
history.clearRetainingCapacity(); history.clearRetainingCapacity();
try history.append(new_game_state);
},
.important => try history.append(new_game_state),
.transient => {
try history.append(new_game_state);
},
} }
try history.append(try transition.game_state.clone(gpa.allocator())); history_type = transition.history_type;
if (request_command) |command| gpa.allocator().free(command); if (request_command) |command| gpa.allocator().free(command);
request_command = null; request_command = null;
@ -1021,7 +1046,7 @@ fn drawCardHandler(arena: std.mem.Allocator, request: Request) HandlerError!Resp
new_game_state.handler = &playerTurnHandler; new_game_state.handler = &playerTurnHandler;
return Response{ .transition = .{ return Response{ .transition = .{
.game_state = new_game_state, .game_state = new_game_state,
.can_undo = false, .history_type = .start,
} }; } };
} else if (std.mem.eql(u8, command, "draw discard_pile")) { } else if (std.mem.eql(u8, command, "draw discard_pile")) {
var new_game_state = try request.game_state.clone(arena); 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; new_game_state.handler = &playerTurnHandler;
return Response{ .transition = .{ return Response{ .transition = .{
.game_state = new_game_state, .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 = .{ return Response{ .transition = .{
.game_state = new_game_state, .game_state = new_game_state,
.can_undo = true, .history_type = .transient,
.reset_selection = false, .reset_selection = false,
} }; } };
} else if (std.mem.eql(u8, command, "discard")) { } 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 = .{ return Response{ .transition = .{
.game_state = new_game_state, .game_state = new_game_state,
.can_undo = true, .history_type = .important,
.reset_selection = false, .reset_selection = false,
} }; } };
} }
@ -1165,7 +1190,7 @@ fn endOfTurnConfirmHandler(arena: std.mem.Allocator, request: Request) HandlerEr
return Response{ .transition = .{ return Response{ .transition = .{
.game_state = new_game_state, .game_state = new_game_state,
.can_undo = false, .history_type = .start,
} }; } };
} }
} }