A browser-based multiplayer game that teaches kids pathfinding and autonomous-navigation algorithms through a virtual grid game. Built with Vite + React + TypeScript and synced in real time with Firebase Realtime Database.
Live at https://mitmedialab.github.io/doodlebot-controller/ (deployed from main via
GitHub Pages).
Two players join a shared room and each controls a bot on a 16×16 grid. Players drag bots, coins, and obstacles onto the board, assign their bot a movement policy, then start — all bots execute simultaneously and the player who collects the most coins wins the phase.
The game runs as three phases that introduce planning strategies of increasing sophistication:
| Phase | Movement policy available | Notes |
|---|---|---|
| 1 | Goal-based planning (Manhattan) only | The reflex baseline is forced; the utility option is hidden. |
| 2 | Goal-based + Utility-based (Dijkstra) | Utility-based is a single-owner claim — only one player may take it (labelled unclaimed / yours / taken). |
| 3 | Goal-based + Utility-based, free choice | Any player may pick Utility-based; no claim. |
Each phase runs on a 60-second countdown and ends when the timer expires or all coins are collected. A results modal shows the per-player score and advances to the next phase (or finishes the game after phase 3).
The grid model implements three distance strategies:
- Reflex planning (Euclidean) — the default fallback; greedy straight-line distance.
- Goal-based planning (Manhattan) — greedy
|dx| + |dy|distance. - Utility-based planning (Dijkstra) — true shortest path that routes around obstacles, computed from a per-coin weighted graph. It carries a cosmetic memory/heat "cost" in the resource panel.
Only Goal-based and Utility-based are offered as radio options in the UI; Reflex is the implicit fallback when a bot has no policy set.
Three visual themes change sprites and backgrounds: None / Default (plain robots), City (cars, pizza), and School (buses, bicycles). The room creator picks the theme; it is stored on the room and applied for both players.
This is a build-based app (Node + npm required).
npm install
npm run dev # local dev server (served under base /doodlebot-controller/)
npm run build # tsc + vite build → dist/
npm run preview # serve the production build locally
npm run test:run # run the vitest suite onceOpen the dev server URL, which lands on the splash page (index.html).
index.html splash screen → "Play Game"
└─> rooms.html create a room (share the ID) or join one, creator picks a theme
└─> game.html both players auto-navigate here once the room has 2 players
└─> Phase 1 → Phase 2 → Phase 3 → Finish
Room membership drives navigation: when a room reaches 2 players, RealtimeUpdates
redirects everyone to game.html?room=<id>&option=<theme>&mode=virtual.
- Vite + React 19 + TypeScript — multi-page app (
index.html,rooms.html,game.html), each React page mounted into a single#root. - Firebase Realtime Database + Auth — multiplayer sync and anonymous player identity.
- Bootstrap 5 (CSS/markup only; modals are React-controlled, no Bootstrap JS).
- Vitest + Testing Library (jsdom) — unit and DOM component tests.
doodlebot-controller/
├── index.html / rooms.html / game.html # multi-page entry points
├── public/assets/ # sprites & backgrounds (per theme)
├── src/
│ ├── main.ts / rooms.ts # per-page entry scripts (mount React roots)
│ ├── grid/ # VirtualGrid model + graph/Dijkstra (no DOM)
│ ├── firebase/ # firebase-init (auth) + firebase-sync (RealtimeUpdates)
│ ├── sync/ # grid ↔ Firebase adapter
│ ├── game/resource-model.ts # cosmetic battery/CPU/memory sim (local, unsynced)
│ ├── ui/ # phase-manager, bot-movement, drag-drop, game-setup
│ ├── ui/react/ # GameApp, GameBoard, Sidebar, Controls, PhaseHud,
│ │ # Modals, ResourcePanel, Lobby, useGridSnapshot
│ ├── events.ts # typed event bus (gameEvents)
│ ├── types.ts # shared types + MOVEMENT_VALUES etc.
│ └── __tests__/ # vitest suites
├── vite.config.ts # base: "/doodlebot-controller/"
└── .github/workflows/deploy.yml # build + deploy to GitHub Pages
See CLAUDE.md for architecture details (state separation, the event bus, the Firebase room schema, and the React island model).
Any modern browser (Chrome, Firefox, Safari, Edge).