Files
super-auto-pets-board-game/web/src/types.ts
T

173 lines
3.9 KiB
TypeScript

// Mirrors of the Go view types (internal/game/view.go).
export type Suit = 'red' | 'blue' | 'yellow'
export type CardKind = 'pet' | 'food'
export type Phase = 'lobby' | 'shop' | 'arrange' | 'battle' | 'gameover'
export interface Card {
id: string
kind: CardKind
name: string
tier?: number
power?: number
suit?: Suit
effects?: unknown[]
effectText?: string
food?: string
perk?: boolean
temporary?: boolean
}
export interface PlayerView {
id: string
name: string
seat: number
coins: number
trophies: number
ready: boolean
connected: boolean
isBot?: boolean
deckSize: number
petCount: number
avocados?: number // set-aside Avocado tokens (Golden pack)
firstBuyFree?: boolean // Manta Ray: next buy is free (self only)
buysThisRound?: number // Blue-Ringed Octopus counter (self only)
deck?: Card[]
}
export interface PendingTrade {
playerId: string
tier: number
options: [Card, Card]
}
// Cockatoo (Golden pack): the buyer must reveal one of their pets.
export interface PendingReveal {
playerId: string
source: string
options?: string[] // eligible pet card ids (buyer only)
}
// Nurse Shark (Golden pack): a mid-battle Trumpet-spend choice.
export interface PendingBattleDecision {
seat: number
kind: string
petName: string
min: number
max: number
trumpets: number
}
export interface BattleEvent {
type:
| 'prep'
| 'reveal'
| 'summon'
| 'mill'
| 'rock'
| 'clash'
| 'shield'
| 'strip'
| 'steal'
| 'eat'
| 'heal'
| 'setaside'
| 'release'
| 'trumpet' // a side gains (+) or spends/loses (-) Trumpets (Golden pack)
| 'prevent' // a Cone Snail shaves damage off a hit (Golden pack)
seat?: number
target?: number
card?: Card
count?: number
// clash
damage?: number[]
died?: boolean[]
// rock / strip / steal
roll?: number
dice?: number[] // rock: individual die faces (each 0, 1, or 2)
damageAfter?: number
targetDied?: boolean
// eat (new bonus total) / reveal (starting bonus)
bonus?: number
// human-readable description of this step for the event log
text?: string
}
export interface BattleResult {
round: number
stackSizes: number[]
lineups?: Card[][] // each seat's arranged deck (top first); public for peeking
events: BattleEvent[] | null
winnerSeat: number
trophies: number
}
export interface LogEntry {
seq: number
round: number
phase: Phase
seat: number // acting seat, or -1
icon?: string
kind?: string // e.g. 'result' (battle outcome)
text: string
source?: string // card id that caused a spawn
spawn?: string // 'apple' | 'bee'
}
export interface PackInfo {
id: string
name: string
emoji: string
playable: boolean
}
export interface GameView {
gameId: string
code: string
phase: Phase
round: number
maxRounds: number
maxPets: number
pack: string
packs: PackInfo[]
hostSeat: number
minPlayers: number
maxPlayers: number
youSeat: number
turn: number
shopRow: Card[]
deckCounts: number[]
players: PlayerView[]
pending?: PendingTrade
pendingReveal?: PendingReveal
pendingBattle?: PendingBattleDecision
battle?: BattleResult
winnerSeat: number
log?: LogEntry[]
debug?: boolean // server DEBUG mode: unlocks the buy-any-card panel
}
export type ClientMessage =
| { type: 'setPack'; pack: string }
| { type: 'addBot'; difficulty: string }
| { type: 'removePlayer'; target: string }
| { type: 'start' }
| { type: 'buy'; row: number }
| { type: 'buyAvocado'; row: number }
| { type: 'sell'; cards: string[] }
| { type: 'trade'; cards: string[] }
| { type: 'tradeChoose'; pick: number }
| { type: 'revealChoose'; card: string }
| { type: 'battleChoose'; value: number }
| { type: 'pass' }
| { type: 'arrange'; order: string[] }
| { type: 'ready' }
| { type: 'debugAdd'; name: string }
export interface Session {
gameId: string
code: string
playerId: string
token: string
}