Repository navigation
Conversation
Arimaa currently requires a player to type the raw step list of a turn by hand (`Ee2e3, Ee3e4`, pushes and pulls spelled out with `(x...)` captures). This replaces that with click/arrow-based move entry: click a piece, then the square it should end the turn on (an enemy piece too, for a push or pull), and the engine works out the steps. Every legal turn is enterable this way; typing is never required. Moves are now recorded in Lightvector notation (`Ee2e4`, `Rc2c3 Dd2x`), which names pieces and outcomes rather than steps. Existing recorded games are unaffected: the old step-list format is still read, and replays trusted regardless of what the current validator would accept from a new submission. Move entry ---------- `handleClick` builds up arrows (`<piece><from><to>`), "holds" (a piece confirmed to end where it stands: `<piece><sq><sq>`, drawn for round trips, detours, and forcing survival off a trap), and capture marks (`<piece><sq>x`) from clicks, and resolves them against every legal turn up to 4 steps deep. Resolution is strict by default (a token set must pick out exactly one turn) with a lenient fallback that breaks a tie by fewest own captures, then most enemy captures -- this is what lets two clicks usually be enough even though Arimaa turns can take up to 4 steps. A selection never blocks submission: move() drops a trailing selection rather than getting stuck, and `complete` is only ever 1 (auto-submit) when nothing about the turn had to be inferred. A rejected drawing now says why instead of just "no legal move matches": the opponent's piece (also what a click lands on when the previous turn hasn't been completed yet), a piece boxed in or frozen, a rabbit sent backward, chained typed steps that read as one piece visiting two destinations, or arrows that each work alone but not together. Typed input still works: Lightvector notation directly (including `Dir+` step tokens clicks never produce), or the old step-list format. Compatibility ------------- The recorded-move format changes, but old recorded games do not need to re-validate under the new rules to replay: a trusted move() call plays a turn (or a legacy step list) directly, without going back through validateMove. The version number is unchanged -- nothing about how a previously-recorded game is interpreted has changed, only what a new submission is asked to look like and how strictly it's checked. Two moves the step validator incorrectly allowed are now rejected for new submissions: a push completed by a piece no stronger than the one it's pushing, and a pull that ends the pulled piece anywhere but the square the puller just vacated. Recorded games containing either (a handful of plies across the full corpus of recorded games) still replay unchanged, since replay never re-validates. Performance ----------- The step-sequence resolver (iterative deepening with an admissible heuristic bound) got measurably slower on some inputs once "holds" were added, since a piece that ends where it started can't be pruned by the step-count bound. A transposition memo (per depth, keyed on the board plus each moved piece's visited squares, off whenever a step token is present) plus a cheaper heuristic evaluation (cached witness lists, a distance table, early-outs once a bound already exceeds the remaining budget) brought the worst observed click, from a stress test over recorded games, down from ~0.9s to ~50-190ms, with no change to what the search finds (checked against 3,000+ random positions with pruning on and off). Testing ------- test/games/arimaa.test.ts: 49 tests -- notation parsing, strict/lenient resolution, a randomized pruned-vs-unpruned equivalence check, arrow/hold/capture-mark entry (including forced arrows, detours, and trap-mark conversion), legacy-format compatibility (a submission the rules no longer allow is rejected, but the same string still replays trusted), 5 recorded games replayed move-by-move, and an independent exhaustive enumerator that checks every legal turn from several representative positions is reachable purely by clicks. Full suite (`npx mocha`): 1502 passing, 1 pre-existing failure (storisende.storage.test.ts, a fixed 2000ms timeout on a large board) in a file this change does not touch; reproduces identically on a clean develop checkout. `npm run lint` (Weblate key check, game-names locale check, eslint): clean. `tsc --noEmit` on the changed files: clean. Stress test: replayed all 449 games / 12,590 movement turns of a recorded-game corpus through both the old and new engines. Mean clicks per turn (old vs. new, Complete Move included): 7.39 -> 4.67. All but 3 turns (the illegal legacy plies above) are enterable purely by clicks under the new model. Also manually verified the click flows end-to-end by driving the actual playground/ app in headless Chromium (setup, single/multi-step turns, step-by-step re-selection, holds, an ambiguous drawing, a rotated board). locales/en/apgames.json and locales/eo/apgames.json updated for the new and changed validation/instruction strings. Other locales are untouched -- they're machine-managed and will pick these up after merge. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016YPW35p91rLsBRPSz63L1k
Member
|
How does this handle games that are in progress? Will players see the notation change? And can you tell me what's different between current and lightvector format? It looks pretty similar to me. What are some examples of changes? |
Member
|
AI explained the differences :) I'll be sure to announce the change when it's finally released. Will merge and you can test on Dev. |
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Enter moves by clicking pieces and where you want them to go. Should save clicks and be intuitive. I should write a more detailed entry on the Wiki, but mostly you should just be able to use the input system without understanding all the details of how it decides everything.
Moves are now recorded in Lightvector notation (
Ee2e4,Rc2c3 Dd2x), which names pieces and outcomes rather than steps. Existing recorded games are unaffected: the old step-list format is still read, and replays trusted regardless of what the current validator would accept from a new submission. Just think of it as like Algebraic Notation from chess, and it becomes pretty intuitive.Also fixed some preexistent bugs.
I've tested it on the developer playground and it seems perfect, the two things I really want to test on the dev server:
Move entry
handleClickbuilds up arrows (<piece><from><to>), "holds" (a piece confirmed to end where it stands:<piece><sq><sq>, drawn for round trips, detours, and forcing survival off a trap), and capture marks (<piece><sq>x) from clicks, and resolves them against every legal turn up to 4 steps deep. Resolution is strict by default (a token set must pick out exactly one turn) with a lenient fallback that breaks a tie by fewest own captures, then most enemy captures -- this is what lets two clicks usually be enough even though Arimaa turns can take up to 4 steps. A selection never blocks submission: move() drops a trailing selection rather than getting stuck, andcompleteis only ever 1 (auto-submit) when nothing about the turn had to be inferred.A rejected drawing now says why instead of just "no legal move matches": the opponent's piece (also what a click lands on when the previous turn hasn't been completed yet), a piece boxed in or frozen, a rabbit sent backward, chained typed steps that read as one piece visiting two destinations, or arrows that each work alone but not together. Typed input still works: Lightvector notation directly (including
Dir+step tokens clicks never produce), or the old step-list format.Compatibility
The recorded-move format changes, but old recorded games do not need to re-validate under the new rules to replay: a trusted move() call plays a turn (or a legacy step list) directly, without going back through validateMove. The version number is unchanged -- nothing about how a previously-recorded game is interpreted has changed, only what a new submission is asked to look like and how strictly it's checked.
Two moves the step validator incorrectly allowed are now rejected for new submissions: a push completed by a piece no stronger than the one it's pushing, and a pull that ends the pulled piece anywhere but the square the puller just vacated. Recorded games containing either (a handful of plies across the full corpus of recorded games) still replay unchanged, since replay never re-validates.
Performance
The step-sequence resolver (iterative deepening with an admissible heuristic bound) got measurably slower on some inputs once "holds" were added, since a piece that ends where it started can't be pruned by the step-count bound. A transposition memo (per depth, keyed on the board plus each moved piece's visited squares, off whenever a step token is present) plus a cheaper heuristic evaluation (cached witness lists, a distance table, early-outs once a bound already exceeds the remaining budget) brought the worst observed click, from a stress test over recorded games, down from ~0.9s to ~50-190ms, with no change to what the search finds (checked against 3,000+ random positions with pruning on and off).
Testing
test/games/arimaa.test.ts: 49 tests -- notation parsing, strict/lenient resolution, a randomized pruned-vs-unpruned equivalence check, arrow/hold/capture-mark entry (including forced arrows, detours, and trap-mark conversion), legacy-format compatibility (a submission the rules no longer allow is rejected, but the same string still replays trusted), 5 recorded games replayed move-by-move, and an independent exhaustive enumerator that checks every legal turn from several representative positions is reachable purely by clicks.
Full suite (
npx mocha): 1502 passing, 1 pre-existing failure (storisende.storage.test.ts, a fixed 2000ms timeout on a large board) in a file this change does not touch; reproduces identically on a clean develop checkout.npm run lint(Weblate key check, game-names locale check, eslint): clean.tsc --noEmiton the changed files: clean.Stress test: replayed all 449 games / 12,590 movement turns of a recorded-game corpus through both the old and new engines. Mean clicks per turn (old vs. new, Complete Move included): 7.39 -> 4.67. All but 3 turns (the illegal legacy plies above) are enterable purely by clicks under the new model. Also manually verified the click flows end-to-end by driving the actual playground/ app in headless Chromium (setup, single/multi-step turns, step-by-step re-selection, holds, an ambiguous drawing, a rotated board).
locales/en/apgames.json and locales/eo/apgames.json updated for the new and changed validation/instruction strings. Other locales are untouched -- they're machine-managed and will pick these up after merge.