only activate "New Meld" when a valid meld is marked

dev
LeRoyce Pearson 2024-02-27 00:27:09 -07:00
parent f0e6bc4e0d
commit 6f42b35e14
1 changed files with 49 additions and 3 deletions

View File

@ -23,7 +23,7 @@ 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), marked_cards: std.AutoArrayHashMapUnmanaged(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));
@ -968,10 +968,11 @@ fn playerTurnHandler(arena: std.mem.Allocator, request: Request) HandlerError!Re
var new_game_state = try request.game_state.clone(arena); var new_game_state = try request.game_state.clone(arena);
if (new_game_state.marked_cards.contains(card)) { if (new_game_state.marked_cards.contains(card)) {
_ = new_game_state.marked_cards.remove(card); _ = new_game_state.marked_cards.swapRemove(card);
} else { } else {
try new_game_state.marked_cards.put(arena, card, {}); try new_game_state.marked_cards.put(arena, card, {});
} }
new_game_state.marked_cards.sort(ArrayHashMapRummyHandSort{ .keys = new_game_state.marked_cards.keys() });
return Response{ .transition = .{ return Response{ .transition = .{
.game_state = new_game_state, .game_state = new_game_state,
@ -982,8 +983,11 @@ fn playerTurnHandler(arena: std.mem.Allocator, request: Request) HandlerError!Re
var new_meld_text = try TextElement.create(arena, .{ var new_meld_text = try TextElement.create(arena, .{
.text = "New Meld", .text = "New Meld",
.command = "new-meld", .command = null,
}); });
if (isValidRummyMeld(request.game_state.marked_cards.keys())) {
new_meld_text.command = "new-meld";
}
var melds_hbox = try HBox.create(arena); var melds_hbox = try HBox.create(arena);
try melds_hbox.addElement(new_meld_text.element()); try melds_hbox.addElement(new_meld_text.element());
@ -1015,6 +1019,48 @@ fn playerTurnHandler(arena: std.mem.Allocator, request: Request) HandlerError!Re
return Response{ .page = page.element() }; return Response{ .page = page.element() };
} }
fn isValidRummyMeld(cards: []const Card) bool {
std.debug.assert(std.sort.isSorted(Card, cards, {}, rummyHandSort));
if (cards.len < 3) {
return false;
}
const expected_rank = cards[0].rank;
var is_valid_set = true;
for (cards) |card| {
if (card.rank != expected_rank) {
is_valid_set = false;
break;
}
}
const expected_suit = cards[0].suit;
var is_valid_run = true;
for (cards[0 .. cards.len - 1], cards[1..]) |prev_card, card| {
if (card.suit != expected_suit or card.rank != (prev_card.rank + 1)) {
is_valid_run = false;
break;
}
}
return is_valid_set or is_valid_run;
}
pub fn rummyHandSort(_: void, lhs: Card, rhs: Card) bool {
if (lhs.rank < rhs.rank) return true;
if (lhs.rank > rhs.rank) return false;
return @intFromEnum(lhs.suit) < @intFromEnum(rhs.suit);
}
const ArrayHashMapRummyHandSort = struct {
keys: []const Card,
pub fn lessThan(this: @This(), lhs_index: usize, rhs_index: usize) bool {
return rummyHandSort({}, this.keys[lhs_index], this.keys[rhs_index]);
}
};
fn glfw_framebuffer_size_callback(window: ?*seizer.backend.glfw.c.GLFWwindow, width: c_int, height: c_int) callconv(.C) void { fn glfw_framebuffer_size_callback(window: ?*seizer.backend.glfw.c.GLFWwindow, width: c_int, height: c_int) callconv(.C) void {
_ = window; _ = window;
gl.viewport( gl.viewport(