feat: v2 — queue matchmaking, procedural audio, sprite archetypes, auth

- Add queue-based matchmaking with Elo-proximity and 10s timeout
- Procedural sound engine (SFX, voice announcer, 4-track music)
- Sprite system refactored into 6 archetypes (standard, lobster, sheep, cyborg, blob, tank)
- 42+ fight choreographies with themed/generic/wild card selection
- 4 KO finish styles, super-speed mode, hyperdetail close-ups
- Auth routes, JoinBout page, bot profile with stats
- 7-tier ranking system (Baby through Legend)
- Arena and challenge system expansions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-06 22:13:19 +00:00
co-authored by Claude Opus 4.6
parent 335c148866
commit 47d20fbe66
82 changed files with 14011 additions and 741 deletions
@@ -0,0 +1,330 @@
# Botfights: 30-Day Production Plan
## Context
Botfights is a procedural fighting game (Vue 3 + Kaplay + Hono/SQLite) where AI bots battle through challenge rounds with pixel art sprites, synthesized audio, and choreographed fight animations. Currently a working prototype with 6 character archetypes, 42 choreographies, 4 music tracks, 6 voice profiles, ~45 challenge prompts, and 12 mock bots. The goal is to scale this to production-grade content (100 characters, 300 moves, 10,000 challenges, 20 songs, 30 voices, 30+ arenas) and build an overnight fight loop that runs autonomously.
---
## Phase 1: Module Splitting (Days 1-6)
The 3 monolith files must be split before any content scaling. Without this, adding content to 3500-line files is unmaintainable.
### Day 1-2: Split `sprites.ts` (954 lines)
```
frontend/src/game/sprites/
index.ts -- re-exports generateSpriteSheet, getBotColors, etc.
palette.ts -- makePal, parseHSL, Pal interface
constants.ts -- FRAME_SIZE, ANIMATIONS, INTERNAL, SCALE
drawing.ts -- px(), box(), fill() drawing primitives
base-body.ts -- drawFrame() core body/head/arms/legs/pose logic
archetypes/
index.ts -- archetype registry + roll function
standard.ts -- base (no extra features)
lobster.ts -- claws, antennae, segmented body, tail
sheep.ts -- wool, floppy ears, hooves
cyborg.ts -- metal plating, robot eye, wiring
blob.ts -- wobbly outline, googly eyes, drool
tank.ts -- armor, rivets, treads
judge.ts -- generateJudgeSpriteSheet()
```
Each archetype exports `{ name, weight, drawFeatures(ctx, pal, params) }`. The base-body calls the archetype's `drawFeatures` after the shared body drawing.
**Test:** Sprite preview page renders all 6 archetypes at all tiers identically to before.
### Day 3-4: Split `FightScene.ts` (~3500 lines)
```
frontend/src/game/fight/
index.ts -- createFightScene() orchestrator, returns controller
types.ts -- FightContext interface (k, W, H, GROUND_Y, HOME_A, HOME_B, helpers)
constants.ts -- ARENA_THEMES, spriteAnims, positions
particles.ts -- spawnSparks, spawnBulletHoles, spawnExhaust, etc.
projectiles.ts -- spawnProjectile, spawnBullet, spawnProp, spawnBarrage
effects.ts -- glitchRGB, scanlineGlitch, vhsTracking, dimensionalShift, etc.
grotesque.ts -- spawnGrotesqueDetails, destroyGrotesqueDetails
arena-decor.ts -- drawArenaDecor() per-arena backgrounds
choreography/
index.ts -- choreographyMap registry, pickChoreography
challenge-map.ts -- CHALLENGE_THEMED + critMoves
basic.ts -- dashPunch, aerialSlam, flyingKick, uppercut
ranged.ts -- projectile, gunBurst, sniperShot, minigunSpray
movement.ts -- dashThrough, fullScreenDash, teleportStrike
heavy.ts -- groundPound, jetpackDive, bodySlam, suplex
weapons.ts -- swordSlash, hammerSmash, katanaCombo, chainsawRev, whipCrack
vehicles.ts -- motorbikeCharge, carSmash, boatCannon
themed.ts -- golfClubSmash, fireBreath, riddleBarrage, coinShower, etc.
finishers.ts -- playKO (4 styles), playPerfect
round.ts -- playRound, playTaunt, playDodge
```
**Critical pattern:** Choreography functions close over Kaplay context. Each file exports functions that take a `FightContext` object with all shared state/helpers.
**Test:** Replay several fights, verify all 42 choreographies work.
### Day 5-6: Split `sounds.ts` (1381 lines) + server modules
```
frontend/src/game/sounds/
index.ts -- re-exports
context.ts -- AudioContext setup, gain nodes
primitives.ts -- tone(), noise(), sweep() helpers
sfx.ts -- all sfx functions (punch, kick, special, etc.)
voice.ts -- voice profiles, speak(), announce*(), voice lines
music/
index.ts -- startMusic(), stopMusic(), setMusicIntensity()
types.ts -- MusicTrack interface
player.ts -- playMusicBar() scheduler
tracks/
neon-fury.ts
dark-circuit.ts
pixel-blitz.ts
skull-crusher.ts
server/src/engine/
challenges/
index.ts -- pickChallenge(), registry
types.ts -- Challenge interfaces
speed-blitz.ts -- prompts array
riddle.ts
... (one per type)
mock/
index.ts -- runMockFight(), seedMockFights()
bots.ts -- MOCK_BOTS array
answers.ts -- MOCK_ANSWERS, BAD_ANSWERS
trash-talk.ts -- TRASH_TALK lines
```
**Test:** Full end-to-end fight replay with music, SFX, voice.
**Deliverable:** Identical functionality, ~40 small focused modules instead of 3 monoliths.
---
## Phase 2: Characters (Days 7-12)
### Day 7-8: New archetypes batch 1 (8 new)
- `dog.ts` -- floppy ears, wagging tail, snout with tongue, collar
- `cat.ts` -- pointed ears, whiskers, curled tail, slit eyes
- `cactus.ts` -- spikes everywhere, small flower on head, no real arms
- `pizza.ts` -- triangular body, cheese drip, pepperoni spots
- `mushroom.ts` -- dome cap head, spotted cap, stubby legs, spore particles
- `shark.ts` -- dorsal fin, teeth row, tail fin
- `penguin.ts` -- tuxedo coloring, beak, flippers
- `octopus.ts` -- 4 visible tentacles, large head, suction cups
### Day 9-10: New archetypes batch 2 (8 more)
- `skeleton.ts` -- visible ribs, skull head, bony limbs
- `ghost.ts` -- semi-transparent, wavy bottom (no legs), glowing eyes
- `alien.ts` -- big head, huge eyes, antenna, green tint
- `dinosaur.ts` -- tail, tiny arms, spiky back, big jaw
- `pirate.ts` -- eye patch, hat, peg leg, hook hand
- `ninja.ts` -- mask, headband, throwing star
- `cowboy.ts` -- hat, bandana, boots with spurs
- `wizard.ts` -- pointed hat, robe, staff replaces one arm, beard
### Day 11: Final archetypes + hybrid system
- `bee.ts` -- stripes, wings, stinger, antennae
- `frog.ts` -- wide mouth, bulging eyes, webbed feet, long tongue
- `snail.ts` -- shell on back, eye stalks, slime trail
- **Hybrid system:** 10% chance a bot combines features from 2 archetypes (lobster+sunglasses, sheep+robot arm, etc.)
- **Total:** 25 archetypes
### Day 12: 100 Named Bots + Seed Data
Expand `MOCK_BOTS` from 12 to 100 with distribution:
- ~5 tier-5, ~10 tier-4, ~20 tier-3, ~25 tier-2, ~25 tier-1, ~15 tier-0
Funny names by theme:
- **Tech:** `segfault_sarah`, `stack_overflow_sam`, `infinite_loop_larry`, `null_reference_nancy`
- **Food:** `pizza_pete`, `sushi_sensei`, `taco_tornado`, `burrito_bomber`
- **Animals:** `mega_lobster_xl`, `tactical_penguin`, `stealth_shark_3000`
- **Pop culture:** `keyboard_warrior`, `meme_lord_420`, `reply_guy_9000`
- **Absurd:** `sentient_toaster`, `angry_calculator`, `philosophical_fork`
Pre-seed 200 fight history records.
**Test:** `pnpm seed`, verify 100 bots, leaderboard renders, sprite preview shows all archetypes.
---
## Phase 3: Choreographies (Days 13-19)
Scale from 42 to 300 choreographies. Each follows the established function signature.
### Day 13-14: Food choreographies (~30 moves)
`choreography/food.ts`:
- `pizzaThrow`, `bananaSlip`, `pieFace`, `hotDogWhip`, `sushiRoll`
- `watermelonSmash`, `popcornBarrage`, `burritoWrap`, `cakeExplosion`, `iceCreamFreeze`
- `tacoSlam`, `donutSpin`, `breadSlap`, `eggCrack`, `soupSplash`
- `cheeseWheel`, `grapeShot`, `pineappleGrenade`, `cornCobGatling`, `steakSlap`
- Plus ~10 more food-themed variations
### Day 15-16: Spins/flips (~25) + vehicles (~15)
`choreography/spins.ts`:
- `spin720`, `backflipKick`, `tornadoSpin`, `corkscrewDive`, `cartwheel`
- `helicopterSpin`, `barrelRoll`, `frontflipSlam`, `spinningPiledriver`
- `doubleBackflip`, `wallflip`, `moonwalk`, `breakdanceSpin`, `drillKick`
- Plus more rotation/flip-based moves
`choreography/vehicles.ts` expansion:
- `skateboard`, `helicopter`, `shoppingCart`, `zamboni`, `rocketSled`
- `segway`, `unicycle`, `bulldozer`, `rollercoaster`, `cannonball`
- Plus existing (motorbikeCharge, carSmash, boatCannon)
### Day 17-18: Animal (~20) + energy (~20) + silly (~25)
`choreography/animal.ts`:
- `sharkBite`, `beeSwarm`, `frogTongue`, `stampede`, `spiderWeb`
- `snakeStrike`, `bearHug`, `eagleDive`, `ramCharge`, `crocodileRoll`
`choreography/energy.ts`:
- `kamehameha`, `hadouken`, `spiritBomb`, `thunderStrike`, `dragonPunch`
- `novaBlast`, `blackHole`, `sonicBoom`, `plasmaWhip`, `quantumTunnel`
`choreography/silly.ts`:
- `pillowFight`, `tickleAttack`, `selfieStun`, `vibeCheck`, `dabOnEm`
- `yeetThrow`, `airHorn`, `rubberChicken`, `bananaPeelChain`, `confettiCannon`
- `invisibleWall`, `slipNSlide`, `trampolineBounce`, `bubbleWrap`, `kazooBlast`
### Day 19: Wire all 300 choreographies
- Register all in `choreographyMap`
- Update `CHALLENGE_THEMED` with new move pools per challenge type
- Balance `pickChoreography` weights for maximum variety
- Add new moves to `critMoves` and `wild` arrays
**Test:** Run 50 fight replays, verify no crashes, observe variety.
---
## Phase 4: Challenges (Days 20-22)
Scale from ~45 prompts to ~10,000 challenges. Hilarious, modern, pop culture, stupid/silly.
### Day 20: Challenge bank architecture
```
server/src/engine/challenges/
banks/
speed-blitz.ts -- 1,200+ prompts
riddle.ts -- 500+ riddles
code-golf.ts -- 400+ challenges
roast-battle.ts -- 600+ roast prompts
hallucination.ts -- 800+ true/false
token-economy.ts -- 500+ explain prompts
creative-writing.ts -- 400+ creative prompts
math-blitz.ts -- 1,500+ math problems (many templated)
trap-card.ts -- 600+ prompt injections
meme-knowledge.ts -- 500+ meme identification (NEW TYPE)
emoji-translate.ts -- 400+ emoji challenges (NEW TYPE)
debate.ts -- 300+ debate topics (NEW TYPE)
fill-the-blank.ts -- 400+ completions (NEW TYPE)
reverse-engineer.ts -- 300+ output puzzles (NEW TYPE)
survival.ts -- 500+ escalating difficulty (NEW TYPE)
```
### Day 21: Build prompt banks (~10,000 total)
- Mix of hand-written and procedural templates
- Pop culture: "Is it true Elon Musk once fought a kangaroo?", "What would happen if the Minecraft creeper attended a job interview?"
- Modern/silly: "Explain blockchain to a medieval peasant", "Write a breakup text from a printer to its owner"
- Procedural templates for math/trivia: fill in numbers, countries, units
### Day 22: New challenge types + mock answers
- 6 new types: meme_knowledge, emoji_translate, debate, fill_the_blank, reverse_engineer, survival
- Scoring for each, mock answers for all 100 bots
- Wire into frontend `CHALLENGE_THEMED`
---
## Phase 5: Audio (Days 23-25)
### Day 23: 16 new music tracks (20 total)
Each track ~40 lines. Genre variety:
- 2x Synthwave (180-200 BPM), 2x Metal (250-280 BPM)
- 2x Chiptune (200-220 BPM), 2x Jazz Fusion (160-180 BPM)
- 2x Drum & Bass (170-175 BPM), 2x Lo-fi (140-160 BPM)
- 2x Ska Punk (210-230 BPM), 2x Boss Fight (280-300 BPM)
Intensity-based genre grouping:
- Low: lo-fi, jazz, chiptune | Medium: synthwave, ska punk
- High: metal, drum & bass | Max: boss fight
### Day 24: 24 new voice profiles (30 total)
New: whisper, manic, gravelly, chipper, deadpan, sports_caster, old_timey, drill_sergeant, surfer_dude, valley_girl, pirate_voice, robot_glitch, auctioneer, news_anchor, horror_narrator, lullaby, rage_quit, stoner, brit_posh, aussie, game_show, wrestling_announcer, noir_detective, anime_narrator
Expand voice line libraries to 300+ unique lines.
### Day 25: New SFX + arena-specific ambience
- 20 new SFX for new choreography types
- Arena-specific ambient background layers (beach waves, space hum, forest chirps)
---
## Phase 6: Scenes & Polish (Days 26-27)
### Day 26: 15+ new arenas (30+ total)
volcano, underwater, rooftop, train, kitchen, arcade, library, parking_lot, school, hospital, factory, castle, moon_base, ice_rink, stadium
New modifiers: fire_boost, ice_slow, gravity_low, double_damage, chaos_mode
### Day 27: Scene transitions + animated elements
- 4 transition styles: wipe, circle close/open, pixel dissolve, glitch cut
- Animated arena backgrounds: floating particles, dynamic lighting
- Enhanced spectator crowd reactions tied to round outcomes
---
## Phase 7: Production Loop (Days 28-30)
### Day 28: Fight scheduler + matchmaking
`server/src/engine/scheduler.ts`:
- `startScheduler(intervalMs)` -- Elo-based matchmaking loop
- Routes: `POST /api/scheduler/start|stop`, `GET /api/scheduler/status`
- Queue with rate limiting + bot cooldown
### Day 29: Headless mode + overnight operation
- `pnpm run fight-loop` for headless scheduler
- Env vars: `FIGHT_INTERVAL_MS`, `FIGHTS_PER_BATCH`, `MAX_CONCURRENT`
- Structured JSON logging, graceful SIGTERM shutdown
- `GET /api/stats` endpoint, health monitoring
### Day 30: Final seed data + integration test
- Generate: 100 bots, 500+ fight history
- Verify: Elo bell curve, tier distribution
- Full E2E: seed -> dev -> replay 10 fights -> fight-loop -> 100 fights -> typecheck + lint
---
## Dependency Graph
```
Phase 1 (Split) --- BLOCKS EVERYTHING
|
+-- Phase 2 (Characters) -- independent after Phase 1
+-- Phase 3 (Choreographies) -- independent after Phase 1
+-- Phase 4 (Challenges) -- independent after Phase 1
+-- Phase 5 (Audio) -- independent after Phase 1
|
+-- Phase 6 (Scenes) -- needs Phase 1 + Phase 3
+-- Phase 7 (Production) -- needs Phase 2 + Phase 4
```
## Testing Strategy
After every day:
1. `pnpm typecheck` -- catches import/export errors
2. Sprite preview page -- verify all archetypes render
3. Watch 5 random fight replays -- no crashes, visual variety
4. Audio check -- music, voices, SFX all play
5. `pnpm seed` -- verify DB has expected data
## Critical Files
- `frontend/src/game/sprites.ts` -> split into `sprites/` directory
- `frontend/src/game/FightScene.ts` -> split into `fight/` directory
- `frontend/src/game/sounds.ts` -> split into `sounds/` directory
- `frontend/src/components/FightViewer.vue` -> update imports
- `server/src/engine/challenges.ts` -> split into `challenges/` directory
- `server/src/engine/mock.ts` -> split into `mock/` + expand to 100 bots
- `server/src/engine/arenas.ts` -> expand to 30+ arenas
- `server/src/seed.ts` -> update imports
- `server/src/routes/fights.ts` -> add scheduler routes