117 lines
5.2 KiB
Markdown
117 lines
5.2 KiB
Markdown
# Super Auto Pets: The Board Game — Online
|
||
|
||
A web app for playing the Super Auto Pets board game remotely. 1v1 for now;
|
||
the engine is built to grow to more players. Play a friend by room code, or
|
||
play solo against a computer opponent (easy / medium / hard).
|
||
|
||
## Stack
|
||
|
||
- **Backend**: Go (stdlib-first). Pure game engine in `internal/game`,
|
||
WebSocket sync via `coder/websocket`, persistence as JSON blobs in SQLite
|
||
(`modernc.org/sqlite`, no cgo).
|
||
- **Frontend**: React + Vite + TypeScript in `web/`. DOM/CSS card rendering
|
||
and battle animations.
|
||
- **Tasks**: [mise](https://mise.jdx.dev) (`mise.toml`).
|
||
|
||
## Quick start
|
||
|
||
```sh
|
||
mise run install-web # once: npm install
|
||
mise run serve # build frontend + server, run on :8080
|
||
```
|
||
|
||
Open http://localhost:8080, host a game, and join from another browser (or
|
||
incognito window) with the 5-letter code.
|
||
|
||
### Development
|
||
|
||
```sh
|
||
mise run dev # Go server on :8080 + Vite hot reload on :5173
|
||
mise run test # Go tests (game engine)
|
||
mise run check # go vet + frontend type-check
|
||
```
|
||
|
||
During development open the Vite URL (http://localhost:5173); it proxies
|
||
`/api` (including the WebSocket) to the Go server.
|
||
|
||
## Configuration
|
||
|
||
Set via environment or a `.env` file (see `.env.example`):
|
||
|
||
| Variable | Default | Purpose |
|
||
| ------------ | ---------- | ------------------------------------ |
|
||
| `DATA_DIR` | `data` | Directory holding the SQLite DB |
|
||
| `PORT` | `8080` | HTTP port |
|
||
| `STATIC_DIR` | `web/dist` | Built frontend to serve |
|
||
|
||
## Rules implemented
|
||
|
||
Six rounds, each with its own shop tier deck. Per round:
|
||
|
||
1. **Shop** — each player has 3 gold and players alternate actions, 1 gold
|
||
each: **buy** one of 4 face-up cards; **sell** any number of hand cards
|
||
(each becomes an 🍎 apple, +1 power food, and Sell effects fire); or
|
||
**trade in** 3 same-suit pets (the Triple action) to pick 1 of the top 2
|
||
cards of the next tier's deck — Triple effects fire on the traded cards
|
||
and the received pet's Buy effect fires. Passing forfeits remaining gold.
|
||
2. **Cleanup** — anyone holding more than 5 pets must sell down to 5.
|
||
3. **Arrange** — Battle Prep effects fire first (e.g. Giraffe hands out
|
||
apples), then players secretly order their decks. Food cards apply to the
|
||
next pet after them; trailing foods are wasted. A pet only benefits from
|
||
its last-applied **perk** (e.g. Honey, Garlic).
|
||
4. **Battle** — automatic stack machine. Cards reveal off the top of each
|
||
deck until a pet is in play. Play effects fire on reveal (rocks roll a d6
|
||
with faces 0/0/1/1/2/2 and hit the opposing pet before the clash; Skunk
|
||
strips foods; Wolverine steals apples; Chili mills the enemy deck). The
|
||
two pets simultaneously deal their full power to each other as damage
|
||
markers; a pet with markers ≥ power faints (attack never drops while
|
||
wounded). Faint effects push summons onto either deck, recycle apples
|
||
(Dodo), set aside delayed/recurring/conditional rock volleys (Badger,
|
||
Blowfish, Snake, Crocodile), raise auras (Turkey, Mammoth), or arm a
|
||
team shield (Turtle). Survivors that took damage fire Hurt effects
|
||
(Peacock, Camel, Gorilla). Shields (Turtle/Gorilla/Melon) block whole
|
||
hits, Garlic shaves 1 per attack, and Scorpion KOs anything its clash
|
||
attack manages to hurt. Hippo heals when enemies faint; Rhino rocks each
|
||
enemy pet as it's played. A clash that changes nothing ends the battle
|
||
as a stalemate draw. Last player able to field a pet wins: 1 trophy for
|
||
rounds 1–5, 2 for round 6. Draws award nothing.
|
||
|
||
Apples and bees are **temporary**: they leave your deck after the battle.
|
||
Most trophies after round 6 wins.
|
||
|
||
All six tiers use the real card data:
|
||
|
||
| Tier | Pets | Food |
|
||
| ---- | ---- | ---- |
|
||
| 1 | Ant, Cricket, Duck, Otter, Mosquito, Fish | — |
|
||
| 2 | Worm, Flamingo, Peacock, Swan, Rat, Spider | Honey |
|
||
| 3 | Dog, Dolphin, Giraffe, Camel, Sheep, Dodo, Badger | Garlic |
|
||
| 4 | Squirrel, Turtle, Rooster, Bison, Blowfish, Skunk, Hippo | Pineapple |
|
||
| 5 | Monkey, Rhino, Crocodile, Scorpion, Seal, Shark, Turkey | Chili |
|
||
| 6 | Gorilla, Fly, Leopard, Mammoth, Cat, Snake, Wolverine | Melon |
|
||
|
||
## Layout
|
||
|
||
```
|
||
cmd/server/ entrypoint
|
||
internal/game/ rules engine (pure, fully tested)
|
||
internal/ai/ computer opponent (decides from a player View only)
|
||
internal/server/ HTTP + WebSocket rooms; drives bot turns
|
||
internal/store/ SQLite persistence
|
||
internal/env/ .env loading
|
||
web/ React frontend
|
||
```
|
||
|
||
## The computer opponent
|
||
|
||
Any seat can be a bot (`Player.IsBot`); humans and bots are interchangeable
|
||
to the engine, which is what will let future >2-player games mix them
|
||
freely. The AI in `internal/ai` never touches the `Game` — it decides from a
|
||
`game.View`, the same per-player state a human client is sent, plus a
|
||
persisted memory of public observations (battle lineups, the event log, shop
|
||
row changes). It cannot see your deck order, hidden trade picks, or the
|
||
shuffled shop decks. It scores candidate moves by Monte-Carlo battle
|
||
rollouts (`game.SimulateBattle`) against sampled guesses of your deck and
|
||
ordering, blended with a long-term deck-value heuristic; difficulty tunes a
|
||
softmax over the scored moves plus the rollout budget.
|