diff --git a/src/client.odin b/src/client.odin index bf295ae..31703f5 100644 --- a/src/client.odin +++ b/src/client.odin @@ -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) } diff --git a/src/game.odin b/src/game.odin index 41dba42..1dbb51b 100644 --- a/src/game.odin +++ b/src/game.odin @@ -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() diff --git a/src/main.odin b/src/main.odin index ca5013e..576ba25 100644 --- a/src/main.odin +++ b/src/main.odin @@ -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 diff --git a/src/server.odin b/src/server.odin index b95bc7c..49c4af8 100644 --- a/src/server.odin +++ b/src/server.odin @@ -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 } }