{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://sashite.dev/schemas/stn/1.0.0/schema.json",
  "title": "State Transition Notation (STN) v1.0.0",
  "description": "Rule-agnostic JSON format for describing state transitions in abstract strategy board games using CELL coordinates and QPI piece identification",
  "type": "object",

  "properties": {
    "$schema": {
      "type": "string",
      "format": "uri",
      "description": "URI reference to the JSON Schema specification version"
    },
    "board": {
      "type": "object",
      "description": "Board position changes mapping CELL coordinates to their final states",
      "patternProperties": {
        "^[a-z]+(?:[1-9]\\d*[A-Z]+[a-z]+)*(?:[1-9]\\d*(?:[A-Z]+)?)?$": {
          "oneOf": [
            {
              "type": "string",
              "pattern": "^([A-Z]:[-+]?[A-Z]'?|[a-z]:[-+]?[a-z]'?)$",
              "description": "QPI piece identifier for the piece occupying this location"
            },
            {
              "type": "null",
              "description": "Location becomes empty"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "hands": {
      "type": "object",
      "description": "Hand/reserve changes mapping QPI piece identifiers to delta counts",
      "patternProperties": {
        "^([A-Z]:[-+]?[A-Z]'?|[a-z]:[-+]?[a-z]'?)$": {
          "type": "integer",
          "not": {
            "const": 0
          },
          "description": "Net change in piece count (positive = added, negative = removed)"
        }
      },
      "additionalProperties": false
    },
    "toggle": {
      "type": "boolean",
      "description": "Whether the transition toggles the active player (default: false)",
      "default": false
    }
  },

  "additionalProperties": false,

  "examples": [
    {
      "description": "Simple movement (toggle implicit false)",
      "value": {
        "board": {
          "e2": null,
          "e4": "C:P"
        }
      }
    },
    {
      "description": "Simple movement with explicit toggle",
      "value": {
        "board": {
          "e2": null,
          "e4": "C:P"
        },
        "toggle": true
      }
    },
    {
      "description": "Simple capture",
      "value": {
        "board": {
          "b1": "S:S",
          "c2": null
        },
        "hands": {
          "S:B": 1
        },
        "toggle": true
      }
    },
    {
      "description": "Drop from hand",
      "value": {
        "board": {
          "e5": "S:P"
        },
        "hands": {
          "S:P": -1
        },
        "toggle": true
      }
    },
    {
      "description": "Castling (multiple board changes)",
      "value": {
        "board": {
          "e1": null,
          "g1": "C:K",
          "h1": null,
          "f1": "C:R"
        },
        "toggle": true
      }
    },
    {
      "description": "En passant capture",
      "value": {
        "board": {
          "e5": null,
          "f6": "C:P",
          "f5": null
        },
        "hands": {
          "c:p": 1
        },
        "toggle": true
      }
    },
    {
      "description": "Pawn promotion",
      "value": {
        "board": {
          "e7": null,
          "e8": "C:Q"
        },
        "toggle": true
      }
    },
    {
      "description": "3D movement (multi-dimensional coordinates)",
      "value": {
        "board": {
          "e2A": null,
          "f3B": "R:B"
        },
        "toggle": true
      }
    },
    {
      "description": "Cross-style capture (Chess captures Xiangqi piece)",
      "value": {
        "board": {
          "a1": "C:R",
          "a8": null
        },
        "hands": {
          "x:r": 1
        },
        "toggle": true
      }
    },
    {
      "description": "Multiple moves cumulative (toggle: false, original player still active)",
      "value": {
        "board": {
          "e2": null,
          "e4": "C:P",
          "e5": "c:p",
          "e7": null
        },
        "toggle": false
      }
    },
    {
      "description": "Empty transition (no changes)",
      "value": {}
    },
    {
      "description": "Complex Shōgi move with promotion and capture",
      "value": {
        "board": {
          "g8": null,
          "g9": "S:+P",
          "h9": null
        },
        "hands": {
          "S:G": 1
        },
        "toggle": true
      }
    },
    {
      "description": "Piece exchange sequence",
      "value": {
        "board": {
          "e2": "X:B",
          "e3": null,
          "f2": "X:A"
        },
        "hands": {
          "X:A": -1
        },
        "toggle": true
      }
    },
    {
      "description": "Pass move (turn change only)",
      "value": {
        "toggle": true
      }
    },
    {
      "description": "Board-only change with no turn change",
      "value": {
        "board": {
          "e2": null,
          "e4": "C:P"
        }
      }
    }
  ],

  "counterExamples": [
    {
      "description": "Invalid CELL coordinate (uppercase first)",
      "value": {
        "board": {
          "E2": "C:P"
        }
      }
    },
    {
      "description": "Invalid CELL coordinate (number first)",
      "value": {
        "board": {
          "2e": "C:P"
        }
      }
    },
    {
      "description": "Invalid QPI format in board (missing colon)",
      "value": {
        "board": {
          "e4": "CP"
        }
      }
    },
    {
      "description": "Invalid QPI format in board (multi-character style)",
      "value": {
        "board": {
          "e4": "CHESS:P"
        }
      }
    },
    {
      "description": "Invalid QPI format in board (mixed case style)",
      "value": {
        "board": {
          "e4": "Chess:P"
        }
      }
    },
    {
      "description": "Invalid QPI format in board (case mismatch)",
      "value": {
        "board": {
          "e4": "C:p"
        }
      }
    },
    {
      "description": "Invalid QPI format in hands (missing colon)",
      "value": {
        "hands": {
          "CP": 1
        }
      }
    },
    {
      "description": "Invalid QPI format in hands (multi-character style)",
      "value": {
        "hands": {
          "CHESS:P": 1
        }
      }
    },
    {
      "description": "Invalid QPI format in hands (mixed case style)",
      "value": {
        "hands": {
          "Chess:P": 1
        }
      }
    },
    {
      "description": "Invalid QPI format in hands (case mismatch)",
      "value": {
        "hands": {
          "C:p": 1
        }
      }
    },
    {
      "description": "Zero delta in hands (not allowed)",
      "value": {
        "hands": {
          "C:P": 0
        }
      }
    },
    {
      "description": "Non-integer delta in hands",
      "value": {
        "hands": {
          "C:P": 1.5
        }
      }
    },
    {
      "description": "Invalid board value (not QPI or null)",
      "value": {
        "board": {
          "e4": "invalid"
        }
      }
    },
    {
      "description": "Invalid toggle value (not boolean)",
      "value": {
        "toggle": "true"
      }
    },
    {
      "description": "Extra properties not allowed",
      "value": {
        "board": {
          "e4": "C:P"
        },
        "extra": "not allowed"
      }
    },
    {
      "description": "Invalid CELL coordinate with HAND location (not allowed in board)",
      "value": {
        "board": {
          "*": "C:P"
        }
      }
    }
  ]
}
