A C++ port of Magicor (original by Peter Gebauer, public domain), using the Whiskers Engine (OpenGL, SDL2).
- CMake 3.10 or later
- A C++17 compiler
- SDL2
- OpenGL 3.3 Core
- SDL2_mixer
On macOS with Homebrew, typical packages are sdl2, sdl2_mixer, and a GLM include path the engine can find (see Whiskers Engine CMake notes).
- Emscripten (
emcmake,em++on yourPATH) - Ninja (the CMake wasm preset uses the Ninja generator)
From the repository root:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build buildThe binary is build/magicor (or build/Release/magicor on some multi-config generators). Run it from the repo root (or ensure assets/data resolves) so game data under assets/data/ is found.
Optional: -DMAGICOR_DEBUG_PROTOCOL=OFF disables the JSON stdio debug protocol on native builds.
Always configure through emcmake so the Emscripten toolchain is applied:
emcmake cmake --preset wasm
cmake --build --preset wasmArtifacts are written to build-wasm/:
magicor.html— open in a browser via http:// (notfile://)magicor.jsmagicor.wasmmagicor.data— preloadedassets/datatree
Serve the directory locally, for example:
cd build-wasm && python3 -m http.serverThen visit the printed URL and open magicor.html. Deploy all four files together; keep the same relative paths on your host.
If the console shows WebGL context creation failed with Sandboxed = yes or GL_VENDOR = Disabled, the page is not running in a GPU-capable WebGL context. That usually means an embedded or sandboxed browser (for example some in-editor preview panels), not a bug in the build.
Use a normal desktop browser tab: open http://localhost:…/magicor.html in Chrome, Firefox, or Edge launched from the OS, not the IDE’s built-in browser.
Chrome DevTools MCP: configure chrome-devtools in Cursor’s MCP settings and ensure the MCP server starts; the agent can only use it when that server is connected.
The native build with the JSON debug protocol can be driven from Python: see tools/mcp_server.py (MCP) and tools/playtest_levels.py (batch).
| Command (from repo root) | Purpose |
|---|---|
python3 tools/playtest_levels.py |
For each world level: load + walk R/L from spawn, then a third load with a one-tile nudge and Space to smoke-test ice create/destroy; writes tools/playtest-report.txt. Use --no-ice-smoke to skip the ice pass. |
python3 tools/playtest_levels.py --no-mobility --solve --solve-seconds 90 |
For each level: run a heuristic policy to try to extinguish all fires (sim time budget per level, not real wall time); e.g. --report tools/playtest-solve.txt. |
A true solver (search, planning, or learning) is not implemented yet: --solve is a greedy policy. Results vary; see the latest numbers in the report you generate. The design note specs/PLAYTEST_AND_SOLVER.md explains current tooling, what “passing” means, how to iterate the script, and higher-level approaches (engine as forward model, abstract state, BFS/IDA*, MCTS, macro-actions, etc.).
For AI-assisted exploration in Cursor, see AGENTS.md and the .cursor/rules/magicor-playtest-exploratory.mdc rule (avoid abusing teleport_entity for bug repro).
CMake does not automatically relink when only files under assets/data/ change. After adding or updating assets, force a fresh link output and rebuild:
rm -f build-wasm/magicor.html build-wasm/magicor.js build-wasm/magicor.wasm build-wasm/magicor.data
cmake --build --preset wasmGame data and original design credit the Magicor project and its license. Third-party code (engine, fonts under assets/data/fonts, etc.) has its own license files where applicable.