Engine PR 8.2: pawn promotion — last-rank move expansion + applyMove piece placement #69

Closed
opened 2026-05-16 16:04:01 +00:00 by root · 4 comments
root commented 2026-05-16 16:04:01 +00:00 (Migrated from gitlab.core-project.space)

Imported from GitHub amaurycoudr/chess-project#69, opened by @amaurycoudr on 2026-05-16 16:04 UTC.
Closed on GitHub on 2026-05-16 21:37 UTC as completed.


Parent

#67

What to build

Additive on slice 8.1: handle pawns reaching the last rank. A pawn move (push or capture) landing on the final rank expands into four Moves — one per promotion piece n/b/r/q — and applyMove lands the mover as the chosen piece instead of a pawn.

Slice 8.1 deliberately omits last-rank pawn moves; this slice adds them back, the only mechanism by which a pawn legally reaches the last rank.

Implements step 8 (partial) of docs/adr/0004-engine-slice-plan-and-king-first-piece-ordering.md.

  • Extend pseudoLegalPawnMoves in movegen.ts: a generated pawn move whose destination is on the last rank fans into four Moves with promotion set to n, b, r, q. Applies equally to straight pushes and diagonal captures.
  • Modify applyMove in rules.ts: when move.promotion is set, the mover is removed from the pawn set and added to the promotion piece's set on the destination, rather than remaining a pawn.
  • Extend rules-pawns.test.ts with promotion coverage (four-way expansion, capture-promotion, applyMove piece placement, promotion-with-check).

Move.promotion, the moveOf helper, and Game.apply's promotion-aware legality comparison already exist — no type changes.

Acceptance criteria

  • A pawn one step from the last rank, with the square ahead empty, produces exactly four pushes — promotion n/b/r/q
  • A pawn capturing onto the last rank produces four capture-promotion moves
  • Promotion expansion applies to both colors (white onto rank 8, black onto rank 1)
  • Game.apply() of a promotion move removes the pawn and places the chosen piece on the destination square
  • A capture-promotion both removes the captured piece and places the promoted piece
  • A promotion move that delivers check / mate is reported correctly by Game.status()
  • A promotion move leaving the mover's king in check is excluded
  • Non-last-rank pawn moves still carry no promotion field (no regression from 8.1)
  • Tests follow the rules-knights.test.ts / rules-pawns.test.ts style, written as vertical TDD slices
  • pnpm lint, pnpm typecheck, pnpm test, pnpm build all green from the repo root

Blocked by

  • Blocked by #68
> _Imported from GitHub [amaurycoudr/chess-project#69](https://github.com/amaurycoudr/chess-project/issues/69), opened by [@amaurycoudr](https://github.com/amaurycoudr) on 2026-05-16 16:04 UTC._ > _Closed on GitHub on 2026-05-16 21:37 UTC as completed._ <!-- github-issue:69 --> --- ## Parent #67 ## What to build Additive on slice 8.1: handle pawns reaching the last rank. A pawn move (push or capture) landing on the final rank expands into four `Move`s — one per promotion piece `n`/`b`/`r`/`q` — and `applyMove` lands the mover as the chosen piece instead of a pawn. Slice 8.1 deliberately omits last-rank pawn moves; this slice adds them back, the only mechanism by which a pawn legally reaches the last rank. Implements step 8 (partial) of `docs/adr/0004-engine-slice-plan-and-king-first-piece-ordering.md`. - Extend `pseudoLegalPawnMoves` in `movegen.ts`: a generated pawn move whose destination is on the last rank fans into four `Move`s with `promotion` set to `n`, `b`, `r`, `q`. Applies equally to straight pushes and diagonal captures. - Modify `applyMove` in `rules.ts`: when `move.promotion` is set, the mover is removed from the pawn set and added to the promotion piece's set on the destination, rather than remaining a pawn. - Extend `rules-pawns.test.ts` with promotion coverage (four-way expansion, capture-promotion, `applyMove` piece placement, promotion-with-check). `Move.promotion`, the `moveOf` helper, and `Game.apply`'s promotion-aware legality comparison already exist — no type changes. ## Acceptance criteria - [ ] A pawn one step from the last rank, with the square ahead empty, produces exactly four pushes — `promotion` `n`/`b`/`r`/`q` - [ ] A pawn capturing onto the last rank produces four capture-promotion moves - [ ] Promotion expansion applies to both colors (white onto rank 8, black onto rank 1) - [ ] `Game.apply()` of a promotion move removes the pawn and places the chosen piece on the destination square - [ ] A capture-promotion both removes the captured piece and places the promoted piece - [ ] A promotion move that delivers check / mate is reported correctly by `Game.status()` - [ ] A promotion move leaving the mover's king in check is excluded - [ ] Non-last-rank pawn moves still carry no `promotion` field (no regression from 8.1) - [ ] Tests follow the `rules-knights.test.ts` / `rules-pawns.test.ts` style, written as vertical TDD slices - [ ] `pnpm lint`, `pnpm typecheck`, `pnpm test`, `pnpm build` all green from the repo root ## Blocked by - Blocked by #68
root commented 2026-05-16 16:59:23 +00:00 (Migrated from gitlab.core-project.space)

Imported from a GitHub comment by @amaurycoudr on 2026-05-16 16:59 UTC.

Implemented by Sandcastle on branch sandcastle/sequential-reviewer/1778950044172 — awaiting review. Adds last-rank move expansion (4 promotion variants per push/capture) and applyMove promotion handling.

> _Imported from a [GitHub comment](https://github.com/amaurycoudr/chess-project/issues/69#issuecomment-4467532423) by [@amaurycoudr](https://github.com/amaurycoudr) on 2026-05-16 16:59 UTC._ <!-- github-comment:4467532423 --> Implemented by Sandcastle on branch `sandcastle/sequential-reviewer/1778950044172` — awaiting review. Adds last-rank move expansion (4 promotion variants per push/capture) and applyMove promotion handling.
root commented 2026-05-16 17:26:54 +00:00 (Migrated from gitlab.core-project.space)

Imported from a GitHub comment by @amaurycoudr on 2026-05-16 17:26 UTC.

Promoted to branch feat/engine-pr-8-1-pawns-pushes-captures-attack-mask-legality-wiring-68 (PR #72), not yet merged to main. A dependent slice should git fetch origin feat/engine-pr-8-1-pawns-pushes-captures-attack-mask-legality-wiring-68 and branch off it.

> _Imported from a [GitHub comment](https://github.com/amaurycoudr/chess-project/issues/69#issuecomment-4467607508) by [@amaurycoudr](https://github.com/amaurycoudr) on 2026-05-16 17:26 UTC._ <!-- github-comment:4467607508 --> Promoted to branch `feat/engine-pr-8-1-pawns-pushes-captures-attack-mask-legality-wiring-68` (PR #72), not yet merged to main. A dependent slice should `git fetch origin feat/engine-pr-8-1-pawns-pushes-captures-attack-mask-legality-wiring-68` and branch off it.
root (Migrated from gitlab.core-project.space) closed this issue 2026-05-16 21:37:08 +00:00
root commented 2026-10-13 08:38:30 +00:00 (Migrated from gitlab.core-project.space)

mentioned in issue #71

mentioned in issue #71
root commented 2026-10-13 10:20:26 +00:00 (Migrated from gitlab.core-project.space)

mentioned in commit ed7e97de1c

mentioned in commit ed7e97de1caa39daf1aa5d5857e943a4108ff249
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
amaurycoudr/chess-project#69
No description provided.