package game // PlayerView is what any player may know about a seat. Deck contents are // only included for the viewer's own seat; opponents see counts. type PlayerView struct { ID string `json:"id"` Name string `json:"name"` Seat int `json:"seat"` Coins int `json:"coins"` Trophies int `json:"trophies"` Ready bool `json:"ready"` Connected bool `json:"connected"` DeckSize int `json:"deckSize"` PetCount int `json:"petCount"` Deck []Card `json:"deck,omitempty"` // self only } // View is the full game state as seen by one player. type View struct { GameID string `json:"gameId"` Code string `json:"code"` Phase Phase `json:"phase"` Round int `json:"round"` MaxRounds int `json:"maxRounds"` MaxPets int `json:"maxPets"` YouSeat int `json:"youSeat"` Turn int `json:"turn"` ShopRow []Card `json:"shopRow"` DeckCounts []int `json:"deckCounts"` // remaining shop cards per tier Players []PlayerView `json:"players"` // Pending is included for everyone so opponents see a trade is in // progress, but the revealed options are only shown to the trader. Pending *PendingTrade `json:"pending,omitempty"` Battle *BattleResult `json:"battle,omitempty"` WinnerSeat int `json:"winnerSeat"` } // ViewFor builds the state visible to the given player. func (g *Game) ViewFor(playerID string) View { v := View{ GameID: g.ID, Code: g.Code, Phase: g.Phase, Round: g.Round, MaxRounds: MaxRounds, MaxPets: MaxPets, YouSeat: -1, Turn: g.Turn, ShopRow: g.ShopRow, WinnerSeat: g.WinnerSeat, } for _, deck := range g.ShopDecks { v.DeckCounts = append(v.DeckCounts, len(deck)) } for _, p := range g.Players { pv := PlayerView{ ID: p.ID, Name: p.Name, Seat: p.Seat, Coins: p.Coins, Trophies: p.Trophies, Ready: p.Ready, Connected: p.Connected, DeckSize: len(p.Deck), PetCount: p.PetCount(), } if p.ID == playerID { v.YouSeat = p.Seat pv.Deck = p.Deck } v.Players = append(v.Players, pv) } if g.Pending != nil { pending := *g.Pending if pending.PlayerID != playerID { pending.Options = [2]Card{} // hide the revealed cards } v.Pending = &pending } // Battle results (lineups, events) are public once resolved. Keep the // battle around during the following shop phase too, so late joiners / // reconnects can still see the last result. v.Battle = g.Battle return v }