JSON Schema
The JSON form of an MSR record is described by this JSON Schema
(docs/spec/0.1/msr.schema.json). The compact MS1: envelope decompresses to
the same JSON.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://morpion-solitaire.io/spec/0.1/msr.schema.json",
"title": "MSR 0.1 — Morpion Solitaire Record",
"description": "Self-describing record for a Morpion Solitaire game. See docs/spec/0.1/msr.md. This schema validates the JSON form (the compact MS1: envelope decompresses to the same JSON).",
"type": "object",
"required": ["variant", "score", "moves"],
"additionalProperties": true,
"properties": {
"version": {
"description": "Format version, major.minor. \"0.1\" for this spec (a bare integer is accepted for backward compatibility).",
"type": ["string", "integer"],
"default": "0.1"
},
"variant": {
"description": "Variant code, digit first.",
"type": "string",
"enum": ["4T", "4D", "5T", "5D"]
},
"score": {
"description": "Number of moves (equals moves.length).",
"type": "integer",
"minimum": 0
},
"moves": {
"description": "Moves in play order.",
"type": "array",
"items": { "$ref": "#/$defs/move" }
},
"producer": {
"description": "Program that wrote the file, e.g. \"morpion-solitaire/0.1.0\".",
"type": "string"
},
"available_moves": {
"description": "Legal moves available at the final position (0 means terminal).",
"type": "integer",
"minimum": 0
},
"terminal": {
"description": "Whether the final position is terminal.",
"type": "boolean"
},
"bbox": {
"description": "Bounding box of all placed points: [min_x, min_y, max_x, max_y].",
"type": "array",
"items": { "type": "integer" },
"minItems": 4,
"maxItems": 4
},
"saved_at": {
"description": "ISO-8601 UTC save timestamp.",
"type": "string"
},
"description": { "type": "string" },
"author": {
"description": "Who set the record (person/team/handle).",
"type": "string"
},
"source": {
"description": "Where the game originates: a URL or citation (e.g. the original record site or an imported Pentasol file).",
"type": "string"
},
"transcribed_by": {
"description": "Who transcribed the game into MSR form (curator/project), distinct from source and author.",
"type": "string"
},
"tags": {
"description": "Free-form labels.",
"type": "array",
"items": { "type": "string" }
},
"solver": {
"description": "Automated-search provenance; present only for solver-produced games.",
"type": "object",
"additionalProperties": true,
"properties": {
"tool": {
"description": "The search tool/engine that produced the game (name or brand, e.g. \"morpion-solitaire.io\"). Distinct from the file-level producer.",
"type": "string"
},
"method": {
"description": "Algorithm and parameters, e.g. \"nrpa L3\". Does not restate the seed.",
"type": "string"
},
"seed": {
"description": "RNG seed, for reproducibility.",
"type": "integer",
"minimum": 0
},
"nodes_explored": {
"description": "Search effort in nodes.",
"type": "integer",
"minimum": 0
},
"elapsed_secs": {
"description": "Wall-clock seconds of the producing search.",
"type": "number",
"minimum": 0
}
}
}
},
"$defs": {
"move": {
"type": "object",
"required": ["x", "y", "dir", "pos"],
"additionalProperties": false,
"properties": {
"x": { "description": "X of the new point.", "type": "integer" },
"y": { "description": "Y of the new point.", "type": "integer" },
"dir": {
"description": "Direction code.",
"type": "string",
"enum": ["H", "V", "DP", "DN"]
},
"pos": {
"description": "Index of the new point within the line (0..line_len).",
"type": "integer",
"minimum": 0,
"maximum": 4
}
}
}
}
}