Turn-Based Strategy Board
Problem
Design StrategyBoard for a compact two-player board game played on a fixed 5 by 5 grid. The pieces use familiar king, rook, and knight movement, while one match owns the position, current side, move history, and final outcome.
Requirements
- Configured position. Public constructor inputs use the declared non-null value types; null arguments, null piece entries, and null value-object fields are outside the cross-language API and are not judged. Copy the supplied position. Accept exactly one king per side and at most two rooks and two knights per side, with unique in-bounds squares, valid strings, and neither king initially attacked. Reject invalid strings, coordinates, occupancy, counts, or initial attacks with the runtime's invalid-argument exception.
- Piece movement. A king moves one square in any direction. A rook moves a positive distance orthogonally through empty intermediate squares. A knight moves two squares on one axis and one on the other, regardless of intermediate occupancy. No piece may land on a friendly piece or capture a king.
- Legal turns. Only the current side may move. A move must follow its piece rule and leave that side's king unattacked. A square is attacked when an opposing piece can reach it by its base movement and blocking rule, without testing that opposing piece's own king safety. A successful move applies an optional capture, appends one history entry, and changes the current side. A rejected move changes no state.
- Legal-move query.
legalMovesreturns row-major destinations only for a current-side piece in an ongoing match. It returns an empty list for an empty square, an opposing piece, or a completed match, and never changes match state. - Terminal outcomes. Construction records stalemate when the starting side has no legal move. After a successful move, the mover wins by checkmate if the next side has no legal move and its king is attacked; the result is stalemate if it has no legal move and its king is not attacked. The current side may instead end an ongoing match by resigning, which awards the win to the opposite side. Check alone does not complete a match.
- Stable completion. After completion,
moveandresignreturnfalse, legal-move queries return an empty list, history stays unchanged, and the outcome never changes.
API
Value types
| Type | Fields |
|---|---|
PieceSpec | side: string, type: string, row: int32, column: int32 |
Position | row: int32, column: int32 |
MoveRecord | turnNumber: int32, side: string, pieceType: string, fromRow: int32, fromColumn: int32, toRow: int32, toColumn: int32, capturedType: string |
Allowed sides are "white" and "black". Allowed piece types are "king", "rook", and "knight". capturedType is "none", "rook", or "knight". Arrays and their contained values returned by the API are detached snapshots.
| Signature | Returns | Behavior |
|---|---|---|
StrategyBoard(pieces: PieceSpec[], startingSide: string) | New match | Validates and copies the configured position, then checks for initial stalemate. |
move(fromRow: int32, fromColumn: int32, toRow: int32, toColumn: int32) | boolean | Applies one legal current-side move and returns true; returns false for rule-based rejection. |
legalMoves(row: int32, column: int32) | Position[] | Returns legal destinations in row-major order under the query rule. |
history() | MoveRecord[] | Returns successful moves in chronological order. Turn numbers start at 1; resignation and rejected moves add no entry. |
resign() | boolean | Ends an ongoing match with the opposite side winning by resignation and returns true; returns false after completion. |
outcome() | string | Returns "ongoing", "white-won-checkmate", "black-won-checkmate", "draw-stalemate", "white-won-resignation", or "black-won-resignation". |
Coordinates passed to public methods must be in [0, 4]. An out-of-range coordinate throws Python ValueError, Java IllegalArgumentException, or C++ std::invalid_argument before any state changes. Construction uses the same language-specific exception for an invalid configuration within the public input domain. Trusted drivers reject malformed testcase transport before calling learner code.
Examples
Start with the white king at (2,1), a white rook at (4,2), the black king at (0,0), and white to move.
| Step | Operation | Result |
|---|---|---|
| 1 | legalMoves(4,2) | [(0,2), (1,2), (2,2), (3,2), (4,0), (4,1), (4,3), (4,4)] |
| 2 | move(4,2,0,2) | true |
| 3 | outcome() | "white-won-checkmate" |
| 4 | move(0,0,1,0) | false |
| 5 | history() | One white rook move from (4,2) to (0,2) with capturedType = "none" |
A rook move through an occupied intermediate square returns false, preserves the turn, and adds no history entry.
Constraints
- The board has exactly 5 rows and 5 columns, indexed
0through4. - A match contains 2 to 10 pieces.
- A testcase contains at most 20,000 method calls and 10,000 successful moves.
- Rows, columns, and turn numbers are nonnegative signed 32-bit integers.
Notes
Calls are processed sequentially. Concurrent access, repetition draws, move-count draws, insufficient-material draws, other chess pieces or special moves, undo, clocks, persistence, rendering, and arbitrary board sizes are outside the contract.