kinda working client

This commit is contained in:
2026-05-25 12:55:09 +02:00
parent da51c5871b
commit cb08664ab3
4 changed files with 88 additions and 10 deletions
+70 -5
View File
@@ -3,13 +3,78 @@ package hanabi
import "core:fmt"
import "core:net"
Client_View :: struct {
num_hints: int,
num_lives: int,
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
net.recv(sock, header[:])
num_cards := header[2]
body := make([]byte, 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
}
}
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)
hand: [dynamic]Card
for c in 0 ..< cards_per_hand {
append(&hand, unpack_card(pl.cards[i * cards_per_hand + c]))
}
players[i].hand = hand
}
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 {
fmt.println()
for c in p.hand {
fmt.println(c.value, c.color)
}
}
}
run_client :: proc(host_addr: net.Endpoint) {
sock, list_err := net.dial_tcp(host_addr)
serv, list_err := net.dial_tcp(host_addr)
if list_err != nil do panic(fmt.tprintln("failed to dial:", net.to_string(host_addr)))
defer net.close(sock)
buf: [256]byte
net.recv(sock, buf[:])
fmt.println(transmute(string)buf[:])
defer net.close(serv)
pl := recv_payload(serv, context.temp_allocator)
fmt.println("received payload")
view := create_view(pl, context.temp_allocator)
render_view(view)
free_all(context.temp_allocator)
}
+2 -1
View File
@@ -53,7 +53,8 @@ create_player :: proc(g: ^Game) -> (p: Player) {
}
create_game :: proc(hint_tokens, lives_left, num_players: int) -> (s: Game) {
assert(num_players > 1 && num_players < 6)
assert(num_players >= 2 && num_players <= 5)
s.num_players = num_players
s.hint_tokens = hint_tokens
s.lives_left = lives_left
s.deck = create_deck()
+1 -1
View File
@@ -37,7 +37,7 @@ main :: proc() {
if !endpoint_ok do panic(fmt.tprintln("failed to parse endpoint:", os.args[2]))
num_players, int_ok := strconv.parse_int(os.args[3])
if !int_ok do panic(fmt.tprintln("failed to parse number of players:", os.args[3]))
if num_players < 1 || num_players > 5 do return
if num_players < 2 || num_players > 5 do return
run_server(addr, num_players)
case:
return
+15 -3
View File
@@ -39,6 +39,10 @@ Bit_Card :: bit_field u8 {
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,
@@ -52,7 +56,7 @@ create_payload :: proc(g: Game, player: int, allocator := context.allocator) ->
if i == player do continue
hand := g.players[i].hand[:]
for c in hand {
append(&cards, Bit_Card{value = c.value, color = c.color})
append(&cards, pack_card(c))
}
}
return {u8(g.hint_tokens), u8(g.lives_left), u8(len(cards)), cards[:]}
@@ -88,19 +92,27 @@ run_server :: proc(
defer delete_game(&g)
current_player := rand.int_max(num_players)
game_loop: for {
GAME_LOOP: for {
for i in 0 ..< num_players {
pl := create_payload(g, i, context.temp_allocator)
send_err := send_payload(w.sockets[i], pl)
if send_err != nil do panic("failed to send payload")
}
fmt.printfln("player %s's turn!", current_player)
fmt.printfln("player %d's turn!", current_player)
for p in g.players {
fmt.println()
for c in p.hand {
fmt.println(c.value, c.color)
}
}
// body
current_player = (current_player + 1) % num_players
free_all(context.temp_allocator)
break GAME_LOOP
}
}