{
  "$id": "https://dnd-gm.local/schemas/game-contract.schema.json",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "contractVersion",
    "stateVersion",
    "gameId",
    "rules",
    "characters",
    "commandKinds",
    "randomness",
    "turns",
    "migrations",
    "permissions"
  ],
  "properties": {
    "contractVersion": {
      "const": "1.0.0"
    },
    "stateVersion": {
      "const": "1.0.0"
    },
    "gameId": {
      "type": "string",
      "minLength": 1,
      "maxLength": 128
    },
    "rules": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "version",
        "attribution",
        "resolution",
        "abilities",
        "inventorySlots",
        "maxHitPoints"
      ],
      "properties": {
        "id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128
        },
        "version": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128
        },
        "attribution": {
          "type": "string",
          "minLength": 1
        },
        "resolution": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "dieSides",
            "successWhen",
            "criticalSuccess",
            "criticalFailure"
          ],
          "properties": {
            "dieSides": {
              "const": 20
            },
            "successWhen": {
              "const": "roll_plus_modifier_gte_difficulty"
            },
            "criticalSuccess": {
              "const": 20
            },
            "criticalFailure": {
              "const": 1
            }
          }
        },
        "abilities": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          },
          "uniqueItems": true
        },
        "inventorySlots": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100
        },
        "maxHitPoints": {
          "type": "integer",
          "minimum": 1,
          "maximum": 1000
        }
      }
    },
    "characters": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "name",
          "abilities",
          "startingLocationId",
          "startingItemIds",
          "branchId"
        ],
        "properties": {
          "id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          },
          "abilities": {
            "type": "object",
            "minProperties": 1,
            "additionalProperties": {
              "type": "integer",
              "minimum": -10,
              "maximum": 20
            }
          },
          "startingLocationId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          },
          "startingItemIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "uniqueItems": true
          },
          "branchId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          }
        }
      }
    },
    "commandKinds": {
      "type": "array",
      "minItems": 1,
      "uniqueItems": true,
      "items": {
        "enum": [
          "move",
          "check",
          "take_item",
          "use_item",
          "attack",
          "share_fact",
          "end_turn"
        ]
      }
    },
    "randomness": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "authority",
        "productionSource",
        "testSource",
        "replay"
      ],
      "properties": {
        "authority": {
          "const": "server"
        },
        "productionSource": {
          "const": "cryptographic"
        },
        "testSource": {
          "const": "seeded"
        },
        "replay": {
          "const": "recorded_outcomes"
        }
      }
    },
    "turns": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "mode",
        "timeUnit",
        "concurrentPolicy"
      ],
      "properties": {
        "mode": {
          "const": "round_robin"
        },
        "timeUnit": {
          "const": "turn"
        },
        "concurrentPolicy": {
          "const": "expected_state_version"
        }
      }
    },
    "migrations": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "supportedStateVersions",
        "unknownVersion",
        "historicalEvents"
      ],
      "properties": {
        "supportedStateVersions": {
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          }
        },
        "unknownVersion": {
          "const": "reject"
        },
        "historicalEvents": {
          "const": "immutable"
        }
      }
    },
    "permissions": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "stateChangingRequiresActiveTurn",
        "playerMayActOnlyAsSelf",
        "narratorMayMutateState"
      ],
      "properties": {
        "stateChangingRequiresActiveTurn": {
          "type": "boolean"
        },
        "playerMayActOnlyAsSelf": {
          "type": "boolean"
        },
        "narratorMayMutateState": {
          "const": false
        }
      }
    }
  }
}
