Sashité for Developers
  1. Sashité for Developers
  2. Specifications
  3. GGN
  4. 1.0.0
  5. Examples

GGN Examples

Practical implementation guide for General Gameplay Notation v1.0.0.


Examples

Simple Movement

{
  "C:R": {
    "a1": {
      "a4": [
        {
          "must": { "a2": "empty", "a3": "empty", "a4": "empty" },
          "deny": {},
          "diff": {
            "board": {
              "a1": null,
              "a4": "C:R"
            }
          }
        }
      ]
    }
  }
}

Capture

{
  "C:R": {
    "a1": {
      "a4": [
        {
          "must": { "a2": "empty", "a3": "empty", "a4": "enemy" },
          "deny": {},
          "diff": {
            "board": {
              "a1": null,
              "a4": "C:R"
            },
            "hands": {
              "c:r": 1
            }
          }
        }
      ]
    }
  }
}

Drop from Hand

{
  "S:P": {
    "*": {
      "e4": [
        {
          "must": { "e4": "empty" },
          "deny": {},
          "diff": {
            "board": {
              "e4": "S:P"
            },
            "hands": {
              "S:P": -1
            }
          }
        }
      ]
    }
  }
}

Capture to Hand

{
  "A:R": {
    "a1": {
      "*": [
        {
          "must": { "a1": "enemy" },
          "deny": {},
          "diff": {
            "board": {
              "a1": null
            },
            "hands": {
              "A:R": 1
            }
          }
        }
      ]
    }
  }
}

Multiple Promotion Choices

{
  "C:P": {
    "e7": {
      "e8": [
        {
          "must": { "e8": "empty" },
          "deny": {},
          "diff": {
            "board": {
              "e7": null,
              "e8": "C:Q"
            }
          }
        }
      ]
    }
  }
}

Note: This example shows promotion to queen. Different promotion choices would be separate GGN entries with different diff outcomes.

Complex Movement (Castling Possibility)

{
  "C:+K": {
    "e1": {
      "g1": [
        {
          "must": { "f1": "empty", "g1": "empty", "h1": "C:+R" },
          "deny": {},
          "diff": {
            "board": {
              "e1": null,
              "g1": "C:K",
              "h1": null,
              "f1": "C:R"
            }
          }
        }
      ]
    }
  }
}

Capture Possibility (Shōgi-style)

{
  "S:P": {
    "c3": {
      "c4": [
        {
          "must": { "c4": "enemy" },
          "deny": {},
          "diff": {
            "board": {
              "c3": null,
              "c4": "S:P"
            },
            "hands": {
              "S:P": 1
            }
          }
        }
      ]
    }
  }
}

Cross-Style Game Example

{
  "C:R": {
    "a1": {
      "a4": [
        {
          "must": { "a2": "empty", "a3": "empty", "a4": "enemy" },
          "deny": {},
          "diff": {
            "board": {
              "a1": null,
              "a4": "C:R"
            },
            "hands": {
              "x:c": 1
            }
          }
        }
      ]
    }
  },
  "x:c": {
    "b2": {
      "b8": [
        {
          "must": { "b3": "empty", "b4": "empty", "b5": "empty", "b6": "empty", "b8": "enemy" },
          "deny": { "b7": "empty" },
          "diff": {
            "board": {
              "b2": null,
              "b8": "x:c"
            },
            "hands": {
              "C:R": 1
            }
          }
        }
      ]
    }
  }
}

This example shows a GGN data set usable for a game where Chess pieces face Xiangqi pieces.

Conditional Movement (En Passant)

{
  "C:P": {
    "e5": {
      "f6": [
        {
          "must": { "f6": "empty", "f5": "c:-p" },
          "deny": {},
          "diff": {
            "board": {
              "e5": null,
              "f6": "C:P",
              "f5": null
            },
            "hands": {
              "c:p": 1
            }
          }
        }
      ]
    }
  }
}

This represents an en passant possibility: pawn can move to f6 if f6 is empty AND f5 contains an enemy pawn vulnerable to en passant (noted with the - modifier).

Multi-Dimensional Movement

{
  "R:B": {
    "a1A": {
      "d4D": [
        {
          "must": { "b2B": "empty", "c3C": "empty", "d4D": "empty" },
          "deny": {},
          "diff": {
            "board": {
              "a1A": null,
              "d4D": "R:B"
            }
          }
        }
      ]
    }
  }
}

Example from Raumschach showing bishop movement across dimensions using CELL coordinates.

Pawn Drop with File Restriction (Shogi-Style)

Dropping a pawn from hand onto e4, with the restriction that there must not be another unpromoted pawn on the same file.

{
  "S:P": {
    "*": {
      "e4": [
        {
          "must": { "e4": "empty" },
          "deny": {
            "e1": "S:P", "e2": "S:P", "e3": "S:P",
            "e5": "S:P", "e6": "S:P", "e7": "S:P",
            "e8": "S:P", "e9": "S:P"
          },
          "diff": {
            "board": {
              "e4": "S:P"
            },
            "hands": {
              "S:P": -1
            }
          }
        }
      ]
    }
  }
}

Piece State Transitions

Pre-Move vs Post-Move States

GGN represents pieces in their pre-move state (before the action is executed) in the query structure, while the diff field represents the post-move state (after the action is completed). This distinction is crucial for pieces whose states change as a result of movement.

State Evolution Examples

Castling Eligibility Loss:

When a rook moves for the first time, it loses its castling eligibility. This state change is reflected in the different QPI identifiers used in the query versus the diff field:

{
  "C:+R": {
    "a1": {
      "a4": [
        {
          "must": { "a2": "empty", "a3": "empty", "a4": "empty" },
          "deny": {},
          "diff": {
            "board": {
              "a1": null,
              "a4": "C:R"
            }
          }
        }
      ]
    }
  }
}

The query uses C:+R (rook with castling eligibility) but the diff shows C:R (rook without castling eligibility).

En Passant Vulnerability:

A pawn vulnerable to en passant capture loses this vulnerability after any move:

{
  "c:-p": {
    "f5": {
      "f4": [
        {
          "must": { "f4": "empty" },
          "deny": {},
          "diff": {
            "board": {
              "f5": null,
              "f4": "c:p"
            }
          }
        }
      ]
    }
  }
}

The query uses c:-p (vulnerable pawn) but the diff shows c:p (normal pawn).

Design Rationale

This temporal distinction allows GGN to:


Integration with PMN

GGN defines movement possibilities with complete state transitions, while PMN handles mechanical execution. When a GGN move is selected, the diff field provides the expected outcome that can be validated against PMN execution results.

Simple Movement to PMN

GGN possibility:

{
  "C:+R": {
    "a1": {
      "a4": [
        {
          "must": { "a2": "empty", "a3": "empty", "a4": "empty" },
          "deny": {},
          "diff": {
            "board": {
              "a1": null,
              "a4": "C:R"
            }
          }
        }
      ]
    }
  }
}

PMN execution:

["a1", "a4", "C:R"]

Complex Movement to PMN

GGN possibility (castling):

{
  "C:+K": {
    "e1": {
      "g1": [
        {
          "must": { "f1": "empty", "g1": "empty", "h1": "C:+R" },
          "deny": {},
          "diff": {
            "board": {
              "e1": null,
              "g1": "C:K",
              "h1": null,
              "f1": "C:R"
            }
          }
        }
      ]
    }
  }
}

PMN execution:

["e1", "g1", "C:K", "h1", "f1", "C:R"]

Capture to PMN

GGN possibility (en passant):

{
  "C:P": {
    "e5": {
      "f6": [
        {
          "must": { "f6": "empty", "f5": "c:-p" },
          "deny": {},
          "diff": {
            "board": {
              "e5": null,
              "f6": "C:P",
              "f5": null
            },
            "hands": {
              "c:p": 1
            }
          }
        }
      ]
    }
  }
}

PMN execution:

["e5", "f6", "C:P", "f5", "*", "c:p"]