Adds cinematic bullet-time combat sequence with slow-mo golden projectiles,
afterimage dodge trails, and devastating counter-rush with multi-hit impact.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Creator omni-morph now generates actual sprite sheets for morphed archetypes
- 3 new Creator showboats: bullet time attack, ₿ throne summon, disco dance
- Music: subtle tempo shift (+10 BPM max), longer phrases (8/16/24 bars),
smoother crossfades, less chaotic hi-hat at high intensity
- Server: security headers, body size limit, production error masking,
CORS origin warning, graceful shutdown with drain
- Payments: atomic consume (eliminates SELECT/UPDATE race), release reverts DB
- Fight loop: round events for live TUI, retro displayPrompt
- Frontend: pass pubkey in payment/queue requests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Completely rewrote all 30 showboats with much more walking, jumping,
sprinting back and forth across the arena. Fighters now pace, charge,
leapfrog, zigzag sprint, do backflip retreats, wall-to-wall dashes,
kangaroo hops, shadow box sprints, and girlfriend kiss scenes.
Added 12 Creator-exclusive magical showboats:
- Levitate across screen trailing golden ₿ rain
- Portal teleport (vanish, flash between 3 spots, reappear)
- Massive golden code rain summon (₿01∞⚡⛏ characters)
- ₿ orbit explosion (orbit then burst outward)
- Lightning flight (zigzag with lightning bolts)
- Satoshi meditation (golden aura, bitcoin wisdom quotes)
- Golden tornado (circular path with ₿ trail)
- Laptop hack (type furiously, spawn code chars)
- Bitcoin rain shower (fly across dropping ₿ coins)
- Dimension rift (tear golden portal, step through)
- Golden ascension (rise, glow, slam down with shockwave)
- Phase walk (flicker through opponent's space)
Creator gets magical showboats ~60% of the time. Pause between
showboats shortened to keep the action constant.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fighters now perform random showboating micro-animations while idle
during question reading and opponent's answer — shadow boxing, backflips,
flex poses, moonwalks, ground pounds, air guitar, sumo stomps, and more.
Each showboat uses existing sprite anims (attack/kick/special/win) combined
with Kaplay tweens for position, scale, rotation, sparks, and emote text.
Showboating loops with random variety and pauses between moves.
Flow: both showboat during question → stop the answering bot during their
turn → stop all before fight animation begins.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Unified speakAsync/speakAsyncWithRate into _speakAsyncCore with:
- 500ms startup check: bail immediately if speech won't start (mobile/no gesture)
- 8s safety timeout (down from 15s) to prevent blocking
- iOS-safe keepalive: only do Chrome pause/resume workaround on desktop Chrome
- Immediate bail when no voices loaded
- Sprite loading: 5s timeout per sprite prevents mobile hangs from stuck Image decodes
- Scene creation: 10s timeout in FightViewer so overlay/voice flow continues even if
canvas fails on mobile
- playRound: bail gracefully if fighter sprites missing instead of crashing
- Global audio unlock: first touch/click on site unlocks AudioContext + SpeechSynthesis
- Practice button pre-unlocks audio while still in user gesture context
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
TTS fixes:
- Remove 60-char truncation in FightViewer — let speakAnswer handle limits
- Smart truncation at sentence boundaries (period, comma, etc.) up to 200 chars
- Chrome keepalive: periodic pause/resume prevents silent 15s cutoff bug
- Deduplicated cleanup logic in speakAsync/speakAsyncWithRate
Retro mode:
- Simplified challenge prompt from verbose wall of text to clean 3-line format
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace 100vh with 100dvh everywhere (accounts for mobile browser chrome)
- DocsPage: viewport-fixed with tabs pinned, tab content scrolls internally
- BotProfilePage: overflow-hidden outer, internal scroll container
- JoinBoutPage: viewport-fixed with internal overflow scroll
- HumanFightPage: viewport-fixed, flex-1 content area with internal scroll
- All other pages: vh → dvh for correct mobile sizing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DocsPage: escaped \"answer\" inside v-for HTML attribute broke template
parsing causing infinite Vite error loop. Replaced with " entity.
FightScene: three k.text('₿') objects used .angle without k.rotate()
component, causing TS2339 build errors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove all super/ultra combo inputs, exact damage values, discovery
multiplier (1.5x), and Konami Code from BOT_SETUP.md, bot-guide.md,
docs.ts API, and example bot. Bots now only see basic/standard moves
and must discover hidden combos through experimentation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update BOT_SETUP.md with full retro mode combo reference, scoring,
and strategy tips. Add docs/bot-guide.md as a standalone developer
guide covering all challenge types including retro mode. Add
docs/sprite-guide.md and sprite-reference.html for custom sprite
creation. Update docs.ts API endpoint and Python example bot with
retro_mode handling.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Every fight now includes one Retro Mode round where bots submit
gamepad combo inputs (↑↓←→ A B). 24 moves across 4 tiers: basic
(always shown), standard (partially revealed), super (must discover),
and ultra (KONAMI CODE for 50 dmg). Discovery bonus gives 1.5x damage.
Includes pixel-art gamepad overlays (P1/P2) with animated button
presses, retro-specific narrations, and mock bot combo responses
scaled by ELO.
Also adds loops/plan.md with 11-phase production hardening roadmap.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Login auto-creates a human fighter for the Creator pubkey if no DB entry
exists. register-human now applies the_creator archetype for the Creator.
Update endpoint can no longer override the Creator's archetype.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds emissive glow bloom, visible pixel grid, cross-hatch background,
scan lines, 3D bevel, and tier-gated energy particles to poster sprites.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move crypto key init from module-level throw to lazy getKey() — only
errors when encrypt/decrypt are actually called. Downgrade env var
check in index.ts from fatal exit to warning.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fight Card page: dramatic poster background with cross-hatch, spotlights,
vignettes, corner brackets, scan lines; 3D VS orb with punch animation;
selectable undercard with main event always pinned at top
- PosterSprite: high-quality 480px poster frame with 6-pass renderer
(aura, glow, bevel, specular, particles); PixelGlove component
- 12-char bot name limit across all forms and server validation
- Mock bots: all 100 now have diverse archetypes (25 types), 25% human
fighters; seedMockBots updates existing bots on restart
- Leaderboard: inline SpritePreview next to each bot name
- Nostr auth: persistent login, nsec copy button
- Wallet: NWC + Lightning Address, ranked fight flow
- Server: payments, ranked queue, customization endpoint
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Arena page shows small sprite previews next to each bot's name
- Server returns archetype in fights list endpoint
- New /fight-card page with 3D perspective fight poster, neon signs,
animated boxing gloves, fighter bobbing, VS pulse, undercard list
- Added FIGHT CARD to nav bar
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add WalletConnect.vue with NWC/LN Address connection states. Add "FIGHT
FOR SATS" button to JoinBoutPage with entry fee payment flow. Show ranked
pot and winner payout in FightPage. Add sats stats and wallet section to
BotProfilePage. Extend BotData interface with satsWon/satsWagered/hasWallet.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Client-side wallet composable with NWC auto-pay, invoice polling,
Cashu token submission, and persistent wallet state. Follows useNostr
pattern with readonly exports and localStorage persistence.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add /api/payments router (connect-wallet, wallet-status, create-invoice,
check, submit-cashu, winnings, claim, disconnect-wallet). Add ranked
queue endpoints to /api/queue. Mount payments router in app.ts with
orphan payment recovery on startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add ranked-queue.ts with 60s timeout, ELO matching, no-mock guard, and
automatic refund on timeout. Wire orchestrator to accept mode param,
track satsWagered in finalize transaction, trigger payWinner on ranked
win and refundEntry on ranked draw.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements createEntryInvoice, checkPaymentStatus, payWinner, refundEntry,
redeemCashuToken, and recoverOrphanedPayments. Uses nostr-tools for NWC
protocol (NIP-47) and @cashu/cashu-ts for ecash fallback payouts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Disconnect and recreate sfxGain in stopAllAudio() so oscillators
and noise buffers stop immediately instead of playing to completion.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add payments and wallet_connections tables, new columns on fights (mode,
pot_sats, payout_status) and bots (sats_won, sats_wagered, has_wallet).
Install nostr-tools and @cashu/cashu-ts for NWC + ecash support.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- FightViewer: wrap createFightScene in try/catch so scene failures
don't crash every subsequent playRound call
- FightViewer: wait for container to have non-zero dimensions before
creating canvas (prevents 0x0 canvas causing sprite load failures)
- FightViewer: graceful log-only fallback when scene init fails
- FightPage: same dimension-wait and try/catch for initLiveScene
- Fallback canvas dimensions (800x500) when container not yet laid out
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Complete betting infrastructure:
- Bets schema (SQLite) with escrow status tracking
- Cashu token verification + minting (stub for real mint)
- Lightning invoice creation + withdrawal (stub for real LN node)
- Bet placement with odds lock, settlement on fight end
- Payout automation for winners, refunds on draws
- Bet history by pubkey + fight pool info
- Verifiable bet proofs for transparency
- API routes: /api/bets/{odds,place,fight,history,deposit,withdraw}
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Converts ELO ratings + streaks + recent form into betting odds.
Supports decimal, fractional, and American formats.
Includes bet validation, payout calculation, and 27 tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add minimal Python webhook bot (zero deps, stdlib only).
Mark Docker, rate limiting, example bots, tutorial as done in PLAN.md
— all were already implemented.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fetches from /api/docs/webhook and renders as a styled tabbed page.
Added /docs route and DOCS nav link.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- texan profile pitch/rate adjusted (0.65/0.75) to differentiate from deep (0.7/0.7)
- Audited all 60 voice profiles: no remaining pitch+rate duplicates
- Category announces verified: all fire correctly via speak() pipeline
- Speech queue already capped at depth 2 with cancel, no debounce needed
- TTS fallback already graceful: speak() returns silently when unavailable
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- visibilitychange handler resumes speech + AudioContext on tab return
- speak() retry logic: re-attempts once on non-cancel errors after 200ms
- VOICE_VOLUME_SCALE (0.7) prevents voice from overpowering SFX/music
- Music crossfade: brief gain dip (40% -> 100%) on track switches
- Applied volume scale to all speech paths (speak, announce custom)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- impactFreeze(): brief white flash pause on devastating critical hits
- spawnAfterimages(): trailing ghost sprites on fast dash moves
- spawnSparks(): varied particle sizes, rotational velocity, stronger gravity
- cameraZoom(): slight zoom-in on critical final exchanges, pull-back for ultimates
- Wired into dashPunch, aerialSlam, flyingKick, dashThrough, uppercut
- Critical exchanges get 1.3x camera zoom before the blow lands
- Ultimates get 0.85x pull-back to show the full move
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- spawnGrotesqueDetails: radial impact lines + dots during zoom close-ups
- spawnCrowdSigns: signs rise from bottom with text labels, bob, fade out
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- answers.test.ts: 19 tests covering all 10 checkAnswer() tiers
- scoring.test.ts: 30 tests for scoreRound, calculateElo, calculateTier, applyModifiers
- challenges.test.ts: 16 tests for pickChallenge, type exclusion, data integrity
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- FightViewer: track deferred speechSynthesis.cancel() timer, clear on unmount
- BotProfilePage: change isOwner from ref to computed for reactive login state
- sounds.ts: tighten speech queue depth cap from 3 to 2
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All empty catch blocks across 8 Vue pages now log warnings. User-initiated
actions (fight, matchmake) also surface errors in the UI via fightError/loadError refs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- scoring.ts: wire arena damage modifiers (speed_2x, roast_2x, etc.) into applyModifiers()
- human-responses.ts: use challenge.timeout_ms instead of hardcoded 8s
- FightPage.vue: add route watcher for clean state reset on navigation
- Validated all 800 prompts: 0 duplicates, all factual have answers, all choices have 4 items
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add route param watcher so navigating to a new fight properly resets
and reinitializes the scene (fixes KAPLAY re-init / null scene errors)
- Add loading spinner to profile page instant fight button
- Restore truncated challenges.ts (was causing all 500 errors)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ArenaPage: merge duplicate onMounted hooks into single parallel fetch
- FightPage: queue SSE events until liveFightData ready, add reconnect with backoff
- FightViewer: fix stale canvas ref with container ref, add sceneReady guard
- HomePage: replace stopCycling boolean with AbortController for clean unmount
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>