explodorama / files / CONTRIBUTING.md
CONTRIBUTING.md
7ce1fb51 2026-10-23 Pavel Safronov | 1 | # Contributing to Explodorama |
| 2 | ||
8711e8e5 2026-10-27 Pavel Safronov | 3 | Thank you for wanting to help! The project lives at |
2f667e95 2026-10-27 Pavel Safronov | 4 | [code.fuzzyworld.net](https://code.fuzzyworld.net/explodorama/), which has no issue tracker or |
8711e8e5 2026-10-27 Pavel Safronov | 5 | merge requests. Bug reports and playtest notes are welcome through the game's **report** |
| 6 | link, which opens a prefilled email. Code contributions arrive by email too: share a branch | |
| 7 | from any git host, or send a `git format-patch`, to `contrib-68uq+explodorama@fuzzyworld.net` | |
| 8 | ([how to contribute](https://code.fuzzyworld.net/contribute/)). | |
7ce1fb51 2026-10-23 Pavel Safronov | 9 | |
| 10 | ## Reporting a bug | |
| 11 | ||
2f667e95 2026-10-27 Pavel Safronov | 12 | Send a report and include: |
7ce1fb51 2026-10-23 Pavel Safronov | 13 | |
| 14 | - what you did, what you expected, and what happened instead; | |
| 15 | - the **seed** (shown in the menu, and on the game-over and victory banners) and the level — | |
| 16 | with the seed, the same board can be replayed with `?seed=<number>`; | |
| 17 | - the device and browser, and a screenshot if you can. | |
| 18 | ||
| 19 | ## Getting set up | |
| 20 | ||
2f667e95 2026-10-27 Pavel Safronov | 21 | You need Node.js 22. |
7ce1fb51 2026-10-23 Pavel Safronov | 22 | |
| 23 | ```sh | |
| 24 | npm install | |
| 25 | npm run dev # http://localhost:5173, plus a QR code for a phone on the same Wi-Fi | |
| 26 | npm test # Vitest | |
| 27 | npm run build # type-check and build into dist/ | |
52d68b59 2026-10-24 Pavel Safronov | 28 | npm run preview # serve the build, with a QR code for a phone on the same Wi-Fi |
7ce1fb51 2026-10-23 Pavel Safronov | 29 | npm run screenshots # build, then photograph the game into docs/screenshots/ (Playwright) |
| 30 | ``` | |
| 31 | ||
52d68b59 2026-10-24 Pavel Safronov | 32 | **Seeing what went wrong:** under `npm run dev`, everything the game writes to the browser |
| 33 | console — and every error, caught or not — is printed in the terminal running `npm run dev`, | |
| 34 | marked `(client)`, from any device, including a phone on the Wi-Fi. An error while drawing a | |
| 35 | frame or playing a turn is caught, logged with its stack and the device (`src/devlog.ts`), and | |
| 36 | the game carries on instead of freezing. | |
| 37 | ||
18ff790e 2026-10-24 Pavel Safronov | 38 | The URL parameters listed in the README (`?seed`, `?level`, `?charges`, `?dev`, |
| 39 | `?immortal`, `?demo`) are the quickest way to reach the situation you are working on. | |
7ce1fb51 2026-10-23 Pavel Safronov | 40 | |
8711e8e5 2026-10-27 Pavel Safronov | 41 | ## Before you send a change |
7ce1fb51 2026-10-23 Pavel Safronov | 42 | |
2f667e95 2026-10-27 Pavel Safronov | 43 | 1. **`npm test` and `npm run build` both pass.** `npm run deploy` runs exactly these two, |
| 44 | and only publishes when they pass. | |
7ce1fb51 2026-10-23 Pavel Safronov | 45 | 2. **Rule changes come with tests.** Game rules live in `src/sim/` and are tested in `test/`. |
| 46 | 3. **The docs are up to date.** A change a player can notice belongs in the README and in | |
| 47 | [CHANGELOG.md](CHANGELOG.md) under *Unreleased*. A change to the design or to a recorded | |
| 48 | decision also updates [PLAN.md](PLAN.md) or [decisions.md](decisions.md). | |
| 49 | 4. **Screenshots are refreshed** with `npm run screenshots` if the change alters how the game | |
| 50 | looks. | |
| 51 | ||
| 52 | ## How the code is laid out | |
| 53 | ||
| 54 | The README's *How it's built* section describes the layout. The rules that matter most: | |
| 55 | ||
| 56 | - **`src/sim/` stays pure and deterministic.** No rendering, no DOM, no `Math.random()`: | |
| 57 | every random choice comes from the seed, so a run's seed plus its actions always replay to | |
| 58 | the same state. | |
| 59 | - **Bump `SIM_VERSION`** in [src/sim/record.ts](src/sim/record.ts) whenever a rule change | |
| 60 | would make an old record replay differently. Saved runs from another version are dropped | |
0b25f1ef 2026-10-24 Pavel Safronov | 61 | rather than replayed wrongly. Note the bump in the changelog, and update the version near |
| 62 | the top of the README: it is the game's version, also shown in the menu. | |
7ce1fb51 2026-10-23 Pavel Safronov | 63 | - **Rendering** (`src/render/`) and the **HTML UI** (`src/ui/`) only read the state and the |
| 64 | events that `step()` returns; they never change the rules. | |
00ad7d0a 2026-10-24 Pavel Safronov | 65 | - **Movement on screen comes from the change of state, not from events.** The player's and the |
| 66 | enemies' moves are worked out from their tile before and after a turn (`playerTransition` in | |
| 67 | `render/effects.ts`), and a pose (hit, jump, crouch, dying) starts only once the move is done. | |
| 68 | Something else happening in the same turn then can't skip the move. Keep new animations to | |
| 69 | that pattern, and add a case to `test/animation.test.ts`. | |
7ce1fb51 2026-10-23 Pavel Safronov | 70 | |
| 71 | ## Art and other assets | |
| 72 | ||
| 73 | - The game uses art from [Kenney](https://www.kenney.nl) packs only, under CC0. Please ask in | |
| 74 | an issue before bringing in a different pack or another artist's work. | |
| 75 | - Copy files **unchanged and under the pack's own file names** into the matching | |
| 76 | `assets/kenney*/` folder, and keep the pack's licence file next to them. | |
| 77 | - Icons with a modifier badge are made from those files by | |
| 78 | [tools/compose-icons.sh](tools/compose-icons.sh) (needs ImageMagick 7) into | |
| 79 | `assets/composed/`, not drawn by hand. The results are committed. | |
| 80 | ||
| 81 | ## Licence | |
| 82 | ||
| 83 | By contributing, you agree that your code is released under the project's | |
| 84 | [MIT licence](LICENSE). Kenney's art is not covered by it; it stays under CC0. |