fix transmutation bug

This commit is contained in:
2026-05-27 19:15:04 +02:00
parent cb08664ab3
commit 1193386c47
3 changed files with 53 additions and 73 deletions
+30 -37
View File
@@ -4,58 +4,51 @@ import "core:fmt"
import "core:net"
Client_View :: struct {
num_hints: int,
num_lives: int,
players: []Player,
num_players: int,
num_hints: int,
num_lives: int,
other_players: []Player,
}
unpack_card :: proc(c: Bit_Card) -> Card {
return {value = c.value, color = c.color}
}
recv_payload :: proc(sock: net.TCP_Socket, allocator := context.allocator) -> Payload {
header: [3]byte
recv_payload :: proc(sock: net.TCP_Socket, allocator := context.allocator) -> (pl: Payload) {
header: [4]u8
net.recv(sock, header[:])
num_cards := header[2]
body := make([]byte, num_cards)
num_cards := header[3]
body := make([]u8, num_cards)
net.recv(sock, body)
return {header[0], header[1], header[2], transmute([]Bit_Card)body}
}
num_players :: proc(num_cards: int) -> int {
switch num_cards {
case 5:
return 2
case 10:
return 3
case 12:
return 4
case 16:
return 5
case:
return -1
}
pl = {header[0], header[1], header[2], header[3], transmute([]Card)body}
// sanity checks
assert(2 <= pl.num_players && pl.num_players <= 5)
assert(pl.num_hints >= 0 && pl.num_lives >= 0)
for c in pl.cards do assert(1 <= c.value && c.value <= 5)
return
}
create_view :: proc(pl: Payload, allocator := context.allocator) -> Client_View {
n := num_players(int(pl.num_cards))
assert(n > 0)
players := make([]Player, n)
for i in 0 ..< n - 1 {
cards_per_hand := int(pl.num_cards) / (n - 1)
cards_per_hand := pl.num_cards / (pl.num_players - 1)
players: [dynamic]Player
i := 0
for cast(u8)len(players) < pl.num_players - 1 {
hand: [dynamic]Card
for c in 0 ..< cards_per_hand {
append(&hand, unpack_card(pl.cards[i * cards_per_hand + c]))
for cast(u8)len(hand) < cards_per_hand {
append(&hand, pl.cards[i])
i += 1
}
players[i].hand = hand
append(&players, Player{hand = hand})
}
return {
num_players = int(pl.num_players),
num_hints = int(pl.num_hints),
num_lives = int(pl.num_lives),
other_players = players[:],
}
return {num_hints = int(pl.num_hints), num_lives = int(pl.num_lives), players = players}
}
render_view :: proc(view: Client_View) {
fmt.println("number of hints left:", view.num_hints)
fmt.println("number of lives left:", view.num_lives)
for p in view.players {
for p in view.other_players {
fmt.println()
for c in p.hand {
fmt.println(c.value, c.color)
+12 -12
View File
@@ -3,21 +3,21 @@ package hanabi
import "core:fmt"
import "core:math/rand"
COLORS :: enum {
RED,
GREEN,
WHITE,
BLUE,
YELLOW,
RAINBOW,
COLORS :: enum u8 {
RED = 0b000,
GREEN = 0b001,
WHITE = 0b010,
BLUE = 0b011,
YELLOW = 0b100,
RAINBOW = 0b101,
}
Card :: struct {
value: int,
color: COLORS,
Card :: bit_field u8 {
value: u8 | 3,
color: COLORS | 3,
}
VALUES: []int : {1, 1, 1, 2, 2, 3, 3, 4, 4, 5}
VALUES: []u8 : {1, 1, 1, 2, 2, 3, 3, 4, 4, 5}
Player :: struct {
hand: [dynamic]Card,
@@ -38,7 +38,7 @@ hand_size :: proc(g: Game) -> int {
create_deck :: proc() -> (deck: [dynamic]Card) {
for c in COLORS {
for v in VALUES {
append(&deck, Card{v, c})
append(&deck, Card{value = v, color = c})
}
}
rand.shuffle(deck[:])
+11 -24
View File
@@ -30,47 +30,34 @@ delete_comm_world :: proc(w: ^Comm_World) {
delete(w.sockets)
}
/*
emulates Card, but packs the fields more neatly
*/
Bit_Card :: bit_field u8 {
value: int | 3,
color: COLORS | 3,
}
pack_card :: proc(c: Card) -> Bit_Card {
return {value = c.value, color = c.color}
}
Payload :: struct #packed {
num_hints: u8,
num_lives: u8,
num_cards: u8,
cards: []Bit_Card,
num_players: u8,
num_hints: u8,
num_lives: u8,
num_cards: u8,
cards: []Card,
}
create_payload :: proc(g: Game, player: int, allocator := context.allocator) -> Payload {
cards: [dynamic]Bit_Card
cards: [dynamic]Card
for i in 0 ..< g.num_players {
if i == player do continue
hand := g.players[i].hand[:]
for c in hand {
append(&cards, pack_card(c))
}
for c in hand do append(&cards, c)
}
return {u8(g.hint_tokens), u8(g.lives_left), u8(len(cards)), cards[:]}
return {u8(g.num_players), u8(g.hint_tokens), u8(g.lives_left), u8(len(cards)), cards[:]}
}
send_payload :: proc(sock: net.TCP_Socket, pl: Payload) -> net.Network_Error {
data: [dynamic]byte
data: [dynamic]u8
defer delete(data)
append(&data, pl.num_hints, pl.num_lives, pl.num_cards)
append(&data, pl.num_players, pl.num_hints, pl.num_lives, pl.num_cards)
for c in pl.cards do append(&data, transmute(u8)c)
net.send(sock, data[:]) or_return
return nil
}
// TODO: add cli input for these
DEFAULT_HINT_TOKENS :: 8
DEFAULT_LIVES :: 3