Files
ProLibertateGames/docs/RULES-chess.md
T
Claude d6e237ce4a Add chess
The full game: castling with every condition, en passant including the
case where taking would expose your own king, promotion to any of the
four, pins, checkmate, stalemate, insufficient material, the fifty-move
rule and threefold repetition.

Move generation is checked against the published perft counts rather
than against hand-written cases — the opening array to depth four
(197,281 positions) plus four standard test positions chosen precisely
because they break generators. Those counts are exact, so matching them
leaves very little room for a rule to be subtly wrong.

The opponent is a negamax search with alpha-beta, iterative deepening
and a capture-only quiescence tail, at three strengths. The quiescence
tail is the part that stops it hanging pieces: a fixed-depth search that
stops mid-exchange scores the position as though the recapture never
comes.

Two supporting changes:

The AI now thinks off the caller's thread. A card AI answers instantly,
but a chess search runs for a second or more, and the match controller's
scope belongs to the screen — searching there would freeze the board it
is drawn on.

Offline setup can seat the local player somewhere other than seat 0,
which is what lets you play Black. Seat 0 is White by definition, so
choosing a colour has to choose a seat.

FEN is read and written, so a table can start from a set position.

203 engine tests pass locally.
2026-08-06 13:34:31 +00:00

85 lines
3.6 KiB
Markdown

# Chess — implemented rules
The full game, not a subset. This is the ruleset the engine enforces. Anything
marked **toggle** is in the game setup screen.
## Table
Two players. Seat 0 is always White; choosing to play Black in setup puts you in
seat 1 and turns the board round so your pieces are still at the near edge.
## Movement
All of it, including the parts that are usually left out:
- **Castling**, both sides, with every condition: the king and the rook must not
have moved, the squares between them must be empty, and the king may not
castle out of check, through an attacked square, or into check. The b-file
square may be attacked on the queen's side — the king does not cross it.
- **En passant**, on the move immediately after a pawn steps two squares and
only then. It is refused when taking would expose your own king, which is the
one case a naive implementation gets wrong.
- **Promotion** to queen, rook, bishop or knight, chosen when the pawn arrives.
- **Pins** — a piece that shields its own king may not step off the line.
Rights are given up correctly: a rook that moves loses its castling right, and
so does a rook captured on its own corner.
## How a game ends
| Ending | When |
| --- | --- |
| Checkmate | No legal move, and in check |
| Stalemate | No legal move, and not in check |
| Insufficient material | Neither side has enough to mate, whatever either plays |
| Fifty-move rule | A hundred half-moves with no capture and no pawn move — **toggle** |
| Threefold repetition | The same position, side to move and rights, three times — **toggle** |
Insufficient material covers bare kings, a king and one minor piece, and two
bishops on the same colour square. King and two knights is *not* included: it
cannot be forced, but it can happen with cooperation, so it is not a dead
position.
Both draw rules apply automatically rather than needing a claim. Switch either
off in setup for a game that runs until somebody is mated.
## Notation
The move list is ordinary algebraic: `e4`, `Nf3`, `exd5`, `O-O`, `a8=Q+`,
`Ra8#`. Two pieces that can reach the same square are told apart by file, or by
rank when they share a file, or by the whole square when they share both.
## Positions
The engine reads and writes FEN, so a table can start from a set position rather
than the opening array — a puzzle, or an adjourned game.
## What the computer opponent does
A negamax search with alpha-beta pruning, iterative deepening, and a
capture-only quiescence tail. The quiescence tail is what stops it giving pieces
away: a search that simply stops after a fixed number of moves scores a position
in the middle of an exchange as though the recapture never comes.
Evaluation is material plus piece placement, with a term in bare endgames that
drives the losing king towards the edge — without it a won endgame just shuffles.
**Toggle** for three strengths:
| Level | Search | Plays |
| --- | --- | --- |
| Casual | 2 ply | Takes any move within about two thirds of a pawn of the best one |
| Club | 3 ply | Nearly always the best move it can see |
| Strong | 4 ply | The best move it can see |
Every level is capped by a node budget, so no single move can hang the app on a
sharp position — it plays the best move from the last depth it finished.
## Testing
Move generation is checked against the published **perft** counts: the exact
number of positions reachable at a given depth. The opening array is verified to
depth four (197,281 positions), along with four standard test positions chosen
because they break generators — castling through check, en passant that would
expose a king, promotion with capture, and heavily pinned pieces.