A 2D open-world RPG where you learn finance by living it. Built with Phaser 3, TypeScript, and Vite.
- Two playable districts: Scam Slum (starting area) and Wall Street
- Three working scammer NPCs with full branching dialogue trees — learn to spot MLMs, "double your money" cons, and fake pre-IPO allocations
- Live-simulated markets using Geometric Brownian Motion — 20 stocks across US (Apple, Tesla, NVIDIA, etc.) and India (Reliance, TCS, HDFC Bank, etc.)
- Full candlestick trading terminal with buy/sell, real-time price updates, portfolio tracking, P&L
- Behavioral Bias Coach that detects FOMO, revenge trading, and overconfidence in real time and intervenes before you make the mistake
- Echo Mode — 5 historical scenarios (Soros 1992, Harshad Mehta 1992, Michael Burry 2005, Buffett Coca-Cola 1988, FTX 2022) where you make decisions blind, then the game reveals whose footsteps you walked in
- Procedurally generated pixel art — no art assets needed, everything is drawn in code
- Full persistence via localStorage — your progress survives refresh
- Responsive UI — works on desktop and mobile browsers
npm install
npm run devOpen http://localhost:3000 and you're in the game.
Firebase SDK integration is already wired in src/systems/FirebaseAuth.ts and src/systems/PortfolioSystem.ts.
- Create your Firebase project at Firebase Console.
- Enable Authentication -> Sign-in method -> Google.
- Create a Firestore Database (start in test mode for local development).
- Add a Web app in Project settings and copy config values.
- Copy
.env.exampleto.envand fill:
cp .env.example .envRequired keys:
VITE_FIREBASE_API_KEYVITE_FIREBASE_AUTH_DOMAINVITE_FIREBASE_PROJECT_IDVITE_FIREBASE_STORAGE_BUCKETVITE_FIREBASE_MESSAGING_SENDER_IDVITE_FIREBASE_APP_ID
Then restart the dev server (npm run dev).
If keys are missing, FinSim falls back to offline/local mode automatically.
- WASD or Arrow keys — Move
- E or Space — Interact with nearby NPC/building
- P — Open portfolio
- Esc — Close any modal
- Watch the intro. Your mom lost ₹2,00,000 to a WhatsApp scam. You have ₹10,000.
- Meet the scammers. Walk around Scam Slum. There are three of them. Talk to each. Ask questions. Notice the red flags.
- Ride the train. Go to the train station (east side). Choose Wall Street.
- Meet Warren-bot. He's standing in front of the NYSE. Talk to him.
- Enter the brokerage. Walk up to the big blue building and press E.
- Buy something. Pick a stock. Buy 10 shares. Watch the chart.
- Try to trigger the bias coach. Buy a stock that just pumped 5%+ in the last 10 minutes — FOMO alert fires.
- Try Echo Mode. There's a purple "Time Machine" building in both districts. Make a blind decision on a historical trade. See whose footsteps you walked in.
- Check your portfolio. Click the "Portfolio" button top-right or press P.
finsim/
├── src/
│ ├── main.ts # Entry — wires Phaser + DOM UI
│ ├── config/constants.ts # All magic numbers live here
│ ├── types/index.ts # Shared TypeScript types
│ ├── lib/math.ts # GBM, Sharpe, Kelly, AMM, RSI, SMA
│ ├── systems/
│ │ ├── MarketEngine.ts # Live price simulation + subscribe API
│ │ ├── PortfolioSystem.ts # Cash, holdings, transactions (localStorage)
│ │ ├── BehaviorTracker.ts # Cognitive bias detection + interventions
│ │ └── DialogueSystem.ts # NPC conversations with branching
│ ├── data/
│ │ ├── stocks.ts # Stock universe (US + India)
│ │ ├── dialogues.ts # Scammer scripts, Warren-bot, etc.
│ │ └── echoScenarios.ts # 5 seeded historical trades
│ ├── entities/
│ │ ├── Player.ts # Top-down character w/ procedural sprite
│ │ ├── NPC.ts # Archetype-based NPCs
│ │ └── Building.ts # 7 building types, all drawn in code
│ ├── scenes/
│ │ ├── BootScene.ts # Loading + texture generation
│ │ ├── ScamSlumScene.ts # Starting district
│ │ └── WallStreetScene.ts # Wall Street + Dalal Street (same scene, diff market)
│ └── ui/
│ ├── styles.css
│ ├── HUDManager.ts # Top bar (cash, portfolio, district)
│ ├── TradingTerminal.ts # Full trading modal w/ candlesticks
│ └── Modals.ts # Portfolio, Bias Toast, Help, Echo Mode
├── index.html # Shell + all DOM overlays
├── package.json
├── tsconfig.json
└── vite.config.ts
Open devtools console, type finsim. and see the exposed API:
finsim.portfolio.getCash() // Current cash
finsim.portfolio.reset() // Clear portfolio
finsim.behavior.getEvents() // All logged player actions
finsim.openEcho() // Force open Echo Mode
finsim.openTerminal() // Force open trading terminal
finsim.reset() // Nuke localStorage + reload (new game)Add to src/data/echoScenarios.ts. The schema is in src/types/index.ts. Each scenario takes about 15 min to write. Target 20 total for a real library.
Currently Dalal Street shares the Wall Street scene with a different market prop. Promote it to its own scene with BSE-themed visuals and a full Harshad Mehta boss fight.
New scene, neon palette. Build a DEX interface using the ammSwap() function already in lib/math.ts. Hide one rug pull token.
Currently using GBM simulation. Swap MarketEngine.tick() with an Alpha Vantage / CoinGecko fetch. Cache in Supabase edge function to share across users.
Replace the hardcoded dialogue tree with a Claude API call. System prompt: "You are Warren Buffett. Answer this beginner's question in 2-3 sentences."
Add Supabase auth + realtime. Global leaderboard by portfolio value.
Add a virtual joystick (bottom-left) and tap-to-interact for mobile.
Current sprites are procedural. Commission pixel art from Fiverr (~$500) or use Kenney.nl asset packs to replace Player/NPC/Building draw methods.
Every trade runs through BehaviorTracker.checkPreTradeBias() before execution:
- FOMO — Flags if the stock pumped more than 5% in the last 10 candles and you're buying
- Revenge Trading — Flags if you've had 2+ consecutive losses and you're now sizing up 1.5x+ from your average
- Overconfidence — Flags if you've had 3+ wins and you're doubling your usual size
If triggered, the trade is paused and the Bias Toast appears. You can proceed or take a break. Either way, the decision is logged to behavior_events for later ML training.
Open the purple Time Machine building. The game picks a random scenario from echoScenarios.ts, shows you a chart, news headlines, and four actions — stripped of identifying details. You pick one. The game then reveals which real trader/fraudster you matched and the outcome.
The file to expand: src/data/echoScenarios.ts. Each scenario has:
contextHidden/contextRevealed— before/after identitychartData— price series (usepriceSeries()helper)actions— 4 choices, each with its own outcome descriptioncorrectActionId— the winning moveheroName,heroOutcome,lesson— the reveal contentisFraud— if true, the reveal shows in red
Mira replaces the canned bias-detection messages with personalized 1–2 sentence coaching pulled from a Cloud Function that calls Gemini 2.5 Flash. It's served by functions/src/index.ts (Firebase Functions v2) and consumed client-side by src/systems/MiraCoach.ts.
When the user is signed in and the function is reachable, the coach toast initially shows the canned LESSONS body (instant), then swaps to the Gemini response with a "Mira AI" chip the moment it arrives. If the call times out (4s) or the user is offline, the canned copy stays — gameplay never blocks on the LLM.
Cost protection (4 layers):
- Auth gate — only signed-in users hit the function.
- Per-UID rate limit (30 calls/min) on the function side.
- SHA-256 cache on bucketized inputs — repeat triggers from the same player are free for 1h server-side and 30min client-side.
- 240-char hard cap on output (≈ 60 tokens).
MIT License Copyright (c) 2026 Charanjot Singh