- Sashité for Developers
- Specifications
- QPI
- 1.0.0
- Examples
QPI Examples
This page shows how the same QPI format can be adapted to different game rules and data models.
QPI is intentionally rule-agnostic: the token is always the same shape (<sin>:<pin>), but your Rule System decides what updates happen on capture, promotion, conversion, offboard storage, drops, etc.
Quick refresher
A QPI token is:
<sin>:<pin>
<sin>is a SIN letter (style abbreviation; case carries a Side tag).<pin>is a PIN token (piece abbreviation + optional state + optional terminal marker; case of the piece letter is the Piece Side).
Example tokens:
C:R— styleC+ pieceRS:+r— styleS+ enhanced piecerX:G^— styleX+ terminal pieceG
Case tags and the Native/Derived relationship
QPI has two independent case carriers:
| Component | Case carries | What it is |
|---|---|---|
| SIN letter | a Side tag (first/second) |
a tag attached to the style letter |
| PIN letter | the current Piece Side (first/second) |
the piece’s current side |
From these, QPI defines a deterministic relationship:
- Native iff
case(<sin>) == case(PIN letter) - Derived otherwise
| QPI | SIN case | PIN case | Cases match? | Relationship |
|---|---|---|---|---|
C:R |
upper | upper | ✓ | Native |
C:r |
upper | lower | ✗ | Derived |
c:r |
lower | lower | ✓ | Native |
c:R |
lower | upper | ✗ | Derived |
Important: “Native/Derived” here is only the case-relationship. Any meaning like “ownership”, “conversion”, “original camp”, “eligible to drop”, etc. is context-defined.
A note on conventions
Because SIN case and PIN case are independent, contexts commonly adopt one of these conventions:
Convention A — Aligned-case (canonical in single-style games)
You enforce:
case(<sin>) == case(PIN letter)
This means every on-board piece is Native by construction.
This is often useful when:
- both players share the same style (e.g., shōgi),
- you want a canonical form,
- SIN case is considered redundant once Piece Side is known.
Convention B — Origin-preserving (track an origin tag)
You keep SIN case stable across side swaps, and only flip the PIN case when a piece changes side.
This can be useful when:
- your Rule System wants an additional “origin tag”,
- you model restrictions or metadata based on “where a piece comes from”.
Convention C — Fully independent
You allow either case to be chosen independently, without canonicalization.
This is useful when:
- you import tokens from heterogeneous sources,
- you use SIN case as a free tag not tied to the piece’s current side.
The following sections illustrate how the same game event can be modeled differently depending on your chosen convention.
Worked example 1 — Chess-like capture (identity-preserving)
In western chess, a captured piece is removed from the board and does not change side.
Assume:
- chess style letter:
C - rook letter:
R - first side: uppercase, second side: lowercase
Before capture (on board)
| Piece | QPI |
|---|---|
| White rook | C:R |
Capture event
A chess engine often models capture as:
- remove the piece from the board
- record it in a captured list (optional)
On the board: the rook disappears.
In captured material/history: the rook can remain C:R because it is still “a white rook” as a historical fact.
Example (informative):
captured_pieces += ["C:R"]
board.remove("C:R")
No “side swap” is required because chess capture does not turn pieces into the capturer’s pieces.
Worked example 2 — Shōgi-like capture (side-swapping), with optional canonicalization
In shōgi, captured pieces change camp and may be dropped later.
Assume:
- shōgi style letter:
S - rook letter:
R - first side (sente): uppercase
- second side (gote): lowercase
Before capture (on board)
| Piece | QPI |
|---|---|
| Sente rook | S:R |
After capture (in hand / offboard)
Minimum structural update: the piece changes side, so the PIN letter case flips.
| Modeling | Result | Explanation |
|---|---|---|
| Raw side swap | S:r |
only PIN case changed (Piece Side flipped) |
Now you can choose whether to canonicalize SIN case.
Option 2A — Aligned-case canonicalization (recommended for “single-style canonical” shōgi)
If both players share the same style and you want a canonical token shape, you can normalize:
case(<sin>) := case(PIN letter)
So S:r becomes:
| Modeling | Result | Explanation |
|---|---|---|
| Canonical shōgi token | s:r |
SIN case aligned to PIN case |
Under this convention:
S:rands:rare treated as equivalent representations of the same shōgi rook on the second side,- the canonical form is
s:r, - and every in-play piece remains Native by construction.
Option 2B — Origin-preserving convention (keep SIN case stable)
If your system wants to preserve an origin tag, you may keep SIN case as-is:
| Modeling | Result | Explanation |
|---|---|---|
| Origin-preserving | S:r |
SIN keeps its case-tag; PIN flips to reflect current side |
This makes S:r Derived (cases differ), which can be useful as a mechanical signal in your own rules — but that meaning remains your choice.
Drop (placing the piece back on board)
- Under aligned-case canonicalization: the dropped rook for gote is
s:r. - Under origin-preserving: the dropped rook remains
S:runless your rules say otherwise.
Promotion / demotion as Piece State
Promotion-like effects can be encoded with the PIN state modifier:
| Event | Before | After | Note |
|---|---|---|---|
| promote rook (context-defined) | s:r |
s:+r |
state becomes enhanced |
| revert to normal | s:+r |
s:r |
state returns to normal |
(These are encodings; the actual rule meaning is game-defined.)
“How to update a QPI token” recipes
These examples show the smallest token edits for common attribute changes.
Side change (Piece Side flips)
Flip the PIN letter case:
| Before | After | Change |
|---|---|---|
C:R |
C:r |
side: first → second |
s:p |
s:P |
side: second → first |
Style change (Piece Style changes)
Change the SIN letter identity (case optional):
| Before | After | Change |
|---|---|---|
C:R |
S:R |
style: chess → shōgi (keeping the SIN case-tag) |
C:R |
s:R |
style changed and SIN case-tag changed |
State change (Piece State changes)
Add or change the PIN prefix:
| Before | After | Change |
|---|---|---|
S:r |
S:+r |
state: normal → enhanced |
S:+r |
S:-r |
state: enhanced → diminished |
Terminal status change
Add or remove ^:
| Before | After | Change |
|---|---|---|
C:K |
C:K^ |
becomes terminal |
C:K^ |
C:K |
terminal removed |
Combined changes
Multiple edits can happen at once (context-defined):
| Before | After | Notes |
|---|---|---|
C:R |
S:r |
style changed + side changed |
m:+P |
C:P |
style changed + state reset |
C:b |
m:+B^ |
style + side + state + terminal |
Single-style catalogs (informative)
These tables illustrate one common mapping for well-known games. They are examples, not requirements.
Western chess (one possible convention)
- chess style letter:
C - first side pieces:
C:… - second side pieces:
c:…
| QPI | Piece | Notes |
|---|---|---|
C:K^ / c:k^ |
King | terminal |
C:Q / c:q |
Queen | |
C:R / c:r |
Rook | |
C:B / c:b |
Bishop | |
C:N / c:n |
Knight | |
C:P / c:p |
Pawn |
Japanese shōgi (aligned-case “single-style canonical”)
- shōgi style letter:
S - canonical rule:
case(<sin>) == case(PIN letter)
| QPI | Piece | Notes |
|---|---|---|
S:K^ / s:k^ |
King | terminal |
S:R / s:r |
Rook | |
S:+R / s:+r |
Promoted rook | enhanced |
S:B / s:b |
Bishop | |
S:+B / s:+b |
Promoted bishop | enhanced |
S:G / s:g |
Gold | |
S:S / s:s |
Silver | |
S:+S / s:+s |
Promoted silver | enhanced |
S:P / s:p |
Pawn | |
S:+P / s:+p |
Promoted pawn | enhanced |
Cross-style scenarios (informative)
In hybrid games, players may use different styles. QPI supports that naturally by using different SIN letters.
Example style letters:
C= chessS= shōgiX= xiangqim= makruk
Example setup: Chess vs Shōgi
| QPI | Interpretation (example) | Native/Derived |
|---|---|---|
C:R |
chess rook, first side | Native |
c:r |
chess rook, second side | Native |
S:g |
shōgi gold, second side (SIN tag = second, PIN side = second) | Native |
S:G |
shōgi gold, first side | Native |
Capture + conversion can be modeled explicitly
If your rules say a capture swaps side, and a conversion swaps style, you can represent each effect:
| Event (context-defined) | Before | After | Notes |
|---|---|---|---|
| captured (side swap only) | C:R |
C:r |
PIN case flips |
| converted (style swap only) | C:R |
S:R |
SIN letter identity changes |
| captured + converted | C:R |
S:r |
both effects |
If you also adopt canonicalization (aligned-case), you can normalize S:r → s:r (or any other rule your system defines).
Combined modifier matrix (useful for testing)
All combinations for a style letter C and a piece letter K:
Native (cases match)
| QPI | Side | State | Terminal |
|---|---|---|---|
C:K |
first | normal | no |
C:K^ |
first | normal | yes |
C:+K |
first | enhanced | no |
C:+K^ |
first | enhanced | yes |
C:-K |
first | diminished | no |
C:-K^ |
first | diminished | yes |
Derived (cases differ)
| QPI | Side | State | Terminal |
|---|---|---|---|
C:k |
second | normal | no |
C:k^ |
second | normal | yes |
C:+k |
second | enhanced | no |
C:+k^ |
second | enhanced | yes |
C:-k |
second | diminished | no |
C:-k^ |
second | diminished | yes |
Mutation sequences (informative)
A token can go through multiple updates. The events below are just examples of what a Rule System might do.
Example: shōgi-like rook lifecycle (aligned-case canonical)
| Step | QPI | Event |
|---|---|---|
| 1 | S:R |
initial |
| 2 | s:r |
captured (side swap + canonicalization) |
| 3 | s:+r |
promoted (state change) |
| 4 | s:r |
demoted / reset (state removed) |
Example: terminal marker usage
| Step | QPI | Event |
|---|---|---|
| 1 | C:K |
standard |
| 2 | C:K^ |
designated terminal |
| 3 | c:k^ |
moved to second side (if your rules allow it) |
| 4 | c:k |
terminal removed |
Context dependency
QPI tokens are context-dependent: letters are abbreviations, and the context decides their human meaning.
| QPI | Chess context | Shōgi context | Xiangqi context |
|---|---|---|---|
C:K^ |
King | — | — |
S:K^ |
— | King | — |
X:G^ |
— | — | General |
C:R |
Rook | — | — |
S:R |
— | Rook | — |
X:R |
— | — | Chariot |
A context can publish the mapping table (catalog), but QPI remains valid without it.
