feat: mark/unmark cards after drawing
parent
c5526ba229
commit
2dde105a58
56
src/main.zig
56
src/main.zig
|
@ -23,6 +23,8 @@ const GameState = struct {
|
|||
discard_pile: 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() {
|
||||
var draw_pile = std.ArrayListUnmanaged(Card).fromOwnedSlice(try makeStandardDeck(allocator));
|
||||
errdefer draw_pile.deinit(allocator);
|
||||
|
@ -59,6 +61,7 @@ const GameState = struct {
|
|||
.draw_pile = draw_pile,
|
||||
.discard_pile = discard_pile,
|
||||
.hands = hands,
|
||||
.marked_cards = .{},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -69,6 +72,7 @@ const GameState = struct {
|
|||
hand.deinit(this.allocator);
|
||||
}
|
||||
this.allocator.free(this.hands);
|
||||
this.marked_cards.deinit(this.allocator);
|
||||
}
|
||||
|
||||
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),
|
||||
.discard_pile = try this.discard_pile.clone(allocator),
|
||||
.hands = hands,
|
||||
.marked_cards = try this.marked_cards.clone(allocator),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
@ -262,6 +267,9 @@ pub fn main() !void {
|
|||
history.clearRetainingCapacity();
|
||||
}
|
||||
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,
|
||||
visual: Visual,
|
||||
command: ?[]const u8,
|
||||
marked: bool,
|
||||
|
||||
const Visual = union(enum) {
|
||||
back,
|
||||
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());
|
||||
errdefer allocator.destroy(this);
|
||||
|
||||
|
@ -748,6 +757,7 @@ pub const CardElement = struct {
|
|||
.allocator = allocator,
|
||||
.visual = options.visual,
|
||||
.command = options.command,
|
||||
.marked = options.marked orelse false,
|
||||
};
|
||||
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 {
|
||||
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) {
|
||||
.back => render_resources.deck.tilesheet.renderTile(
|
||||
canvas,
|
||||
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(
|
||||
canvas,
|
||||
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.?)) {
|
||||
canvas.rect(
|
||||
min,
|
||||
.{ min[0] + mark_offset[0], min[1] + mark_offset[1] },
|
||||
.{ max[0] - min[0], max[1] - min[1] },
|
||||
.{ .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 {
|
||||
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);
|
||||
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| {
|
||||
var card_element = try CardElement.create(arena, .{
|
||||
.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());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue