# aspirin 15-puzzle (sliding 1-15) for the Ontrol **Orion** (800x480), built only from stock Sedona kits (`control`, `ontrolControl`, `ontrolOx`, `ontrolOrion`), so it runs on the stock simulator. | App | What it does | |---|---| | `aspirin.sax` / `app-ORION-aspirin.zip` | Playable game: auto-shuffle at start, tap a tile next to the gap to slide it, SHUFFLE button, move counter, SOLVED! | | `aspirin_solver.sax` / `app-ORION-aspirin_solver.zip` | Demo: shuffles 30 moves, then an auto solver plays one move per second until SOLVED! (it records the shuffle and replays the inverse moves) | ## Run in the simulator `simulatorLauncher.exe` → folder button → pick a `app-ORION-*.zip` → Start Simulator. The simulator is headless; to watch the screen run `viewer\run_viewer.cmd` (live view over SOX as `guest`, display only). ## Build ```bash python build.py # gen .sax -> sedonac .sab -> launcher backup zips (both apps) python verify_logic.py # offline scan-engine model test of the game python verify_logic.py --solver ``` `gen_aspirin.py` holds layout, colours, shuffle length (`SHUFFLE_MOVES`) and solver delay (`SOLVE_DELAY`). Paths to the Sedona install are at the top of `build.py`. ## How it works - Each tile is a `PushButtonLabel` whose `x`/`y` are linked from logic, so tiles move. - Tile state = offset from home cell held in `ADemux2` latches; blank cell = 3 - sum(offsets). - A tile moves on a one-scan `OneShot` when it is next to the blank and touched (or picked by the shuffle); it latches the blank's cell and the blank follows automatically. - Shuffle uses a logistic-map RNG made of `Reset`/`Mul2` blocks; only legal moves, so always solvable. - Solved = blank home and the weighted sum of tile offsets is 0 (rearrangement inequality).