{
 "$schema": "https://json-schema.org/draft/2020-12/schema",
 "$id": "https://jabbertoon.com/schemas/program.schema.json",
 "title": "Jabbertoon program",
 "description": "A move (kind \"behaviour\"), a scene or a cartoon in the Jabbertoon block language (https://jabbertoon.com/docs/language/). This schema checks the shape; the engine validator also checks formulas, part names and placement values.",
 "type": "object",
 "required": [
  "v",
  "kind",
  "scripts"
 ],
 "properties": {
  "v": {
   "const": 1,
   "description": "The language version: always 1."
  },
  "kind": {
   "enum": [
    "behaviour",
    "scene",
    "cartoon"
   ]
  },
  "name": {
   "type": "string"
  },
  "note": {
   "type": "string"
  },
  "params": {
   "type": "object",
   "description": "Settings with their defaults: a number, or a formula string starting with \"=\".",
   "additionalProperties": {
    "$ref": "#/$defs/value"
   }
  },
  "vars": {
   "type": "object",
   "description": "Variables and the numbers they start at.",
   "additionalProperties": {
    "type": "number"
   }
  },
  "cast": {
   "type": "object",
   "description": "Scenes and cartoons: the characters, by id.",
   "additionalProperties": {
    "$ref": "#/$defs/castEntry"
   }
  },
  "places": {
   "type": "object",
   "description": "Scenes and cartoons: the places, by name.",
   "additionalProperties": {
    "oneOf": [
     {
      "type": "string"
     },
     {
      "type": "object"
     }
    ]
   }
  },
  "scripts": {
   "type": "array",
   "items": {
    "$ref": "#/$defs/script"
   }
  }
 },
 "$defs": {
  "value": {
   "oneOf": [
    {
     "type": "number"
    },
    {
     "type": "string",
     "pattern": "^="
    }
   ],
   "description": "A number, or a formula: a string starting with \"=\", e.g. \"=7*loud\"."
  },
  "script": {
   "type": "object",
   "required": [
    "body"
   ],
   "properties": {
    "hat": {
     "$ref": "#/$defs/hat"
    },
    "body": {
     "$ref": "#/$defs/blocks"
    },
    "note": {
     "type": "string"
    },
    "id": {
     "type": "string"
    }
   }
  },
  "hat": {
   "type": "object",
   "required": [
    "on"
   ],
   "properties": {
    "on": {
     "enum": [
      "start",
      "talk-start",
      "talk-end",
      "beat",
      "loud",
      "every",
      "key",
      "click",
      "touch",
      "scene"
     ],
     "description": "When the script runs. start, talk-start, talk-end and scene fire today; key and click fire in the block editor; beat, loud, every and touch load and save but do not fire yet."
    }
   }
  },
  "blocks": {
   "type": "array",
   "items": {
    "$ref": "#/$defs/block"
   }
  },
  "block": {
   "type": "object",
   "required": [
    "op"
   ],
   "properties": {
    "op": {
     "enum": [
      "set",
      "ramp",
      "wait",
      "for",
      "while",
      "until",
      "repeat",
      "forever",
      "together",
      "if",
      "stop",
      "stopAll",
      "wave",
      "hop",
      "gait",
      "drive",
      "mood",
      "setVar",
      "changeVar",
      "move",
      "moveTo",
      "turn",
      "turnTo",
      "scaleTo",
      "squash",
      "setPart",
      "turnPart",
      "liftPart",
      "bob",
      "sway",
      "wobble",
      "shake",
      "swingPart",
      "window",
      "chain",
      "follow",
      "reach",
      "release",
      "view",
      "swish",
      "flop",
      "bend",
      "bow",
      "letFollow",
      "turnView",
      "say",
      "does",
      "caption",
      "cut",
      "enter",
      "exit",
      "place"
     ],
     "description": "The block. The other fields are its arguments (the block language reference, sections 3, 4, 7 and 8)."
    },
    "body": {
     "$ref": "#/$defs/blocks"
    },
    "else": {
     "$ref": "#/$defs/blocks"
    },
    "branches": {
     "type": "array",
     "items": {
      "$ref": "#/$defs/blocks"
     }
    },
    "note": {
     "type": "string"
    },
    "id": {
     "type": "string"
    }
   }
  },
  "castEntry": {
   "oneOf": [
    {
     "type": "string",
     "description": "A role description, e.g. \"any\"."
    },
    {
     "type": "object",
     "properties": {
      "name": {
       "type": "string"
      },
      "legs": {
       "type": "integer",
       "minimum": 0
      },
      "voice": {
       "type": "string"
      },
      "note": {
       "type": "string"
      },
      "at": {
       "type": "object",
       "properties": {
        "x": {
         "type": "number"
        },
        "y": {
         "type": "number"
        },
        "h": {
         "type": "number",
         "exclusiveMinimum": 0
        },
        "facing": {
         "enum": [
          1,
          -1
         ]
        }
       }
      },
      "pack": {
       "oneOf": [
        {
         "type": "string",
         "pattern": "^[a-z0-9]+(:[a-z0-9_.-]+)+$"
        },
        {
         "type": "object",
         "required": [
          "id"
         ],
         "properties": {
          "id": {
           "type": "string",
           "pattern": "^[a-z0-9]+(:[a-z0-9_.-]+)+$"
          },
          "version": {
           "type": "string"
          }
         }
        }
       ]
      },
      "look": {
       "type": "object"
      }
     }
    }
   ]
  }
 }
}
