Files
retur/README.md
Fredrik Johansson 6c9b313783
All checks were successful
Docker / build-and-push (push) Successful in 36s
Add real replay variety: 15 new letters, random per-day roster
Every playthrough showed the exact same fixed 30 letters in the exact
same order — no randomization anywhere in the codebase. Added 15 new
letters (3 per day, l31-l45), bringing each day's pool to 9, and
changed the engine to draw PER_DAY_COUNT (6) at random from that pool
per game instead of always using the same fixed set.

- engine.ts: buildRoster() shuffles each day's pool and takes the
  first 6; GameState now carries a `roster` (letter ids in day order)
  generated once at createState() and persisted with the rest of the
  save. lettersForDay/currentLetter read through the roster instead
  of the full LETTERS array directly.
- Save key bumped to v3 — old saves have no roster field, and
  backfilling one wouldn't match already-recorded decisions, so old
  saves are simply ignored rather than partially migrated.
- Tests rewritten: several previously asserted specific letter ids at
  specific positions, which no longer holds under randomization.
  Split into buildRoster() property tests (right count, no dupes,
  every id resolves, different seeds differ) and engine tests that
  either check general correctness or construct an explicit roster
  when a specific letter's behavior needs locking in (l22, l04).

Verified: 11/11 vitest, tsc clean, and a real 5-fresh-games browser
test confirming 5 different first-letter senders instead of the same
one every time.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 21:12:06 +02:00

47 lines
2.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Retur
**Avdelningen för obeställbara försändelser.**
A short bureaucratic supernatural sorting game. You have five shifts at a municipal dead-letter office. Read each letter, consult an expanding and occasionally contradictory rulebook, then route it to delivery, sender, Archive 9, or quarantine.
Later regulations override earlier ones. The letters know this too.
## Stack
Vanilla TypeScript + Vite. No framework, backend, or runtime dependencies. State is kept in `localStorage`.
The visual language deliberately follows `djupet`: JetBrains Mono, near-black blue panels, restrained eldritch color, compact administrative labels, and pressure expressed through a screen-edge vignette. Retur replaces Djupet's Malmö map and idle resources with a paper desk, physical stamps, and a regulation sidebar.
## Development
```bash
npm install
npm run dev # http://localhost:5691
npm run typecheck
npm test
npm run build
```
## Rules
- Inspect the sender, recipient, address, postmark, letter text, and marks.
- Select one of four routes and stamp the decision.
- New regulations arrive each morning. Later and more specific rules take precedence.
- Incorrect sorting costs composure and raises suspicion.
- A completed day restores one composure; suspicion persists.
- Survive all five days to receive a permanent position. This is not necessarily a reward.
- Each day draws 6 letters at random from a larger pool (currently 9) — every playthrough sees a different subset, so a second run doesn't mean already knowing every answer.
Keyboard: `1``4` selects a route, `Enter` stamps or continues, `?` opens help.
## Deployment
The production image is a static Vite build served by nginx. A push to `main` triggers the Gitea Actions workflow, which builds and publishes `repo.explewd.com/explewd/retur:latest` plus an immutable short-SHA tag. The deployment host pulls that image through Docker Compose.
```bash
docker compose pull
docker compose up -d
```
**Live:** [retur.games.goonk.se](https://retur.games.goonk.se)