feat: mark/unmark cards after drawing

dev
LeRoyce Pearson 2024-02-26 22:24:47 -07:00
parent c5526ba229
commit 2dde105a58
1 changed files with 51 additions and 5 deletions

View File

@ -23,6 +23,8 @@ const GameState = struct {
discard_pile: std.ArrayListUnmanaged(Card), discard_pile: std.ArrayListUnmanaged(Card),
hands: []std.ArrayListUnmanaged(Card), hands: []std.ArrayListUnmanaged(Card),
marked_cards: std.AutoHashMapUnmanaged(Card, void),
pub fn init(allocator: std.mem.Allocator, seed: u64, num_players: usize) !@This() { pub fn init(allocator: std.mem.Allocator, seed: u64, num_players: usize) !@This() {
var draw_pile = std.ArrayListUnmanaged(Card).fromOwnedSlice(try makeStandardDeck(allocator)); var draw_pile = std.ArrayListUnmanaged(Card).fromOwnedSlice(try makeStandardDeck(allocator));
errdefer draw_pile.deinit(allocator); errdefer draw_pile.deinit(allocator);
@ -59,6 +61,7 @@ const GameState = struct {
.draw_pile = draw_pile, .draw_pile = draw_pile,
.discard_pile = discard_pile, .discard_pile = discard_pile,
.hands = hands, .hands = hands,
.marked_cards = .{},
}; };
} }
@ -69,6 +72,7 @@ const GameState = struct {
hand.deinit(this.allocator); hand.deinit(this.allocator);
} }
this.allocator.free(this.hands); this.allocator.free(this.hands);
this.marked_cards.deinit(this.allocator);
} }
pub fn clone(this: @This(), allocator: std.mem.Allocator) !@This() { pub fn clone(this: @This(), allocator: std.mem.Allocator) !@This() {
@ -84,6 +88,7 @@ const GameState = struct {
.draw_pile = try this.draw_pile.clone(allocator), .draw_pile = try this.draw_pile.clone(allocator),
.discard_pile = try this.discard_pile.clone(allocator), .discard_pile = try this.discard_pile.clone(allocator),
.hands = hands, .hands = hands,
.marked_cards = try this.marked_cards.clone(allocator),
}; };
} }
}; };
@ -262,6 +267,9 @@ pub fn main() !void {
history.clearRetainingCapacity(); history.clearRetainingCapacity();
} }
try history.append(try transition.game_state.clone(gpa.allocator())); try history.append(try transition.game_state.clone(gpa.allocator()));
if (request_command) |command| gpa.allocator().free(command);
request_command = null;
}, },
} }
} }
@ -734,13 +742,14 @@ pub const CardElement = struct {
allocator: std.mem.Allocator, allocator: std.mem.Allocator,
visual: Visual, visual: Visual,
command: ?[]const u8, command: ?[]const u8,
marked: bool,
const Visual = union(enum) { const Visual = union(enum) {
back, back,
card: Card, card: Card,
}; };
pub fn create(allocator: std.mem.Allocator, options: struct { visual: Visual, command: ?[]const u8 }) !*@This() { pub fn create(allocator: std.mem.Allocator, options: struct { visual: Visual, command: ?[]const u8, marked: ?bool = null }) !*@This() {
const this = try allocator.create(@This()); const this = try allocator.create(@This());
errdefer allocator.destroy(this); errdefer allocator.destroy(this);
@ -748,6 +757,7 @@ pub const CardElement = struct {
.allocator = allocator, .allocator = allocator,
.visual = options.visual, .visual = options.visual,
.command = options.command, .command = options.command,
.marked = options.marked orelse false,
}; };
return this; return this;
} }
@ -776,24 +786,32 @@ pub const CardElement = struct {
pub fn element_render(pointer: ?*anyopaque, canvas: *seizer.Canvas, render_resources: RenderResources, min: [2]f32, max: [2]f32) void { pub fn element_render(pointer: ?*anyopaque, canvas: *seizer.Canvas, render_resources: RenderResources, min: [2]f32, max: [2]f32) void {
const this: *@This() = @ptrCast(@alignCast(pointer)); const this: *@This() = @ptrCast(@alignCast(pointer));
const mark_offset = if (this.marked)
[2]f32{
0,
@as(f32, @floatFromInt(render_resources.deck.tilesheet.tile_size[1])) * -0.4,
}
else
[2]f32{ 0, 0 };
switch (this.visual) { switch (this.visual) {
.back => render_resources.deck.tilesheet.renderTile( .back => render_resources.deck.tilesheet.renderTile(
canvas, canvas,
render_resources.deck.back, render_resources.deck.back,
.{ min[0], min[1] }, .{ min[0] + mark_offset[0], min[1] + mark_offset[1] },
.{}, .{},
), ),
.card => |card| render_resources.deck.tilesheet.renderTile( .card => |card| render_resources.deck.tilesheet.renderTile(
canvas, canvas,
render_resources.deck.getTileForCard(card), render_resources.deck.getTileForCard(card),
.{ min[0], min[1] }, .{ min[0] + mark_offset[0], min[1] + mark_offset[1] },
.{}, .{},
), ),
} }
if (render_resources.hovered != null and this.command != null and std.mem.eql(u8, render_resources.hovered.?, this.command.?)) { if (render_resources.hovered != null and this.command != null and std.mem.eql(u8, render_resources.hovered.?, this.command.?)) {
canvas.rect( canvas.rect(
min, .{ min[0] + mark_offset[0], min[1] + mark_offset[1] },
.{ max[0] - min[0], max[1] - min[1] }, .{ max[0] - min[0], max[1] - min[1] },
.{ .color = .{ 0xAA, 0xFF, 0xAA, 0x60 } }, .{ .color = .{ 0xAA, 0xFF, 0xAA, 0x60 } },
); );
@ -867,6 +885,33 @@ fn drawCardHandler(arena: std.mem.Allocator, request: Request) HandlerError!Resp
} }
fn playerTurnHandler(arena: std.mem.Allocator, request: Request) HandlerError!Response { fn playerTurnHandler(arena: std.mem.Allocator, request: Request) HandlerError!Response {
if (request.command) |command| handle_command: {
if (std.mem.startsWith(u8, command, "mark ")) {
var iter = std.mem.tokenizeScalar(u8, command, ' ');
_ = iter.next() orelse break :handle_command;
const rank_str = iter.next() orelse break :handle_command;
_ = iter.next() orelse break :handle_command;
const suit_str = iter.next() orelse break :handle_command;
const card = Card{
.suit = std.meta.stringToEnum(assets.Suit, suit_str) orelse break :handle_command,
.rank = std.fmt.parseInt(u4, rank_str, 10) catch break :handle_command,
};
var new_game_state = try request.game_state.clone(arena);
if (new_game_state.marked_cards.contains(card)) {
_ = new_game_state.marked_cards.remove(card);
} else {
try new_game_state.marked_cards.put(arena, card, {});
}
return Response{ .transition = .{
.game_state = new_game_state,
.can_undo = true,
} };
}
}
var draw_pile = try Pile.create(arena, request.game_state.draw_pile.items); var draw_pile = try Pile.create(arena, request.game_state.draw_pile.items);
draw_pile.hidden = true; draw_pile.hidden = true;
@ -876,7 +921,8 @@ fn playerTurnHandler(arena: std.mem.Allocator, request: Request) HandlerError!Re
for (request.game_state.hands[0].items) |card| { for (request.game_state.hands[0].items) |card| {
var card_element = try CardElement.create(arena, .{ var card_element = try CardElement.create(arena, .{
.visual = .{ .card = card }, .visual = .{ .card = card },
.command = "mark", .command = try std.fmt.allocPrint(arena, "mark {} of {s}", .{ card.rank, @tagName(card.suit) }),
.marked = request.game_state.marked_cards.contains(card),
}); });
try hand.addElement(card_element.element()); try hand.addElement(card_element.element());
} }