{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://marcallabs.co.uk/monster-schema.json",
  "title": "Dungeon Quest monster",
  "description": "One monster of the Pit beneath Grimhold, in Dungeon Quest (Marcal Labs). Upload as monsters/<id>.json with the puzzle checker. Rules this schema cannot express: (1) the characters < and > may not appear anywhere in the file; (2) in levels, group and damage the first number may not be bigger than the second; (3) a unique monster must have a group of [1, 1]; (4) each power may appear only once; (5) a summon power must name a monster already on the website (or its own id); (6) folklore creatures only: no monsters owned by game companies; (7) the file must be no bigger than 64 KB. Check files at https://marcallabs.co.uk/puzzle-checker.html.",
  "type": "object",
  "required": [
    "id",
    "name",
    "text",
    "kind",
    "levels",
    "rarity",
    "group",
    "behaviour",
    "hp",
    "damage",
    "speed",
    "xp",
    "treasure",
    "look"
  ],
  "additionalProperties": false,
  "properties": {
    "id": {
      "type": "string",
      "pattern": "^[a-z0-9-]{1,40}$",
      "description": "Short name in small letters, numbers and dashes; also the file name."
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 40,
      "description": "What the player calls it, in small letters unless a proper name."
    },
    "text": {
      "type": "string",
      "minLength": 1,
      "maxLength": 300,
      "description": "What the player sees when they meet it."
    },
    "say": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200,
      "description": "What it says when you meet it."
    },
    "kind": {
      "enum": [
        "vermin",
        "beast",
        "humanoid",
        "undead",
        "spirit",
        "giant",
        "dragon"
      ],
      "description": "Undead and spirits can be turned by a cleric; beasts and vermin cannot be bargained with."
    },
    "levels": {
      "type": "array",
      "minItems": 2,
      "maxItems": 2,
      "items": {
        "type": "integer",
        "minimum": 1,
        "maximum": 20
      },
      "description": "First and last dungeon levels it lives on (first no bigger than second)"
    },
    "rarity": {
      "type": "integer",
      "minimum": 1,
      "maximum": 10,
      "description": "1 very rare to 10 very common."
    },
    "group": {
      "type": "array",
      "minItems": 2,
      "maxItems": 2,
      "items": {
        "type": "integer",
        "minimum": 1,
        "maximum": 8
      },
      "description": "Fewest and most that come together (first no bigger than second)"
    },
    "behaviour": {
      "enum": [
        "guards",
        "wanders",
        "both"
      ],
      "description": "guards: stays in a room with its treasure; wanders: roams the corridors."
    },
    "unique": {
      "type": "boolean",
      "description": "A boss: only ever met once. Needs group [1, 1]."
    },
    "hp": {
      "type": "integer",
      "minimum": 1,
      "maximum": 999,
      "description": "Strength. A new hero has about 100."
    },
    "damage": {
      "type": "array",
      "minItems": 2,
      "maxItems": 2,
      "items": {
        "type": "integer",
        "minimum": 1,
        "maximum": 80
      },
      "description": "Least and most it hits for (first no bigger than second)"
    },
    "hit": {
      "type": "integer",
      "minimum": 10,
      "maximum": 95,
      "description": "Chance to hit, per cent. Default 65."
    },
    "armour": {
      "type": "integer",
      "minimum": 0,
      "maximum": 10,
      "description": "Taken off the damage of each of the player's hits. Default 0."
    },
    "speed": {
      "enum": [
        "slow",
        "medium",
        "fast"
      ],
      "description": "Fast monsters are hard to run from."
    },
    "xp": {
      "type": "integer",
      "minimum": 0,
      "maximum": 2000
    },
    "treasure": {
      "enum": [
        "none",
        "few",
        "some",
        "gold",
        "lots",
        "hoard"
      ]
    },
    "powers": {
      "type": "array",
      "maxItems": 4,
      "items": {
        "oneOf": [
          {
            "type": "object",
            "description": "Poisoned bite or sting: lose amount strength a turn for turns turns.",
            "additionalProperties": false,
            "required": [
              "power",
              "chance",
              "amount",
              "turns"
            ],
            "properties": {
              "power": {
                "const": "poison"
              },
              "chance": {
                "type": "integer",
                "minimum": 1,
                "maximum": 100
              },
              "amount": {
                "type": "integer",
                "minimum": 1,
                "maximum": 10
              },
              "turns": {
                "type": "integer",
                "minimum": 1,
                "maximum": 10
              }
            }
          },
          {
            "type": "object",
            "description": "Greatest strength drops by amount until the temple restores it.",
            "additionalProperties": false,
            "required": [
              "power",
              "chance",
              "amount"
            ],
            "properties": {
              "power": {
                "const": "drain"
              },
              "chance": {
                "type": "integer",
                "minimum": 1,
                "maximum": 100
              },
              "amount": {
                "type": "integer",
                "minimum": 1,
                "maximum": 10
              }
            }
          },
          {
            "type": "object",
            "description": "Snatches up to amount gold.",
            "additionalProperties": false,
            "required": [
              "power",
              "chance",
              "amount"
            ],
            "properties": {
              "power": {
                "const": "steal"
              },
              "chance": {
                "type": "integer",
                "minimum": 1,
                "maximum": 100
              },
              "amount": {
                "type": "integer",
                "minimum": 1,
                "maximum": 200
              }
            }
          },
          {
            "type": "object",
            "description": "You lose your next turn.",
            "additionalProperties": false,
            "required": [
              "power",
              "chance"
            ],
            "properties": {
              "power": {
                "const": "fear"
              },
              "chance": {
                "type": "integer",
                "minimum": 1,
                "maximum": 100
              }
            }
          },
          {
            "type": "object",
            "description": "You cannot run away for turns turns.",
            "additionalProperties": false,
            "required": [
              "power",
              "chance",
              "turns"
            ],
            "properties": {
              "power": {
                "const": "web"
              },
              "chance": {
                "type": "integer",
                "minimum": 1,
                "maximum": 100
              },
              "turns": {
                "type": "integer",
                "minimum": 1,
                "maximum": 5
              }
            }
          },
          {
            "type": "object",
            "description": "You hit less often until the temple lifts it.",
            "additionalProperties": false,
            "required": [
              "power",
              "chance"
            ],
            "properties": {
              "power": {
                "const": "curse"
              },
              "chance": {
                "type": "integer",
                "minimum": 1,
                "maximum": 100
              }
            }
          },
          {
            "type": "object",
            "description": "Once a fight, count of monster (another monster id) join in.",
            "additionalProperties": false,
            "required": [
              "power",
              "chance",
              "count",
              "monster"
            ],
            "properties": {
              "power": {
                "const": "summon"
              },
              "chance": {
                "type": "integer",
                "minimum": 1,
                "maximum": 100
              },
              "count": {
                "type": "integer",
                "minimum": 1,
                "maximum": 4
              },
              "monster": {
                "type": "string",
                "pattern": "^[a-z0-9-]{1,40}$",
                "description": "The id of the monster that comes to help."
              }
            }
          },
          {
            "type": "object",
            "description": "Heals amount every turn.",
            "additionalProperties": false,
            "required": [
              "power",
              "amount"
            ],
            "properties": {
              "power": {
                "const": "regenerate"
              },
              "amount": {
                "type": "integer",
                "minimum": 1,
                "maximum": 30
              }
            }
          },
          {
            "type": "object",
            "description": "Fire (or frost, or gas) for amount damage that armour does not stop.",
            "additionalProperties": false,
            "required": [
              "power",
              "chance",
              "amount"
            ],
            "properties": {
              "power": {
                "const": "breath"
              },
              "chance": {
                "type": "integer",
                "minimum": 1,
                "maximum": 100
              },
              "amount": {
                "type": "integer",
                "minimum": 1,
                "maximum": 80
              }
            }
          }
        ]
      }
    },
    "look": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "model",
        "size",
        "colour"
      ],
      "properties": {
        "model": {
          "enum": [
            "rat",
            "spider",
            "wolf",
            "goblin",
            "orc",
            "skeleton",
            "giant",
            "dragon",
            "man",
            "woman",
            "hooded",
            "farmer",
            "figure",
            "beast",
            "scorpion"
          ],
          "description": "3D models (rat to farmer) take on the colour; figure, beast and scorpion are drawn shapes."
        },
        "size": {
          "type": "number",
          "minimum": 0.2,
          "maximum": 8,
          "description": "Height in metres; a person is about 1.8."
        },
        "colour": {
          "type": "string",
          "pattern": "^#[0-9a-fA-F]{6}$"
        },
        "eyes": {
          "type": "string",
          "pattern": "^#[0-9a-fA-F]{6}$"
        },
        "extras": {
          "type": "array",
          "uniqueItems": true,
          "items": {
            "enum": [
              "ears",
              "tusks",
              "beard",
              "hood",
              "thin",
              "club",
              "blade",
              "ghostly",
              "glow"
            ]
          }
        }
      }
    }
  }
}
