Statuses — Sanki game
==========================================

`reference` `suite-support`

This is a supporting document for the Sashité chess-family NIP suite. It does not define a new event kind or protocol mechanism; it specifies the vocabulary of termination status strings that a Conclusion (kind `3425`) carries in its `content` field for sessions in the `sanki` game context.

The Conclusion NIP (kind `3425`) deliberately leaves the `content` field open-vocabulary (constrained only to `^[a-z]{1,32}$`), deferring the specific status vocabulary to the rule system. This document is that definition for the `sanki` rule system; the kernel the rule system names incorporates it ([Kernel — Sanki](../../rules/kernel-sanki.md) §Identification and contract), so every consumer computing a session's verdict applies it identically.

## Scope

This document covers:

- The set of termination status strings a Conclusion may carry for the `sanki` game.
- The typical result distribution (`result` tags) associated with each status.
- The conventions by which implicit termination signals (`resignation`, `agreement`) are read from a player's Conclusion.
- The outcome values Sashité produces (`100/0`, `0/100`, `50/50`) — and why there are no partial results.

This document does NOT define:

- The protocol-level format of the `content` field (defined in kind `3425`).
- Status vocabularies for other rule systems or other games; those are the responsibility of the respective rule system's documentation.
- Move legality or rule-system details beyond what is necessary to explain termination causes.

## Status vocabulary

The `sanki` rule system recognizes ten termination statuses. Each status string is a lowercase ASCII identifier satisfying `^[a-z]{1,32}$` as required by kind `3425`.

| Status | Source | Typical result | Description |
|---|---|---|---|
| `checkmate` | rule-system | decisive (loser checkmated) | The losing player's royal is in check and, although pseudo-legal moves exist, none of them resolves the check. |
| `stalemate` | rule-system | draw (`50 / 50`) | The active player has pseudo-legal moves and is not in check, but no pseudo-legal move is legal (each would leave its own royal in check). A draw in all three Sanki variants. |
| `nomove` | rule-system | draw (`50 / 50`) | The active player has **no pseudo-legal half-move at all** — they cannot generate any move, legal or not. A draw in all three Sanki variants (see §Distinguishing `checkmate`, `stalemate`, and `nomove`). |
| `insufficient` | rule-system | draw (`50 / 50`) | **Dead position**: neither player can checkmate the opponent's royal by any series of legal moves — the criterion is *possibility*, not forceability. The variant-specific material-only configurations the engine detects are listed in each rule spec's §Dead-Position Detection; see the deliberate cross-variant exception below. |
| `repetition` | rule-system | draw (`50 / 50`) | The same position has occurred the threshold number of times specified by the variant's rule system (e.g., threefold repetition in standard chess). |
| `movelimit` | rule-system | draw (`50 / 50`) | 50 full moves by each player (100 half-moves) have elapsed with no capture and no move of an unpromoted pawn-class piece (Pawn / Fu / Soldier). The FIDE 50-move rule, applied identically across all three Sanki variants. |
| `movecap` | rule-system | draw (`50 / 50`) | The **absolute move cap** — 300 full moves (600 half-moves) — has been reached with the game still ongoing: an unconditional draw regardless of the position, identical across all variants. The non-resetting ceiling of the [Sanki Global Rules](../../rules/rules/sanki-global-rules.md); it sits last in the §Verdict resolution priority (a decisive ending on the 600th half-move outranks it). |
| `timeout` | protocol | decisive (loser timed out) | A player's time-control budget has been exhausted per [Time Accounting — Sanki](time-accounting-sanki.md), anchored on kind `3422`'s t₀ and the per-Ply canonical timing of kind `3423`; two flavours — played-Ply and abandonment — per §Verdict resolution. |
| `resignation` | protocol-reserved | decisive (loser resigned) | The residual interpretation of a Conclusion matching no other cause: the concluding player abandons, at any moment and regardless of the turn; see §Implicit resignation. |
| `agreement` | protocol-reserved | draw (`50 / 50`) | Both players have implicitly agreed to a draw; see §Implicit draw by agreement. |

> **Deliberate exception — the mixed King-versus-General pair.** In cross-variant sessions (chess or ōgi versus xiongqi), a lone King versus a lone General is ruled `insufficient` although it is **not** strictly a dead position: the General steps one square but attacks at Chariot range, so a cornered General is matable *in principle* (with its owner's cooperation). Neither side can **force** a win, however — best defence yields at most a stalemate — so Sashité declares the draw outright rather than making the players shuffle to a repetition or move-limit finish (deciders' ruling, 2026-07-10; interactions-chess-xiongqi.md and interactions-ogi-xiongqi.md, §End of Game). `insufficient` is therefore defined by the dead-position criterion **plus** this one enumerated cross-variant exception.

**Source categories:**

- **rule-system**: the status arises from position evaluation by the variant's rules.
- **protocol**: the status arises from protocol-level mechanics (time accounting).
- **protocol-reserved**: the status arises from specific protocol-level signals — who concluded, and when — read per the conventions below.

### Distinguishing `checkmate`, `stalemate`, and `nomove`

These three rule-system statuses are mutually exclusive and are distinguished by the active player's **pseudo-legal** half-move set — the moves available *before* the self-check filter is applied. This is a rule-agnostic notion that does not depend on any particular variant or on the presence of a royal piece:

- **`nomove`** — the pseudo-legal set is **empty**: the player cannot generate any half-move at all, legal or not. Result: **draw** (`50 / 50`).
- **`checkmate`** — the pseudo-legal set is non-empty, the royal is **in check**, and no pseudo-legal move removes the check (the legal set is empty). Result: **decisive** against the player to move.
- **`stalemate`** — the pseudo-legal set is non-empty, the royal is **not in check**, and every pseudo-legal move would leave the royal in check (the legal set is empty). Result: **draw** (`50 / 50`).

`checkmate` and `stalemate` both presuppose that the player *has* pseudo-legal moves, and differ only by whether the royal is currently in check; `nomove` is the prior case where no pseudo-legal move exists at all. The kernel therefore tests `nomove` first, and only distinguishes `checkmate` from `stalemate` once at least one pseudo-legal move is present.

> **Corner case.** A position where the royal is in check *and* the pseudo-legal set is empty is ruled `nomove` (a draw), not `checkmate` — `nomove` is defined on the pseudo-legal set being empty and takes precedence. This is a deliberate Sashité choice; an engine must order the tests accordingly.

## Implicit termination conventions

Two statuses — `resignation` and `agreement` — do not arise from rule-system position evaluation. They are read from the Conclusion itself — its signer (the *invoker*) and its canonical timing (the *cutoff*) — according to the following conventions, applied to the natural state of events (kind `3425` §Natural state of events at the cutoff).

Both conventions apply only when the natural state replays to a still-ongoing position, and both are anchored at the **cutoff** (the Conclusion's canonical timing). Their interaction with each other and with every other termination cause — including the mutual ordering `agreement` → abandonment `timeout` → `resignation` — is specified in §Verdict resolution.

### Implicit resignation

Resignation is the **residual interpretation** of a Conclusion. The verdict is `resignation` against a player when both of the following hold, evaluated on the natural state of events per kind `3425` §Natural state of events at the cutoff:

1. The player (one of the two session players) signed the Conclusion (kind `3425`).
2. No other termination cause exists at the cutoff: no chain-replay termination, no implicit draw by agreement, and no abandonment timeout (see §Verdict resolution).

The invocation is **independent of the turn**: a player may conclude at any moment, whether or not it is their turn to move. Under the conditions above, the invoker is identified as the **loser**; the result is decisive (`100 / 0` against them).

This convention provides a path for a player to formally terminate a session they no longer wish to continue, without requiring a dedicated resignation event kind — and it makes a conforming, canonically timed Conclusion **never a no-op**: a player who concludes when no objective cause stands (no termination on the board, no pending draw offer to accept, no expired opponent clock) thereby resigns. Clients MUST surface this clearly: the only unconditional "conclude" affordance SHOULD be the resign action, and claim-style affordances (win on time, draw on the board, accept the draw) SHOULD be offered only when the client itself predicts the corresponding verdict from the same public events.

Two boundary notes:

- A Ply published by the invoker after the Conclusion — i.e., with canonical timing strictly greater than the Conclusion's — does NOT exempt them from this convention: the cutoff excludes such Plies from the natural state.
- A win-on-time claim cannot be voided by attestation latency: the abandonment timeout is evaluated at the cutoff, which is necessarily at or after the moment the claim was published, and an expired clock only becomes more expired as the cutoff moves later. The claim that *is* at the claimant's risk is one published while the player on move still has time — it resolves to the claimant's resignation.

### Implicit draw by agreement

A player offers a draw by attaching the optional `draw` tag (kind `3423` §Optional flag tags) to their Ply; an opponent who plays the next ply instead of concluding implicitly declines the offer.

The verdict is `agreement` when all of the following conditions are satisfied, evaluated on the natural state of events per kind `3425` §Natural state of events at the cutoff:

1. The last Ply in the consecutive chain (the canonical Ply at the highest step in the chain) carries the `draw` tag (a draw proposal by its signer).
2. The Conclusion is signed by the **opponent** of that Ply's signer.

The result is `50 / 50`.

This convention provides a path for two players to agree on a draw without a dedicated draw-acceptance event kind. The offering player attaches the `draw` tag to their Ply; the opponent's Conclusion — while the draw offer remains the last move in the chain — constitutes implicit acceptance.

A Ply by the opponent at the slot following the draw-tagged Ply in the play order, with canonical timing less than or equal to the Conclusion's, would extend the chain past the draw-tagged Ply, in which case condition 1 fails and `agreement` does not apply (the opponent's response is interpreted as declining the offer by continuing play). Plies timed strictly after the Conclusion are excluded by the cutoff rule and have no bearing on the verdict.

## Verdict resolution

Every termination cause is **play-derived**: it emerges either from replaying the canonical chain or from resolving the invocation against a still-ongoing position. An **illegal Ply is not a termination cause** — the selection rule simply skips it (premove or live), and the slot falls to the next candidate or stays unfilled (see [Move Encoding — Sanki §Slot candidates and selection](move-encoding-sanki.md)); there is no `illegalmove` status. Two further causes sanctioned by earlier drafts are likewise gone: **equivocation** (several contents for one slot) is resolved by selection, not sanctioned, and **step-ownership** (signing the opponent's steps) is structurally inexpressible since the signer is part of the slot. The two resolution paths are mutually exclusive by construction — a chain that terminates is never resolved post-chain, and vice versa:

1. **Chain replay.** The canonical chain is replayed from the initial position in the play order, applying the **selection rule** ([Move Encoding — Sanki §Slot candidates and selection](move-encoding-sanki.md)) at each successive slot to pick its canonical Ply (the two-window choice — the latest legal premove, else the earliest legal live move; illegal candidates — premove or live — are skipped, not terminations). If the selected Ply terminates the game — a rule-system ending (`checkmate`, `stalemate`, `nomove`, `insufficient`, `repetition`, `movelimit`, `movecap`) or a played-Ply timeout (`timeout`: the mover's budget was already exhausted at the Ply's canonical timing, per [Time Accounting — Sanki](time-accounting-sanki.md)) — the candidate is that termination, anchored at the terminating Ply's canonical timing, and everything after it is irrelevant.
2. **Post-chain resolution.** If the chain replays to a still-ongoing position, the invocation itself is resolved at the **cutoff** (the Conclusion's canonical timing), in order:
   1. implicit draw by **`agreement`** — the last chain Ply offers a draw and the invoker is its signer's opponent (§Implicit draw by agreement);
   2. abandonment **`timeout`** — the player on move at the end of the chain has let their clock, run from the last canonical timing in the chain (or from t₀ for an empty chain) to the cutoff, expire;
   3. otherwise **`resignation`** — the residual interpretation, decisive against the invoker (§Implicit resignation).

   The order matters: an invocation by the offeree while a draw offer stands is an acceptance, not an abandonment; an invocation while the on-move player's clock has expired is a win-on-time claim (or, if the invoker let their own clock expire, a loss on time), not an abandonment.

Because resignation is the residual interpretation, every canonically timed Conclusion by a session player **has a verdict** — there is no "premature" invocation, only a premature one that resolves against its signer. A Conclusion is *conforming* only if the verdict it carries is this one (kind `3425` §Semantic constraints, constraint 8): a client therefore computes the resolution above before publishing, and a verifier recomputes it on receipt. A Conclusion with no canonical timing yet has an undefined cutoff and is pending (kind `3425` §Until the Conclusion has canonical timing).

### Which Conclusion rules

Several conforming Conclusions may coexist (both players conclude, or one player concludes again after an invalid attempt). The cutoff is **verdict-relevant**: two Conclusions can carry two different, equally correct verdicts (e.g., a premature win-on-time claim resolving to the claimant's resignation at one cutoff, and a genuine timeout against the opponent at a later one).

The protocol removes any discretion here: conforming Conclusions are ordered by **canonical timing** (smallest, then smallest event id), and the **earliest** conforming one is canonical (kind `3425` §Idempotence and finality). Once it exists, the session is terminated and every later Conclusion is moot; a non-conforming Conclusion — one whose verdict is not the one its cutoff yields — never occupies the slot, whatever its timing.

This makes the verdict fully predictable from public events, and it keeps invocations honest: the earliest correct invocation is the one that counts, at its signer's risk (§Implicit resignation). A Conclusion timed early but revealed late cannot reopen a terminated session: the slot rule is a conformance condition applied by every verifier, and finality holds from the first canonical Conclusion.

## Result conventions

### Standard outcomes

| Outcome | `result` distribution | Typical statuses |
|---|---|---|
| Decisive (first player wins) | `first` → `100`, `second` → `0` | `checkmate`, `timeout`, `resignation` |
| Decisive (second player wins) | `first` → `0`, `second` → `100` | same |
| Draw | `first` → `50`, `second` → `50` | `stalemate`, `nomove`, `insufficient`, `repetition`, `movelimit`, `movecap`, `agreement` |

### Outcome values produced by Sashité

Within the `sanki` game context, the rule system yields **only three** `result` splits — there are no partial results:

| Split | Meaning |
|---|---|
| `100 / 0` | Decisive win for the first player. |
| `0 / 100` | Decisive win for the second player. |
| `50 / 50` | Draw. |

This matches the rule specifications: a Sanki game has exactly one of three results — `1–0`, `½–½`, or `0–1`. The Elo and Glicko-2 rating attestations (kinds `3426`/`3427`) can *represent* intermediate scores in `[0.0, 1.0]` as a generic capability, but Sashité never emits one; the only scores it maps are `1.0`, `0.0`, and `0.5`.

## Variant notes

Within the `sanki` game context, the three variants (`chess`, `ogi`, `xiongqi`) share the **same** termination semantics — there are no variant-specific outcome differences:

| Status | All Sanki variants |
|---|---|
| `stalemate` | Draw (`50 / 50`) |
| `nomove` | Draw (`50 / 50`) |
| `movelimit` | Draw (`50 / 50`) — FIDE 50-move rule: 100 half-moves with no capture and no move of an unpromoted pawn-class piece (Pawn / Fu / Soldier) |
| `movecap` | Draw (`50 / 50`) — the absolute 300-move (600-half-move) cap, identical across all variants ([Sanki Global Rules](../../rules/rules/sanki-global-rules.md)) |

Earlier Sashité drafts treated `stalemate` as variant-dependent (draw in `chess`, partial win in `ogi`, loss in `xiongqi`) and used a non-FIDE `ogi` move limit; both have been removed to align with the current rule specifications, which make stalemate a uniform draw across Chess, Ōgi, and Xiongqi and admit no partial results.

## References

- Kind `3425` — Conclusion (the event whose `content` field this document specifies)
- [Sanki Global Rules](../../rules/rules/sanki-global-rules.md) — the absolute 300-move (600-half-move) cap that produces the `movecap` draw
- Kind `3423` — Ply (carries the `step` values and the `draw` tag used in implicit termination detection)
- [Move Encoding — Sanki](move-encoding-sanki.md) — slot candidates and the selection rule, and the within-step ordering consumed by the natural state
- [Rating Specification — Glicko-2](rating-specification-glicko2.md) — rating computation consuming `result` values
- [Rating Specification — Elo](rating-specification-elo.md) — alternative rating computation
