wip
This commit is contained in:
+2
-2
@@ -13,7 +13,7 @@ Client_View :: struct {
|
||||
other_players: []Player,
|
||||
}
|
||||
|
||||
recv_payload :: proc(sock: net.TCP_Socket, allocator := context.allocator) -> (pl: Payload) {
|
||||
recv_payload :: proc(sock: net.TCP_Socket, allocator := context.allocator) -> (pl: Player_View) {
|
||||
header: [4]u8
|
||||
net.recv(sock, header[:])
|
||||
num_cards := header[3]
|
||||
@@ -27,7 +27,7 @@ recv_payload :: proc(sock: net.TCP_Socket, allocator := context.allocator) -> (p
|
||||
return
|
||||
}
|
||||
|
||||
create_view :: proc(pl: Payload, allocator := context.allocator) -> Client_View {
|
||||
create_view :: proc(pl: Player_View, allocator := context.allocator) -> Client_View {
|
||||
cards_per_hand := pl.num_cards / (pl.num_players - 1)
|
||||
players: [dynamic]Player
|
||||
i := 0
|
||||
|
||||
+6
-1
@@ -21,6 +21,11 @@ Card :: bit_field u8 {
|
||||
|
||||
Hand :: distinct []Card
|
||||
|
||||
// 6 piles, one for each in COLORS.
|
||||
// u8 between 0-5, representing highest card in pile.
|
||||
// player can only place card of value `played[color]+1`.
|
||||
Played_Card_Piles :: distinct [6]u8
|
||||
|
||||
Game :: struct {
|
||||
num_players: int,
|
||||
num_hints: int,
|
||||
@@ -28,6 +33,7 @@ Game :: struct {
|
||||
hand_size: int,
|
||||
player_hands: [dynamic]Hand,
|
||||
deck: [dynamic]Card,
|
||||
played: Played_Card_Piles,
|
||||
}
|
||||
|
||||
create_deck :: proc() -> (deck: [dynamic]Card) {
|
||||
@@ -71,4 +77,3 @@ delete_game :: proc(g: ^Game) {
|
||||
delete(g.deck)
|
||||
delete(g.player_hands)
|
||||
}
|
||||
|
||||
|
||||
@@ -85,4 +85,3 @@ main :: proc() {
|
||||
}
|
||||
ok = true
|
||||
}
|
||||
|
||||
|
||||
+84
-33
@@ -17,15 +17,15 @@ run_server :: proc(listen_addr: net.Endpoint, num_players: int, num_hints: int,
|
||||
g := create_game(num_hints, num_lives, num_players)
|
||||
defer delete_game(&g)
|
||||
|
||||
w, comm_err := create_comm_world(listener, num_players)
|
||||
comm, comm_err := create_comm_world(listener, num_players)
|
||||
if comm_err != nil do panic(fmt.tprintln("failed to create comm world:", comm_err))
|
||||
defer delete_comm_world(&w)
|
||||
defer delete_comm_world(comm)
|
||||
|
||||
current_player := rand.int_max(num_players)
|
||||
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)
|
||||
view := create_view_from_game(g, i, context.temp_allocator)
|
||||
send_err := send_payload(comm[i], {.State_Update, view})
|
||||
if send_err != nil do panic("failed to send payload")
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ run_server :: proc(listen_addr: net.Endpoint, num_players: int, num_hints: int,
|
||||
|
||||
action: Action
|
||||
POKE: for {
|
||||
poke_err := send_poke(w.sockets[current_player])
|
||||
poke_err := send_poke(comm[current_player])
|
||||
if poke_err != nil do panic(fmt.tprintfln("failed to poke player %d; %s", current_player, poke_err))
|
||||
// action, is_valid := receive_action(w.sockets[current_player])
|
||||
// if is_valid do break POKE
|
||||
@@ -57,68 +57,107 @@ run_server :: proc(listen_addr: net.Endpoint, num_players: int, num_hints: int,
|
||||
COMM
|
||||
**********************/
|
||||
|
||||
Comm_World :: struct {
|
||||
sockets: [dynamic]net.TCP_Socket,
|
||||
}
|
||||
Comm_World :: distinct []net.TCP_Socket
|
||||
|
||||
create_comm_world :: proc(
|
||||
listener: net.TCP_Socket,
|
||||
num_conn: int,
|
||||
) -> (
|
||||
w: Comm_World,
|
||||
comm: Comm_World,
|
||||
err: net.Network_Error,
|
||||
) {
|
||||
w := make([dynamic]net.TCP_Socket, num_conn)
|
||||
fmt.printfln("waiting for players (%d)...", num_conn)
|
||||
for len(w.sockets) < num_conn {
|
||||
for len(w) < num_conn {
|
||||
client_sock, source := net.accept_tcp(listener) or_return
|
||||
append(&w.sockets, client_sock)
|
||||
append(&w, client_sock)
|
||||
fmt.println("player connected:", net.to_string(source))
|
||||
}
|
||||
return
|
||||
return Comm_World(w[:]), nil
|
||||
}
|
||||
|
||||
delete_comm_world :: proc(w: ^Comm_World) {
|
||||
for sock in w.sockets {
|
||||
delete_comm_world :: proc(comm: Comm_World) {
|
||||
for sock in comm {
|
||||
net.close(sock)
|
||||
}
|
||||
delete(w.sockets)
|
||||
delete(comm)
|
||||
}
|
||||
|
||||
/******************************
|
||||
MESSAGE (PAYLOAD/POKE)
|
||||
MESSAGE
|
||||
*******************************/
|
||||
|
||||
Msg_Type :: enum u8 {
|
||||
State_Update,
|
||||
Poke,
|
||||
Info,
|
||||
}
|
||||
|
||||
Payload :: struct #packed {
|
||||
num_players: u8,
|
||||
num_hints: u8,
|
||||
num_lives: u8,
|
||||
num_cards: u8,
|
||||
cards: []Card,
|
||||
Player_View :: struct #packed {
|
||||
constant: bit_field u8 {
|
||||
num_players: u8 | 3,
|
||||
hand_size: u8 | 3,
|
||||
},
|
||||
game_state: bit_field u8 {
|
||||
num_hints: u8 | 5,
|
||||
num_lives: u8 | 3,
|
||||
},
|
||||
played: Played_Card_Piles,
|
||||
num_cards: u8,
|
||||
cards: []Card,
|
||||
}
|
||||
|
||||
create_payload :: proc(g: Game, player: int, allocator := context.allocator) -> Payload {
|
||||
create_view_from_game :: proc(
|
||||
g: Game,
|
||||
player: int,
|
||||
allocator := context.allocator,
|
||||
) -> (
|
||||
view: Player_View,
|
||||
) {
|
||||
view.constant.num_players = u8(g.num_players)
|
||||
view.constant.hand_size = u8(g.hand_size)
|
||||
view.game_state.num_hints = u8(g.num_hints)
|
||||
view.game_state.num_lives = u8(g.num_lives)
|
||||
view.played = g.played
|
||||
cards: [dynamic]Card
|
||||
for i in 0 ..< g.num_players {
|
||||
if i == player do continue
|
||||
hand := g.players[i].hand[:]
|
||||
for c in hand do append(&cards, c)
|
||||
for &c in g.player_hands[i] {
|
||||
append(&cards, mem.reinterpret_copy(Card, &c))
|
||||
}
|
||||
}
|
||||
return {u8(g.num_players), u8(g.num_hints), u8(g.linum_lives u8(len(cards)), cards[:]}
|
||||
view.num_cards = u8(len(cards))
|
||||
view.cards = cards[:]
|
||||
return
|
||||
}
|
||||
|
||||
Info_Data :: distinct []byte
|
||||
|
||||
Payload :: struct #packed {
|
||||
type: Msg_Type,
|
||||
body: union {
|
||||
Player_View,
|
||||
Info_Data,
|
||||
},
|
||||
}
|
||||
|
||||
send_payload :: proc(sock: net.TCP_Socket, pl: Payload) -> net.Network_Error {
|
||||
switch pl.type {
|
||||
case .State_Update:
|
||||
view := pl.body.(Player_View)
|
||||
send_state_update(sock, &view) or_return
|
||||
case .Poke:
|
||||
send_poke(sock) or_return
|
||||
case .Info:
|
||||
send_info(sock, pl.body.(Info_Data))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
send_state_update :: proc(sock: net.TCP_Socket, pl: ^Player_View) -> net.Network_Error {
|
||||
header := Msg_Type.State_Update
|
||||
net.send(sock, mem.ptr_to_bytes(&header))
|
||||
data: [dynamic]u8
|
||||
defer delete(data)
|
||||
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
|
||||
net.send(sock, mem.ptr_to_bytes(&header)) or_return
|
||||
net.send(sock, mem.ptr_to_bytes(pl)) or_return
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -128,10 +167,23 @@ send_poke :: proc(sock: net.TCP_Socket) -> net.Network_Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
send_info :: proc(sock: net.TCP_Socket, data: Info_Data) -> net.Network_Error {
|
||||
header := Msg_Type.Info
|
||||
net.send(sock, mem.ptr_to_bytes(&header)) or_return
|
||||
net.send(sock, transmute([]byte)data) or_return
|
||||
return nil
|
||||
}
|
||||
|
||||
/*************************
|
||||
ACTION RESOLUTION
|
||||
**************************/
|
||||
|
||||
// actions should be handled in the Game kernel.
|
||||
// belief states should be handled here in the server,
|
||||
// or rather the translation between the local _player index
|
||||
// and the global player index used by g.player_hands.
|
||||
// thus, most of this section should likely be moved into game.odin
|
||||
|
||||
Play_Action :: distinct Card
|
||||
Discard_Action :: distinct Card
|
||||
Hint_Action :: distinct Card
|
||||
@@ -153,4 +205,3 @@ validate_action :: proc(action: Action) -> bool {
|
||||
perform_action :: proc(game: ^Game, action: Action) {
|
||||
unimplemented()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env nu
|
||||
|
||||
(interleave
|
||||
{ odin run . -- h localhost:42069 2 | lines | each { "HOST | " ++ $in } }
|
||||
{ sleep 500ms
|
||||
|
||||
Reference in New Issue
Block a user