Skip to content

feat(tma): Full mock game engine with AI opponent, economy, and audit fixes#16

Open
Glazlk wants to merge 1 commit intomainfrom
feature/mock-ui-flow
Open

feat(tma): Full mock game engine with AI opponent, economy, and audit fixes#16
Glazlk wants to merge 1 commit intomainfrom
feature/mock-ui-flow

Conversation

@Glazlk
Copy link
Member

@Glazlk Glazlk commented Mar 14, 2026

Summary

Complete standalone mock game engine that simulates the full PvP user flow with an AI opponent. Replaces the dead socket.ts with mockGame.ts — the entire game is now playable in the browser without any backend, database, or blockchain connection.

This PR enables anyone to experience the full Elmental gameplay loop by simply running pnpm dev.

What's New

  • Mock Game Engine (mockGame.ts) — AI opponent with 3 personalities (aggressive/conservative/adaptive), full commit→reveal→resolve flow, matchmaking simulation (5-15s search)
  • Complete Economy — stake deduction on match-found, winner payout (pool - 5% rake), boost burn/return, transaction ledger
  • Economy Breakdown on ResultScreen — shows stake, pool, rake, payout, boost status, net result
  • Transaction History on ProfileScreen — replaces dead "Recent Rounds" placeholder
  • Balance Protection — PLAY button disabled when insufficient ELM, shows "Need X ELM (have Y)"

Bug Fixes from Code Audit

Bug Fix
Chaos mode always gave 10 regen Now passes random chaosRoll (0-20) to calculateEnergy()
No round cap — infinite draw loop possible MAX_ROUNDS (9) enforced, match ends by score comparison
EnergyBar broke at 120 energy (boost) Dynamic maxEnergy based on boost status
Overclock warning badge was dead UI Now works: visible when energy ≥ 0 but < move cost
MoveCard fully disabled on low energy Now allows overclock plays (energy ≥ 0 but < cost)
Winning round overlay flashed for 100ms 1.5s delay before transitioning to ResultScreen
boost_burn transaction logged amount: 0 Correct negative amounts in all transactions
ProfileScreen always showed empty rounds Live Transaction History from store
Negative ELM balance allowed silently PLAY button disabled + clear messaging
Dead socket.ts (zero imports) Deleted

Files Changed

File Change
apps/tma/src/services/mockGame.ts NEW — Full mock game engine (AI, economy, timers)
apps/tma/src/services/socket.ts DELETED — Orphaned, zero imports
apps/tma/src/stores/gameStore.ts Added: transactions[], matchStake, matchBoostStake, EconomyTransaction type, expanded MatchResult
apps/tma/src/screens/HomeScreen.tsx Mock matchmaking, balance guard, stake display on PLAY button
apps/tma/src/screens/MatchScreen.tsx Mock move submission, dynamic maxEnergy, boost-aware energy bar
apps/tma/src/screens/MatchmakingScreen.tsx Mock cancel
apps/tma/src/screens/ResultScreen.tsx Economy breakdown section, mock result application
apps/tma/src/screens/ProfileScreen.tsx Transaction history, empty state CTA
apps/tma/src/components/MoveCard.tsx Fixed overclock badge, allow overclock plays

Game Mechanics Verified

  • 6x6 move matrix (real shared game logic, 78 tests)
  • Energy: deduction, regen (Classic/Hardcore/Chaos), cap at 100
  • Overclock: triggers at energy < cost, 30% random move replacement
  • Hidden energy: opponent shows LOW/MED/HIGH indicator
  • Round timer: 15s countdown, auto-submit on expire
  • Round cap: MAX_ROUNDS (9) prevents infinite draws
  • Boost: +20 starting energy, burn on loss, return on win
  • Economy: 100 ELM stake, 200 pool, 5% rake, payout calculation
  • ELO: rating changes on win/loss, K-factor 32
  • Draw handling: refund on max rounds tie

How to Test

cd apps/tma && npx vite --host
# Open http://localhost:5173
# Click PLAY NOW → wait 5-15s → play match → see result + economy

Screenshots

Open the app and play a match — all 6 screens are fully interactive.

Test Plan

  • Play match in Classic mode → verify regen (win+5, lose+15, draw+10)
  • Play match in Hardcore mode → verify 0 regen
  • Play match in Chaos mode → verify random regen (0-20)
  • Enable boost → verify 120 starting energy + 10 ELM extra stake
  • Win match → verify payout (190 ELM) + boost returned
  • Lose match → verify stake lost + boost burned
  • Check ProfileScreen → transaction history shows all events
  • Balance below stake → PLAY button disabled
  • Forfeit mid-match → stake lost
  • npx vitest run → 78/78 shared logic tests pass
  • npx vite build → builds successfully

🤖 Generated with Claude Code

…onomy

Replaces dead socket.ts with a comprehensive mock game engine that
simulates the entire PvP match flow with an AI opponent. Uses real
game logic from @elmental/shared for authentic gameplay.

## Mock Game Engine (mockGame.ts)
- AI opponent with 3 personalities: aggressive, conservative, adaptive
- Matchmaking simulation: 5-15 second search, random opponent names/ratings
- Full commit → reveal → resolve round flow with delays
- Energy calculation using real shared game-logic (all 3 modes)
- Overclock system: 30% random move replacement
- Round timer: 15s auto-submit on expire
- Round cap: MAX_ROUNDS (9) prevents infinite draw loops
- Match end detection + 1.5s delay for result overlay visibility

## Economy (fully mocked)
- Stake deducted on match-found (100 ELM + 10 boost if enabled)
- Winner payout: pool (200) - rake (5%) = 190 ELM
- Loser: stake forfeited, boost burned (deflationary)
- Draw (max rounds): both get refund
- Transaction ledger: every economic event logged with type/amount/description
- Balance protection: PLAY button disabled when insufficient ELM
- Forfeit: stake lost + boost burned

## Bug Fixes from Audit
- Chaos mode: now passes random chaosRoll (0-20) to calculateEnergy
  (was always defaulting to 10)
- EnergyBar maxEnergy: dynamic based on boost (120 not hardcoded 100)
- Overclock badge: shows on MoveCard when energy >= 0 but < cost
  (was dead UI — badge only showed on already-disabled cards)
- MoveCard: allows overclock plays (energy >= 0 but < cost) instead
  of fully disabling
- Round cap: MAX_ROUNDS (9) enforced, prevents infinite draw matches
- Winning round overlay: 1.5s delay before ResultScreen (was 100ms)
- Transaction amounts: boost_burn and loss now log correct negative amounts
- ProfileScreen: replaced dead "Recent Rounds" with live Transaction History
- HomeScreen: PLAY button shows stake cost, disabled when balance too low
- Removed dead socket.ts (zero imports in app)

## Store Updates
- Added: transactions[], matchStake, matchBoostStake, addTransaction()
- MatchResult: added stake, rake, boostStake, boostBurned, boostReturned,
  totalPool, winnerPayout for economy breakdown display
- EconomyTransaction type for transaction ledger

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant