docs: describe the tutorial

AGENTS.md and TODO.md notes for the tutorial, and the end-to-end results. A
move that ends the game is no longer explained as giving an extra turn.
This commit is contained in:
Halit Aksoy 2026-10-16 15:00:44 +03:00
parent 636127dae4
commit acd60816f7
7 changed files with 27 additions and 6 deletions

View File

@ -23,8 +23,8 @@ Online Mancala (the Turkish *Mangala* rules) with a web app, an Android/iOS app
Specs that exist: `keycloak-auth` (login, guests, tokens), `game-history` (saved games, live games, replay),
`game-clock` (5 minutes per player, ending games on time), `web-redesign` (the web app's look: themes, board,
pages), `quarkus-backend` (the backend's move from Node to Java and Quarkus) and `game-bot` (playing against a bot
at four levels).
pages), `quarkus-backend` (the backend's move from Node to Java and Quarkus), `game-bot` (playing against a bot
at four levels) and `tutorial` (rules page, lessons, hints in bot games).
## Running locally
@ -114,6 +114,9 @@ which helps to check what the server holds.
(`theme/themes.ts`) are passed to core's `ThemeManager`, which the mobile app uses with its own default themes.
- Styles that need container queries (`@container`, `cqw`), such as the board's, are plain `.css` files imported by the
component; styled-jsx 5.0 does not handle them. `BoardView` fills its container and stands upright below 600 px.
- The rules, lessons and move explanations live in `packages/core/src/tutorial`; their boards after a move come from
the engine (`getMoveOutcome`). After a rule change, run core's tests: they fail if a lesson no longer works, and
the rule texts in `en.ts`/`tr.ts` may need updating.
- When a script drives the app in Chrome, wait for the header (`.hdr`) and a few seconds after the first load before
navigating; navigating during the guest login leaves an invalid token. Open the lobby with the "New Game" button,
not by URL, or the matchmaking message goes out before the WebSocket is open.

10
TODO.md
View File

@ -65,6 +65,16 @@ See `docs/specs/game-bot`.
- [ ] Tune the levels from real games (`games.bot` holds each game's level, strength and seed)
- [ ] Try the bot on a mobile device; only the type check and the bundle were run
## Tutorial
See `docs/specs/tutorial`.
- [ ] Lessons and hints in the mobile app, once it has the new design (it has the rules screen)
- [ ] Hints that look ahead, e.g. a warning when a move lets the opponent capture (the bot's search could do it)
- [ ] Strategy lessons beyond the rules
- [ ] Tutorial progress per account instead of per device
- [ ] If the end-of-game rule changes (Game rules below), update `RuleEndOfGameText2` in `en.ts` and `tr.ts`
## Web redesign
See `docs/specs/web-redesign`.

View File

@ -144,3 +144,10 @@ Components:
a game (the clock goes on); a practice game shows hints and explanations, and a game between two people shows
none.
- Mobile: type check and bundle; the rules screen on a device when one is available.
Checked end to end in Chrome on 2026-10-16: a newcomer's banner, "Not now" hiding it, and the banner gone after the
lessons; all six lessons from the banner, the four with a wrong move first (explained, then reset) and each done;
the list showing all six done and the last lesson offering the practice game; the rules page and, during a game,
the rules panel with the clock running behind it (5:00 → 4:57); a practice game with hint chips that match the board
and an explanation of each move, hints turned off with the switch; a game between two people with hints turned on
on both devices showing no switch and no hints; the rules page and the lesson list at phone width.

View File

@ -1,6 +1,6 @@
# Tutorial: requirements
Status: approved, being implemented on branch `feature/tutorial` (based on `develop`).
Status: implemented on branch `feature/tutorial` (based on `develop`).
Scope: `packages/core`, web app; the mobile app gets the rules only (see R5).
## Goals

View File

@ -12,5 +12,5 @@ Work through the tasks in order; each ends with its tests passing and a commit.
- [x] 5. **Newcomers and practice game**: `TutorialBanner`, `markGamePlayed`, the practice game button.
- [x] 6. **Hints**: hint chips on `BoardView`, the explanation line and the "Hints" switch in bot games on `GamePage`.
- [x] 7. **Mobile rules**: `RulesScreen`, links from the help and game screens; type check and bundle.
- [ ] 8. **End to end and docs**: the Chrome tests from `design.md`; `AGENTS.md` (specs list), `TODO.md` (out of scope
- [x] 8. **End to end and docs**: the Chrome tests from `design.md`; `AGENTS.md` (specs list), `TODO.md` (out of scope
items).

View File

@ -94,7 +94,8 @@ export function explainMove(outcome: MoveOutcome, mover: Mover, t: Translate): s
} else if (outcome.capture === "emptyPit") {
sentences.push(t(`MoveExplainEmptyPit${who}`, { count: outcome.captured }));
} else if (outcome.landing === "ownStore") {
sentences.push(t(`MoveExplainExtraTurn${who}`));
// A move that ends the game gives no turn to play.
if (!outcome.endsGame) sentences.push(t(`MoveExplainExtraTurn${who}`));
} else if (outcome.landing === "opponentPit") {
sentences.push(t(`MoveExplainOdd${who}`, { count: outcome.stonesBeforeLanding + 1 }));
} else if (outcome.stonesBeforeLanding === 0) {

View File

@ -145,7 +145,7 @@ describe("explainMove", () => {
expect(explainMove(outcome([4, 4, 4, 4, 4, 4, 0, 4, 3, 4, 4, 4, 4, 1], 5), "you", translator(en)))
.toBe("Your last stone made an opponent's pit even: you took 4 stones.");
expect(explainMove(outcome([0, 0, 0, 0, 0, 1, 20, 2, 3, 1, 0, 2, 1, 18], 5), "you", translator(en)))
.toBe("Your last stone landed in your store: you play again. One side is empty, so the game is over.");
.toBe("One side is empty, so the game is over.");
});
it("explains the bot's moves from the player's side", () => {