Add support for up to 6 players.
This commit is contained in:
+69
-29
@@ -3,16 +3,19 @@ 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"`
|
||||
IsBot bool `json:"isBot,omitempty"`
|
||||
DeckSize int `json:"deckSize"`
|
||||
PetCount int `json:"petCount"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Seat int `json:"seat"`
|
||||
Coins int `json:"coins"`
|
||||
Trophies int `json:"trophies"`
|
||||
// RoundWins are the rounds this player won a battle in. Public — every
|
||||
// result is — and what the end-of-game countback tie-break runs on.
|
||||
RoundWins []int `json:"roundWins,omitempty"`
|
||||
Ready bool `json:"ready"`
|
||||
Connected bool `json:"connected"`
|
||||
IsBot bool `json:"isBot,omitempty"`
|
||||
DeckSize int `json:"deckSize"`
|
||||
PetCount int `json:"petCount"`
|
||||
// Avocados is the player's set-aside Avocado token count (Golden pack).
|
||||
// Public: buying an Avocado is a public shop event.
|
||||
Avocados int `json:"avocados,omitempty"`
|
||||
@@ -40,21 +43,31 @@ type View struct {
|
||||
Round int `json:"round"`
|
||||
MaxRounds int `json:"maxRounds"`
|
||||
MaxPets int `json:"maxPets"`
|
||||
// Pack is the selected card pack; Packs is the catalog of choices for the
|
||||
// lobby. HostSeat is the seat that controls the lobby (always 0 for now);
|
||||
// MinPlayers is how many seats must be filled before the host can start.
|
||||
Pack string `json:"pack"`
|
||||
Packs []PackInfo `json:"packs"`
|
||||
HostSeat int `json:"hostSeat"`
|
||||
MinPlayers int `json:"minPlayers"`
|
||||
MaxPlayers int `json:"maxPlayers"`
|
||||
YouSeat int `json:"youSeat"`
|
||||
Turn int `json:"turn"`
|
||||
// PrioritySeat is the seat currently holding the priority token.
|
||||
// Packs are the selected card packs, whose tiers shuffle together;
|
||||
// PackCatalog is the list of choices for the lobby and PacksNeeded is how
|
||||
// many the current table size requires. HostSeat is the seat that controls
|
||||
// the lobby (always 0 for now); PlayerCounts lists the table sizes a game
|
||||
// can start at.
|
||||
Packs []string `json:"packs"`
|
||||
PackCatalog []PackInfo `json:"packCatalog"`
|
||||
PacksNeeded int `json:"packsNeeded"`
|
||||
HostSeat int `json:"hostSeat"`
|
||||
MinPlayers int `json:"minPlayers"`
|
||||
MaxPlayers int `json:"maxPlayers"`
|
||||
PlayerCounts []int `json:"playerCounts"`
|
||||
YouSeat int `json:"youSeat"`
|
||||
Turn int `json:"turn"`
|
||||
// PrioritySeat is the seat holding the first-shopper token: it shops first
|
||||
// this round (and, in a two-player game, also acts first in the battle).
|
||||
PrioritySeat int `json:"prioritySeat"`
|
||||
ShopRow []Card `json:"shopRow"`
|
||||
DeckCounts []int `json:"deckCounts"` // remaining shop cards per tier
|
||||
Players []PlayerView `json:"players"`
|
||||
// Matchups are this round's battle pairings — public, since the schedule is
|
||||
// printed in the rulebook. YourOpponent is the seat you face this round, or
|
||||
// -1 outside a running game.
|
||||
Matchups []Matchup `json:"matchups,omitempty"`
|
||||
YourOpponent int `json:"yourOpponent"`
|
||||
// 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"`
|
||||
@@ -65,8 +78,14 @@ type View struct {
|
||||
// PendingSacrifice (Unicorn pack: Water of Youth) mirrors PendingReveal: the
|
||||
// options (the buyer's own pets) are only sent to the buyer.
|
||||
PendingSacrifice *PendingSacrifice `json:"pendingSacrifice,omitempty"`
|
||||
Battle *BattleResult `json:"battle,omitempty"`
|
||||
WinnerSeat int `json:"winnerSeat"`
|
||||
// Battle is the viewer's own battle this round; Battles holds every table's,
|
||||
// so a player can replay any of them. Both are public once resolved.
|
||||
Battle *BattleResult `json:"battle,omitempty"`
|
||||
Battles []*BattleResult `json:"battles,omitempty"`
|
||||
// WinnerSeat is the outright winner at gameover (-1 when shared);
|
||||
// WinnerSeats lists everyone holding the title.
|
||||
WinnerSeat int `json:"winnerSeat"`
|
||||
WinnerSeats []int `json:"winnerSeats,omitempty"`
|
||||
// Log is the shared, public event log shown across every phase.
|
||||
Log []LogEntry `json:"log,omitempty"`
|
||||
// Debug is set by the server when its DEBUG flag is on, unlocking the
|
||||
@@ -83,16 +102,21 @@ func (g *Game) ViewFor(playerID string) View {
|
||||
Round: g.Round,
|
||||
MaxRounds: MaxRounds,
|
||||
MaxPets: MaxPets,
|
||||
Pack: g.Pack,
|
||||
Packs: Packs,
|
||||
Packs: g.packList(),
|
||||
PackCatalog: Packs,
|
||||
PacksNeeded: PacksNeeded(len(g.Players)),
|
||||
HostSeat: 0,
|
||||
MinPlayers: MinPlayers,
|
||||
MaxPlayers: MaxPlayers,
|
||||
PlayerCounts: PlayerCounts,
|
||||
YouSeat: -1,
|
||||
YourOpponent: -1,
|
||||
Turn: g.Turn,
|
||||
PrioritySeat: g.PrioritySeat,
|
||||
ShopRow: g.ShopRow,
|
||||
WinnerSeat: g.WinnerSeat,
|
||||
WinnerSeats: g.WinnerSeats,
|
||||
Matchups: g.Pairings(),
|
||||
Log: g.Log,
|
||||
}
|
||||
for _, deck := range g.ShopDecks {
|
||||
@@ -105,6 +129,7 @@ func (g *Game) ViewFor(playerID string) View {
|
||||
Seat: p.Seat,
|
||||
Coins: p.Coins,
|
||||
Trophies: p.Trophies,
|
||||
RoundWins: p.RoundWins,
|
||||
Ready: p.Ready,
|
||||
Connected: p.Connected,
|
||||
IsBot: p.IsBot,
|
||||
@@ -115,6 +140,7 @@ func (g *Game) ViewFor(playerID string) View {
|
||||
}
|
||||
if p.ID == playerID {
|
||||
v.YouSeat = p.Seat
|
||||
v.YourOpponent = OpponentOf(len(g.Players), g.Round, p.Seat)
|
||||
pv.Deck = p.Deck
|
||||
pv.FirstBuyFree = p.FirstBuyFree
|
||||
pv.BuysThisRound = p.BuysThisRound
|
||||
@@ -144,9 +170,23 @@ func (g *Game) ViewFor(playerID string) View {
|
||||
}
|
||||
v.PendingSacrifice = &sac
|
||||
}
|
||||
// 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
|
||||
// Battle results (lineups, events) are public once resolved — every table's,
|
||||
// not just your own, so players can watch how the rest of the field did.
|
||||
// They stay around during the following shop phase too, so late joiners /
|
||||
// reconnects can still see the last round.
|
||||
v.Battles = g.Battles
|
||||
if v.YouSeat >= 0 {
|
||||
v.Battle = g.BattleFor(v.YouSeat)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// PlayerView returns the view of one seat within a View, or nil.
|
||||
func (v *View) PlayerView(seat int) *PlayerView {
|
||||
for i := range v.Players {
|
||||
if v.Players[i].Seat == seat {
|
||||
return &v.Players[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user