Sashité for Developers

General Gameplay Notation (GGN) Specification

Version: 1.0.0 Author: Sashité Published: 8 March 2014 License: MIT License


Overview

General Gameplay Notation (GGN) is a rule-agnostic, JSON-based format for describing pseudo-legal moves in abstract strategy board games. GGN expresses whether a move is possible under basic movement constraints, while remaining completely silent about higher-level, game-specific legality questions (e.g., check, ko, repetition, castling paths) and mechanical execution details.

GGN serves as a pure movement possibility oracle: given a piece, source position, and destination position, it determines if the movement is feasible under specified pre-conditions.


Core Philosophy

Movement Possibility Model

A single GGN entry answers the fundamental question:

Can this piece, currently on this square or in hand, reach that square or return to hand?

It encodes:

  1. Which piece (via arbitrary string identifier)
  2. From where (source square label or “*” for hand)
  3. To where (destination square label or “*” for hand)
  4. Which pre-conditions must hold (must)
  5. Which pre-conditions must not hold (deny)

Specification Boundaries

GGN is responsible for:

GGN is NOT responsible for:

GGN delegates to:


JSON Structure

{
  "<Source piece>": {
    "<Source position>": {
      "<Destination position>": [
        {
          "must":  { "<square>": "<required state>",  },
          "deny":  { "<square>": "<forbidden state>",  }
        }
      ]
    }
  }
}

Core Fields

Field Type Required Description
Source piece string yes Current piece identifier (arbitrary string)
Source position string yes Origin square or “*” for hand
Destination position string yes Target square or “*” for hand
must object no Pre-conditions that must be satisfied
deny object no Pre-conditions that must not be satisfied

Position Constraints

Piece Identifiers


Pre-Conditions System

Logical Semantics

Occupation States

State Meaning
"empty" Square must be empty
"enemy" Square must contain an opposing piece
Piece identifier Square must contain exactly the specified piece

Implicit States (via deny)

Expression Implicit Meaning
"deny": { "a1": "empty" } Square must be occupied (by any piece)
"deny": { "a1": "enemy" } Square must contain a friendly piece

Constraint Examples

Desired Condition GGN Expression
Square must be empty "must": { "a1": "empty" }
Square must contain enemy "must": { "a1": "enemy" }
Square must contain ally "deny": { "a1": "enemy" }
Square must be occupied "deny": { "a1": "empty" }
Square must contain specific piece "must": { "a1": "K" }
Square must not contain specific piece "deny": { "a1": "K" }

Move Variants

When a move can result in multiple outcomes, each variant is represented as a separate object in the destination array. Common use cases:

All variants share the same source and destination positions but may have different pre-conditions.


Examples

Simple Movement

{
  "R": {
    "a1": {
      "a4": [
        {
          "must": { "a2": "empty", "a3": "empty", "a4": "empty" }
        }
      ]
    }
  }
}

Capture

{
  "R": {
    "a1": {
      "a4": [
        {
          "must": { "a2": "empty", "a3": "empty", "a4": "enemy" }
        }
      ]
    }
  }
}

Drop from Hand

{
  "P": {
    "*": {
      "5e": [
        {
          "must": { "5e": "empty" }
        }
      ]
    }
  }
}

Multiple Promotion Choices

{
  "P": {
    "e7": {
      "e8": [
        {
          "must": { "e8": "empty" }
        }
      ]
    }
  }
}

Note: This example shows that promotion is possible. The specific promotion choice (Q, R, N, B) is determined at the execution layer.

Complex Movement (Castling Possibility)

{
  "K": {
    "e1": {
      "g1": [
        {
          "must": { "f1": "empty", "g1": "empty", "h1": "R" }
        }
      ]
    }
  }
}

Capture Possibility (Shōgi-style)

{
  "S": {
    "2c": {
      "2b": [
        {
          "must": { "2b": "enemy" }
        }
      ]
    }
  }
}

Using Game-Qualified Identifiers

{
  "CHESS:R": {
    "a1": {
      "a4": [
        {
          "must": { "a2": "empty", "a3": "empty", "a4": "empty" }
        }
      ]
    }
  }
}

Using Unicode Piece Symbols

{
  "♖": {
    "a1": {
      "a4": [
        {
          "must": { "a2": "empty", "a3": "empty", "a4": "empty" }
        }
      ]
    }
  }
}

Using Descriptive Names

{
  "white_rook": {
    "a1": {
      "a4": [
        {
          "must": { "a2": "empty", "a3": "empty", "a4": "empty" }
        }
      ]
    }
  }
}

Conditional Movement

{
  "P": {
    "e5": {
      "f6": [
        {
          "must": { "f6": "empty" },
          "deny": { "f5": "empty" }
        }
      ]
    }
  }
}

This represents an en passant possibility: pawn can move to f6 if f6 is empty AND f5 is occupied.


Validation Rules

Structural Requirements

  1. Must conform to the JSON Schema (see Schema section)
  2. All piece identifiers must be non-empty strings
  3. Source and destination positions cannot both be “*” simultaneously
  4. must and deny fields, if present, must not be empty
  5. No square may have the same state in both must and deny within the same variant

Pre-Condition Requirements

  1. All squares in must and deny must be valid board squares (no “*”)
  2. All occupation states must be valid: "empty", "enemy", or valid piece identifiers
  3. must field must not duplicate implicit requirements from query structure

Relationship to Other Notations

Notation Purpose Relationship to GGN
GAN Game-qualified piece identifiers Optional format for piece identification
FEEN Complete board state representation Provides context for move possibility
PMN Mechanical move decomposition Independent execution layer
PNN Basic piece naming Optional format for piece identification

GGN serves as the movement possibility layer in the Sashité ecosystem, providing a clean interface between static position representation (FEEN) and dynamic move execution (PMN or other execution engines).

Layered Architecture

┌─────────────────────────────────────┐
│          Application Layer          │
│         (Game Engines)              │
├─────────────────────────────────────┤
│        Execution Layer              │
│    (PMN, Custom Formats)            │
├─────────────────────────────────────┤
│      Movement Possibility           │
│           (GGN)                     │
├─────────────────────────────────────┤
│       Position Encoding             │
│          (FEEN)                     │
├─────────────────────────────────────┤
│      Piece Identification           │
│        (GAN/PNN)                    │
└─────────────────────────────────────┘

JSON Schema

Schema URL: https://sashite.dev/schemas/ggn/1.0.0/schema.json

The JSON Schema provides structural validation for GGN format compliance without dependencies on external execution formats.

Schema Integration Example

{
  "$schema": "https://sashite.dev/schemas/ggn/1.0.0/schema.json",
  "P": {
    "e7": {
      "e8": [
        {
          "must": { "e8": "empty" }
        }
      ]
    }
  }
}

Implementations

Ruby