Add Nine Men's Morris

Nine pieces each on twenty-four points: place them, then move them, and
every line of three takes an enemy piece off the board. Two pieces left,
or no legal move, and the game is over. See docs/RULES-morris.md.

The board is numbered ring * 8 + index, so its geometry falls out
arithmetically rather than being typed in as a table of twenty-four
rows: neighbours around a square are the index either side, the ladders
between squares run through the odd indices alone, and a mill is three
consecutive points centred on an odd one. A table would say the same
thing and could be wrong in one row.

A turn is one move object — the piece placed or stepped, and the enemy
piece taken when that closes a mill. Generating the removal as part of
the move rather than as a turn of its own means there is no moment where
a player is halfway through a turn, so a device that drops off the
network between closing a mill and choosing what to take cannot leave
the table stuck, and the search counts one ply for what is one decision.

Three rules about mills are easy to get backwards and all three are
tested: the piece that arrives is what closes a mill, so stepping out
takes nothing and stepping back in pays again; a slide along the line
being completed is not a mill, because the third piece it needs is the
one that just moved; and a piece in a mill is spared unless every enemy
piece is in one, without which a player could never be reduced and the
game would not end.

The AI is negamax with alpha-beta and iterative deepening over the same
rules engine, with a node budget so the placing phase does not stall a
phone. It has no quiescence tail and does not need one: there are no
exchanges in Morris. Its evaluation knows that being down to three is
dangerous even with flying on — without that term the search reads three
pieces going anywhere as freedom and starts steering towards losing
pieces to get there, which is a real game it would throw away.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_019Pr6B8xDDtJJcb6WJMw7Ud
This commit is contained in:
Claude
2026-08-07 05:52:26 +00:00
parent e3c311f8b4
commit 94b51347c3
12 changed files with 2116 additions and 4 deletions
+5 -3
View File
@@ -5,12 +5,12 @@ or against other people over Wi-Fi (LAN).
## What works today
The app shell is complete and nine games are playable end to end:
The app shell is complete and ten games are playable end to end:
| | |
| --- | --- |
| **Playable** | Euchre, Kaiser, President, Golf, Wizard, Crazy 8s, Sequence, Chess, Ta Yü |
| **Listed, not yet implemented** | Mastermind, Backgammon, Checkers, Nine Men's Morris, Pirates and Bulgars |
| **Playable** | Euchre, Kaiser, President, Golf, Wizard, Crazy 8s, Sequence, Chess, Ta Yü, Nine Men's Morris |
| **Listed, not yet implemented** | Mastermind, Backgammon, Checkers, Pirates and Bulgars |
Unimplemented games appear in the menu marked *Coming soon* **on dev builds
only** — a production release lists just the games that can actually be played,
@@ -269,6 +269,7 @@ game:
- [Wizard](docs/RULES-wizard.md)
- [Crazy 8s](docs/RULES-crazy8s.md)
- [Chess](docs/RULES-chess.md)
- [Nine Men's Morris](docs/RULES-morris.md)
- [Ta Yü](docs/RULES-tayu.md) — **note the caveats about the reconstruction**:
the game is out of print and the rulebook could not be obtained, so the
document says which parts are attested and which were derived
@@ -287,6 +288,7 @@ game/ rules engines and AI — pure Kotlin, no Android, unit-tested
wizard/ Wizard model, rules, AI
crazyeights/ Crazy 8s model, rules, AI
chess/ Chess model, FEN, move generation, search
morris/ Nine Men's Morris board geometry, mills, rules, search
tayu/ Ta Yü tile geometry, river rules, scoring, AI
net/ wire protocol, LAN transport, lobby, match driver
score/ scorekeeper sheet — pure Kotlin, unit-tested — and its store