{"$schema":"https://json-schema.org/draft/2020-12/schema","title":"GameState","type":"object","properties":{"formatVersion":{"type":"integer","format":"uint32","minimum":0},"engineVersion":{"type":"string"},"tick":{"type":"integer","format":"uint64","minimum":0},"location":{"$ref":"#/$defs/Location"},"values":{"description":"Game values.","type":"object","additionalProperties":{"$ref":"#/$defs/Scalar"},"default":{}},"characters":{"type":"object","additionalProperties":{"$ref":"#/$defs/CharacterState"},"default":{}},"party":{"description":"Order; the first `maxActivePartySize` fight.","type":"array","items":{"type":"string"},"default":[]},"inventory":{"type":"array","items":{"$ref":"#/$defs/ThingQty"},"default":[]},"storages":{"description":"Storage ID → contents.","type":"object","additionalProperties":{"type":"array","items":{"$ref":"#/$defs/ThingQty"}},"default":{}},"made":{"description":"L-176: every thing made in this playthrough, by its ID (`mad_<n>`, counting up), with the\nparts it was made with: wherever it is (carried, kept, worn), its key names it here.","type":"object","additionalProperties":{"$ref":"#/$defs/Made"}},"runMaps":{"description":"L-90: the run maps this playthrough made, by passage.","type":"object","additionalProperties":{"$ref":"#/$defs/RunMapState"}},"shops":{"description":"Shop ID → thing ID → how many are left, for offers with a stock once one was bought.","type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"integer","format":"uint32","minimum":0}}},"mounts":{"description":"Rider → mount (character IDs).","type":"object","additionalProperties":{"type":"string"},"default":{}},"outfits":{"description":"Character → outfit worn, when not its first.","type":"object","additionalProperties":{"type":"string"}},"knowledge":{"$ref":"#/$defs/Knowledge","default":{"passageVisits":{},"exitsUsed":[],"thingsObtained":[],"thingsRead":[],"enemiesSeen":[],"enemiesDefeated":{},"charactersMet":[]}},"battle":{"anyOf":[{"$ref":"#/$defs/BattleState"},{"type":"null"}],"default":null},"dungeon":{"description":"Dungeons (L-155): where the party is in the dungeon last entered, and what it changed in\neach (kept when left).","anyOf":[{"$ref":"#/$defs/DungeonState"},{"type":"null"}]},"dungeonsLeft":{"type":"array","items":{"$ref":"#/$defs/DungeonState"}},"vehicles":{"description":"Maps: where each vehicle that waits where it was left is now, when it moved from its\n`startsAt` (L-64; a save without it loads with every vehicle at its start).","type":"object","additionalProperties":{"type":"string"}},"noEncounters":{"description":"A test state's *No encounters on the way* (L-63): no battle comes by chance.","type":"boolean"},"clock":{"description":"Time (P6-09): the clock, in minutes since day 1, 0:00 (a save without it starts at the\nstart time; none without the feature).","type":["integer","null"],"format":"uint64","minimum":0},"weather":{"description":"Weather (P6-10): the weather now, a kind's ID (a save without it starts at the start\nweather; none without the feature).","type":["string","null"]},"waysOn":{"description":"Weather (P6-30): the passages entered by a way on, the count `passages` looks at (a start,\na load, a jump, camp, a dream from _Sleep_, a test state and the debug panel's visits do\nnot raise it; a save without it starts from its passages' visits; none without the\nfeature).","type":["integer","null"],"format":"uint32","minimum":0},"rng":{"description":"The random stream (PCG state as 16 hex digits): the engine's only one (P8-12).","type":"string"},"shuffles":{"description":"`shuffle` tokens (passage and token text): the variants shown so far.","type":"object","additionalProperties":{"type":"array","items":{"type":"integer","format":"uint32","minimum":0}}},"decks":{"description":"Decks (L-29): deck ID → the cards used up, in the order drawn.","type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},"lastCards":{"description":"Decks (L-29): deck ID → the card it gave last (not twice in a row).","type":"object","additionalProperties":{"type":"string"}},"modules":{"description":"Module packages' own state (L-197; docs/architecture_spec.md, \"Modules with code\"): by\npackage ID, what its state schema allows, migrated by its own migrations. Not written while\nempty (a save without it reads as before).","type":"object","additionalProperties":true},"moduleVersions":{"description":"The modules the game was made with and their versions (L-197): the content's\n`moduleVersions` when the game started, kept by its saves; loading a save that names a\nnewer major than the engine carries is refused (`save.module_newer`). Not written while\nempty.","type":"object","additionalProperties":{"type":"string"}}},"required":["formatVersion","engineVersion","tick","location","rng"],"$defs":{"Location":{"type":"object","properties":{"passageId":{"type":"string"},"stepIndex":{"type":"integer","format":"uint32","minimum":0},"pending":{"anyOf":[{"$ref":"#/$defs/Pending"},{"type":"null"}]},"offeredExits":{"type":["array","null"],"items":{"$ref":"#/$defs/OfferedExit"}},"activeExitPath":{"description":"Exits being resolved: choice → check/battle outcome → …","type":"array","items":{"type":"string"},"default":[]},"replyIndex":{"description":"Position in a stay or wrong-thing reply.","type":["integer","null"],"format":"uint32","minimum":0},"replyKind":{"anyOf":[{"$ref":"#/$defs/ReplyKind"},{"type":"null"}]},"level":{"description":"The reply options on offer (L-20): the exits whose options they are, outermost first;\nnone at the passage's own options.","type":"array","items":{"type":"string"}},"checkResolved":{"anyOf":[{"$ref":"#/$defs/CheckResolved"},{"type":"null"}]},"readerThingId":{"type":["string","null"]},"shopId":{"description":"The shop open over the story.","type":["string","null"]},"endingId":{"type":["string","null"]},"returnStack":{"type":"array","items":{"type":"string"},"default":[]},"returnLevels":{"description":"By position in `return_stack`: the reply options a visit left from (L-20); `back`\nresumes there.","type":"object","additionalProperties":false,"patternProperties":{"^\\d+$":{"type":"array","items":{"type":"string"}}}},"returnLines":{"description":"The line read last in each passage on the return stack: shown again on *Return from\nvisit*, after a load too.","type":"object","additionalProperties":{"$ref":"#/$defs/ShownLine"}},"backdropPassageId":{"type":["string","null"],"default":null},"stage":{"type":"array","items":{"$ref":"#/$defs/StageEntry"},"default":[]},"screen":{"description":"What `screen` steps left in place: a tint, a filter, weather.","anyOf":[{"$ref":"#/$defs/ScreenState"},{"type":"null"}]},"media":{"$ref":"#/$defs/MediaState","default":{"music":null,"ambience":null,"background":null}},"place":{"description":"Maps: the current place.","anyOf":[{"$ref":"#/$defs/PlaceAt"},{"type":"null"}]},"travel":{"description":"Maps: what the travel target waiting now offers.","anyOf":[{"$ref":"#/$defs/TravelOffer"},{"type":"null"}]},"lastLine":{"description":"The line shown last in this passage, as the player read it: shown again after a load\nwithout drawing its variants anew.","anyOf":[{"$ref":"#/$defs/ShownLine"},{"type":"null"}]},"createRerolls":{"description":"Character creation (L-32): how often the numbers were rolled again on the screen open now.","type":["integer","null"],"format":"uint32","minimum":0},"camp":{"description":"Camp (P6-08): camp is made; the return stack's length with the way back on it (*Break\ncamp* goes back to that entry, a `back` below it breaks camp too).","type":["integer","null"],"format":"uint32","minimum":0},"campMedia":{"description":"Camp (P6-11): the music and ambience that played when camp was made; breaking camp brings\nthem back, so the camp's own sound (its fire) ends with it. None in saves from before.","anyOf":[{"$ref":"#/$defs/MediaState"},{"type":"null"}]}},"required":["passageId","stepIndex"]},"Pending":{"oneOf":[{"type":"string","enum":["step","continue","choices","stay","check","ask","read","battle","ending"]},{"description":"A `shop` step waits until the shop closes.","type":"string","const":"shop"},{"description":"Maps: a travel target waits for a place.","type":"string","const":"travel"},{"description":"A `create` step waits until the player is done making their character (L-32).","type":"string","const":"create"}]},"OfferedExit":{"type":"object","properties":{"exitId":{"type":"string"},"enabled":{"type":"boolean"}},"required":["exitId","enabled"]},"ReplyKind":{"type":"string","enum":["stay","wrong_thing","combination"]},"CheckResolved":{"type":"object","properties":{"plus":{"type":"number","format":"double"},"target":{"type":"number","format":"double"}},"required":["plus","target"]},"ShownLine":{"description":"A line as it was shown (docs/game_systems_spec.md, \"Announcing the position\").","type":"object","properties":{"stepId":{"type":"string"},"speakerId":{"type":["string","null"]},"expressionId":{"type":["string","null"]},"spans":{"type":"array","items":{"$ref":"#/$defs/TextSpan"}}},"required":["stepId","spans"]},"TextSpan":{"description":"A run of story text with one formatting and the same effects (docs/game_systems_spec.md,\n\"Text\"; effects inside a line: \"Individual looks and finish\").","type":"object","properties":{"text":{"type":"string"},"bold":{"type":"boolean"},"italic":{"type":"boolean"},"color":{"description":"A colour of the look: `accent`, `muted`, or a tone made readable on its background.","anyOf":[{"$ref":"#/$defs/SpanColor"},{"type":"null"}]},"size":{"anyOf":[{"$ref":"#/$defs/SpanSize"},{"type":"null"}]},"motion":{"description":"Shaking or wavy words (standing still with *Reduce motion*).","anyOf":[{"$ref":"#/$defs/SpanMotion"},{"type":"null"}]},"speed":{"description":"The words appear more slowly or faster while the line appears.","anyOf":[{"$ref":"#/$defs/SpanSpeed"},{"type":"null"}]},"pause":{"description":"A pause while the line appears, in milliseconds (a span without text).","type":["integer","null"],"format":"uint32","minimum":0},"ruby":{"description":"The reading shown above the span's text (ruby, for East Asian scripts).","type":["string","null"]},"entryId":{"description":"Words marked for a collection entry: a tap opens it (L-87).","type":["string","null"]},"revealed":{"description":"For marked words: whether the entry has a revealed section (after reading them).","type":"boolean"}},"required":["text"]},"SpanColor":{"type":"string","enum":["accent","muted","red","orange","gold","green","blue","purple"]},"SpanSize":{"type":"string","enum":["small","big"]},"SpanMotion":{"type":"string","enum":["shake","wave"]},"SpanSpeed":{"type":"string","enum":["slow","fast"]},"StageEntry":{"type":"object","properties":{"characterId":{"type":"string"},"position":{"$ref":"#/$defs/StagePosition"},"expressionId":{"type":["string","null"]},"flip":{"description":"Faces the other way.","type":"boolean"},"outfit":{"description":"In events only: the picture of the outfit worn (a character with outfits).","anyOf":[{"$ref":"#/$defs/ImageRef"},{"type":"null"}]}},"required":["characterId","position"]},"StagePosition":{"type":"string","enum":["left","left_center","center","center_right","right"]},"ImageRef":{"type":"object","properties":{"assetId":{"type":"string"},"alt":{"type":["string","null"]}},"required":["assetId"]},"ScreenState":{"description":"What `screen` steps left in place.","type":"object","properties":{"tint":{"anyOf":[{"$ref":"#/$defs/Tint"},{"type":"null"}]},"weather":{"anyOf":[{"$ref":"#/$defs/Weather"},{"type":"null"}]},"filter":{"anyOf":[{"$ref":"#/$defs/ScreenFilter"},{"type":"null"}]},"variant":{"description":"The look variant a `screen` step chose (L-48).","type":["string","null"]},"camera":{"description":"The camera's framing of the scene picture (L-37; none: the whole picture).","anyOf":[{"$ref":"#/$defs/Camera"},{"type":"null"}]}}},"Tint":{"type":"object","properties":{"color":{"description":"`#rrggbb`.","type":"string"},"amount":{"description":"0–1.","type":"number","format":"double"}},"required":["color","amount"]},"Weather":{"type":"string","enum":["none","rain","snow","fog","petals","leaves","embers","dust","fireflies"]},"ScreenFilter":{"description":"A filter over the scene picture and the stage, kept until changed like the tint.","type":"string","enum":["none","sepia","greyscale","blur","vignette"]},"Camera":{"description":"The camera's framing (L-37): `zoom` times as close, centred on the point `x`, `y` of the\nscene picture (fractions of its width and height).","type":"object","properties":{"zoom":{"description":"1–4.","type":"number","format":"double"},"x":{"description":"0–1, from the left.","type":"number","format":"double"},"y":{"description":"0–1, from the top.","type":"number","format":"double"}},"required":["zoom","x","y"]},"MediaState":{"type":"object","properties":{"music":{"type":["string","null"],"default":null},"ambience":{"type":["string","null"],"default":null},"music_volume":{"description":"The music's and the ambience's loudness, 0–100 (L-192; none: 100).","type":["integer","null"],"format":"uint8","minimum":0,"maximum":255},"ambience_volume":{"type":["integer","null"],"format":"uint8","minimum":0,"maximum":255},"weather_quiet":{"description":"The weather's own sound faded out until the weather changes (L-192).","type":"boolean"},"background":{"anyOf":[{"$ref":"#/$defs/ImageRef"},{"type":"null"}],"default":null}}},"PlaceAt":{"description":"Where the player is on a map.","type":"object","properties":{"mapId":{"type":"string"},"placeId":{"type":"string"}},"required":["mapId","placeId"]},"TravelOffer":{"description":"What a travel target offers while it waits for the player.","type":"object","properties":{"mapId":{"type":"string"},"fromPlaceId":{"type":["string","null"]},"destinations":{"type":"array","items":{"$ref":"#/$defs/TravelDestination"}},"canCancel":{"type":"boolean"},"closedRouteIds":{"description":"The routes shown closed, decided with the offer: after a load and in the menu's map the\nlocks match the places offered. Always stored (a save from before format version 4 gets it\nfrom the migration).","type":"array","items":{"type":"string"}}},"required":["mapId","destinations","canCancel","closedRouteIds"]},"TravelDestination":{"description":"A place a travel target offers, and the routes of the way there.","type":"object","properties":{"placeId":{"type":"string"},"routeIds":{"type":"array","items":{"type":"string"}},"vehicleId":{"description":"By this vehicle (none: on foot; L-64). A place reachable in several ways is offered\nonce per way.","type":["string","null"]}},"required":["placeId","routeIds"]},"Scalar":{"description":"A value of a `ValueDef`: yes/no, number, text or a list's entries (L-20: item keys in a\n`default`, item IDs in a game state).","anyOf":[{"type":"boolean"},{"type":"number","format":"double"},{"type":"string"},{"type":"array","items":{"type":"string"}}]},"CharacterState":{"type":"object","properties":{"base":{"description":"Base values: the starting value plus every `set` and `change` since.","type":"object","additionalProperties":{"$ref":"#/$defs/Scalar"},"default":{}},"level":{"type":"integer","format":"uint32","minimum":0},"xp":{"type":"number","format":"double","default":0},"skills":{"type":"array","items":{"$ref":"#/$defs/SkillState"},"default":[]},"skillPoints":{"type":"integer","format":"uint32","minimum":0,"default":0},"statPoints":{"type":"integer","format":"uint32","minimum":0,"default":0},"statuses":{"type":"array","items":{"$ref":"#/$defs/StatusState"},"default":[]},"equipment":{"description":"Slot ID → thing ID.","type":"object","additionalProperties":{"type":"string"},"default":{}},"secondSet":{"description":"P8-87: the weapons it keeps at hand to swap to in a dice battle (slot ID → a thing it\ncarries).","type":"object","additionalProperties":{"type":"string"}},"row":{"description":"The row chosen with `set_row` or _Change row_ (L-69; none: the character's `row`).","anyOf":[{"$ref":"#/$defs/Row"},{"type":"null"}]}},"required":["level"]},"SkillState":{"type":"object","properties":{"skillId":{"type":"string"},"rank":{"type":"integer","format":"uint32","minimum":0}},"required":["skillId","rank"]},"StatusState":{"type":"object","properties":{"statusId":{"type":"string"},"remaining":{"type":["integer","null"],"format":"uint32","minimum":0}},"required":["statusId"]},"Row":{"description":"A fighter's row (L-69).","type":"string","enum":["front","back"]},"ThingQty":{"type":"object","properties":{"thingId":{"type":"string"},"qty":{"type":"integer","format":"uint32","minimum":0},"made":{"description":"L-176: a made thing's ID (`mad_<n>`, its parts in `GameState.made`; never stacked: `qty`\n1); none: a plain thing.","type":["string","null"]}},"required":["thingId","qty"]},"Made":{"description":"L-176: one thing the game made: its pattern and the parts it was made with.","type":"object","properties":{"thingId":{"type":"string"},"parts":{"type":"array","items":{"type":"string"},"default":[]}},"required":["thingId"]},"RunMapState":{"description":"A run map as this playthrough made it (`GameState.runMaps`, by passage).","type":"object","properties":{"rows":{"description":"Each row's places, bottom first, as their kinds' IDs.","type":"array","items":{"type":"array","items":{"type":"string"}}},"links":{"type":"array","items":{"$ref":"#/$defs/RunLink"}},"passed":{"description":"The places passed, `[row, index]`, in order.","type":"array","items":{"type":"array","items":{"type":"integer","format":"uint32","minimum":0},"minItems":2,"maxItems":2}}},"required":["rows","links"]},"RunLink":{"description":"One link between a place and a place of the next row.","type":"object","properties":{"row":{"type":"integer","format":"uint32","minimum":0},"from":{"type":"integer","format":"uint32","minimum":0},"to":{"type":"integer","format":"uint32","minimum":0}},"required":["row","from","to"]},"Knowledge":{"type":"object","properties":{"passageVisits":{"type":"object","additionalProperties":{"type":"integer","format":"uint32","minimum":0},"default":{}},"rulesHeld":{"description":"Story rules (L-19): those whose condition held at the last look, and those that moved the\nstory (a rule without `again` moves it once).","type":"array","items":{"type":"string"}},"rulesDone":{"type":"array","items":{"type":"string"}},"exitsUsed":{"type":"array","items":{"type":"string"},"default":[]},"thingsObtained":{"type":"array","items":{"type":"string"},"default":[]},"thingsRead":{"type":"array","items":{"type":"string"},"default":[]},"placesFound":{"description":"Maps: places found (not those known from the start).","type":"array","items":{"type":"string"}},"timesRead":{"description":"How often each thing's pages were read (`first/then`, `once`, `cycle` on pages).","type":"object","additionalProperties":{"type":"integer","format":"uint32","minimum":0}},"pagesSeen":{"description":"Things on the game screen (L-174): the pages shown at their last reading, so a page shown\nsince is new.","type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},"enemiesSeen":{"type":"array","items":{"type":"string"},"default":[]},"enemiesDefeated":{"type":"object","additionalProperties":{"type":"integer","format":"uint32","minimum":0},"default":{}},"charactersMet":{"description":"Spoke or were on stage.","type":"array","items":{"type":"string"},"default":[]}}},"BattleState":{"type":"object","properties":{"encounterId":{"type":"string"},"round":{"type":"integer","format":"uint32","minimum":0},"turnOrder":{"type":"array","items":{"type":"string"}},"turnIndex":{"type":"integer","format":"uint32","minimum":0},"combatants":{"type":"array","items":{"$ref":"#/$defs/Combatant"}},"ticks":{"description":"Active time: the engine ticks passed since the battle began.","type":"integer","format":"uint64","minimum":0},"passed":{"description":"Active time: party members who passed with *Next* (their turn has begun already).","type":"array","items":{"type":"string"}},"opening":{"description":"Who acts alone in the first round (L-63).","$ref":"#/$defs/BattleOpening"},"onTheWay":{"description":"A battle that came by chance on the way: what follows it (L-63).","anyOf":[{"$ref":"#/$defs/OnTheWay"},{"type":"null"}]},"night":{"description":"A fight that broke into a night in the camp (P6-08): won or fled, the camp again; lost,\nthe night's `lose`.","type":"boolean"},"plan":{"description":"Planned turns (L-84): the round being planned or played.","anyOf":[{"$ref":"#/$defs/RoundPlan"},{"type":"null"}]},"roundOrder":{"description":"The turn order the round in progress began in, set by a load when the content's has\nchanged since (active time or by rounds ↔ planned, P8-09); the next round follows the\ncontent's.","anyOf":[{"$ref":"#/$defs/TurnOrder"},{"type":"null"}]},"sceneUsed":{"description":"Scene actions used that are offered once per battle (L-95).","type":"array","items":{"type":"string"}},"told":{"description":"Intents told in words (L-98): the next actions foes chose ahead, with their lines, until\nthey act.","type":"array","items":{"$ref":"#/$defs/ToldIntent"}},"dice":{"description":"Dice battles with rerolls (L-99): the party member's throw at the start of its turn, kept\nuntil it attacks or the turn ends.","anyOf":[{"$ref":"#/$defs/HeldDice"},{"type":"null"}]},"extraTurn":{"description":"Dice battles (L-99): who acts once more after this turn (a combination's `extraTurn`).","type":["string","null"]},"initiative":{"description":"Dice battles with `initiative` (L-99): the throw for who starts is still to come.","type":"boolean"},"defenceWait":{"description":"Defence throws by click (L-99): the foe's action waiting for the party's \"Throw to defend\".","anyOf":[{"$ref":"#/$defs/DefenceWait"},{"type":"null"}]},"outplayWait":{"description":"P8-56: the party's attack whose `feint` or `shatter` waits for the player's choice, the\nfoe's defence already thrown and set against it.","anyOf":[{"$ref":"#/$defs/OutplayWait"},{"type":"null"}]},"tricksUsed":{"description":"Dice tricks (L-101): the tricks used in this battle, per fighter and skill or thing.","type":"array","items":{"$ref":"#/$defs/UsedTrick"}},"laidDefence":{"description":"Hidden throws (L-102): a foe's defence laid face down ahead of the party's attack.","anyOf":[{"$ref":"#/$defs/LaidDefence"},{"type":"null"}]},"initiativeKept":{"description":"`keepInitiative` (L-108): who kept the initiative this round (once a round each).","type":"array","items":{"type":"string"}},"select":{"description":"Choose your fighter (L-218): the fighter select still waiting for `pick_fighter` (the\nbattle has no combatants yet).","anyOf":[{"$ref":"#/$defs/FighterSelect"},{"type":"null"}]},"standIn":{"description":"L-218: the party's side fights as stand-ins (a roster battle): nothing of the fight is\nwritten back to the characters, so every fight starts fresh.","type":"boolean"}},"required":["encounterId","round","turnOrder","turnIndex","combatants"]},"Combatant":{"type":"object","properties":{"combatantId":{"type":"string"},"source":{"$ref":"#/$defs/CombatantSource"},"side":{"$ref":"#/$defs/CombatSide"},"values":{"description":"Without status modifiers.","type":"object","additionalProperties":{"type":"number","format":"double"}},"statuses":{"type":"array","items":{"$ref":"#/$defs/StatusState"},"default":[]},"cooldowns":{"type":"object","additionalProperties":{"type":"integer","format":"uint32","minimum":0},"default":{}},"defending":{"type":"boolean"},"defeated":{"type":"boolean"},"time":{"description":"Active time: the time gauge, 0 to 1000.","type":["integer","null"],"format":"uint32","minimum":0},"timeFill":{"description":"Active time: what the gauge gains per tick, as last worked out.","type":["integer","null"],"format":"uint32","minimum":0},"row":{"description":"With rows: `back` in the back row (L-69; none: the front row, or no rows).","anyOf":[{"$ref":"#/$defs/Row"},{"type":"null"}]},"stolen":{"description":"Robbed already in this battle (L-70): \"Nothing left to steal\".","type":"boolean"},"morale":{"description":"A foe's morale (L-96).","anyOf":[{"$ref":"#/$defs/MoraleState"},{"type":"null"}]},"yielded":{"description":"How it gave in at its morale (L-96): it fights no more (and counts as `defeated`).","anyOf":[{"$ref":"#/$defs/MoraleThen"},{"type":"null"}]},"shieldZone":{"description":"Shields (L-106): the zone its shield is held in (with `covers: 2` this one and the next\ndown; none: the middle).","anyOf":[{"$ref":"#/$defs/Zone"},{"type":"null"}]},"shieldBrokenBy":{"description":"Shields (L-106): broken by this fighter's weapon, its armour counts nothing until the end\nof that fighter's next turn.","type":["string","null"]},"momentum":{"description":"Momentum (L-108): added to its next attack throws' sums until one of them hits.","type":"number","format":"double"},"fewerDice":{"description":"`foeFewerDice` (L-108): its next throw has one die fewer.","type":"boolean"},"guardBrokenBy":{"description":"`breakGuard` (L-108): broken by this fighter's throw, its Armour, shield and defence count\nnothing until the end of that fighter's next turn.","type":["string","null"]},"disarmed":{"description":"`disarm` (L-109): its weapons count nothing until the end of its next turn.","type":"boolean"},"swapped":{"description":"P8-87: it swapped its weapons this turn: its attack throws without a boost.","type":"boolean"},"gear":{"description":"P8-87: a foe's things after it swapped (none: its `combat.gear`).","type":["array","null"],"items":{"type":"string"}}},"required":["combatantId","source","side","values","defending","defeated"]},"CombatantSource":{"anyOf":[{"type":"object","properties":{"characterId":{"type":"string"}},"required":["characterId"]},{"type":"object","properties":{"enemyId":{"type":"string"},"level":{"type":"integer","format":"uint32","minimum":0}},"required":["enemyId","level"]}]},"CombatSide":{"type":"string","enum":["party","foe"]},"MoraleState":{"description":"A foe's morale in battle (L-96): its bar, the point it gives in at, and what it does then.","type":"object","properties":{"current":{"type":"number","format":"double"},"max":{"type":"number","format":"double"},"yieldsAt":{"type":"number","format":"double"},"then":{"$ref":"#/$defs/MoraleThen"}},"required":["current","max","yieldsAt","then"]},"MoraleThen":{"description":"How a foe gives in (L-96): it flees, it surrenders (stays, harmless), or it joins the party (a\ncharacter foe only).","type":"string","enum":["flee","surrender","join"]},"Zone":{"description":"Hit zones (L-104; docs/game_systems_spec.md, \"Dice battles\", \"Hit zones\"): where a die is aimed,\nthe first die `top`, the second `middle`, the third `bottom`; with four zones (L-187,\n`DiceRules.fourZones`) the same three are the head, the torso and the legs (`head`, `torso`,\n`legs` read as them) and the fourth die goes to the `feet`.","oneOf":[{"type":"string","enum":["top","middle","bottom"]},{"description":"L-187: only with four zones.","type":"string","const":"feet"},{"description":"P8-111: only with five zones, between the torso and the legs (gloves).","type":"string","const":"hands"}]},"BattleOpening":{"description":"How a battle opens (L-63): `party_first` lets the party act alone in the first round,\n`ambush` the foes.","type":"string","enum":["normal","party_first","ambush"]},"OnTheWay":{"description":"What follows a battle on the way: a won or fled one goes on into the passage (its steps from\nthe first) or along the rest of the way; a lost one takes the area's `lose`.","type":"object","properties":{"areaId":{"type":"string"},"travel":{"description":"Travelling: the way being travelled (none: the passage just entered).","anyOf":[{"$ref":"#/$defs/WayLeft"},{"type":"null"}]}},"required":["areaId"]},"WayLeft":{"description":"A way on the map interrupted by a battle: the routes of the whole way and how many are behind.","type":"object","properties":{"mapId":{"type":"string"},"fromPlaceId":{"type":["string","null"]},"toPlaceId":{"type":"string"},"routeIds":{"type":"array","items":{"type":"string"}},"done":{"description":"Routes travelled already.","type":"integer","format":"uint32","minimum":0},"vehicleId":{"description":"By a vehicle (L-64).","type":["string","null"]}},"required":["mapId","toPlaceId","routeIds","done"]},"RoundPlan":{"description":"Planned turns (L-84): a round's chains, in the round's order by speed.","type":"object","properties":{"phase":{"$ref":"#/$defs/PlanPhase"},"chains":{"type":"array","items":{"$ref":"#/$defs/Chain"}},"replanned":{"description":"The chains were changed once this round (`replan`).","type":"boolean"},"begun":{"description":"Every combatant's turn of the round has begun (`turn_start` ticks, cooldowns).","type":"boolean"},"last":{"description":"The last action on the timeline: who acted and the skill used (none: not a skill), for\ncombos after an ally.","anyOf":[{"$ref":"#/$defs/LastAction"},{"type":"null"}]}},"required":["phase","chains"]},"PlanPhase":{"oneOf":[{"description":"The party plans; the round stands still.","type":"string","const":"planning"},{"description":"The round's first actions played; the party may change its chains once.","type":"string","const":"replan"},{"description":"The chains play on the timeline.","type":"string","const":"playing"}]},"Chain":{"description":"One fighter's chain in a round.","type":"object","properties":{"combatantId":{"type":"string"},"budget":{"description":"The fighter's time this round.","type":"integer","format":"uint32","minimum":0},"actions":{"description":"The actions planned (a foe's intent first; foes and auto battle choose the rest as they go).","type":"array","items":{"$ref":"#/$defs/BattleAction"},"default":[]},"next":{"description":"How many of `actions` were played or cut.","type":"integer","format":"uint32","minimum":0,"default":0},"at":{"description":"The time the chain has reached: its next action plays then.","type":"integer","format":"uint32","minimum":0,"default":0},"done":{"description":"Nothing more this round (played out, cut, or out of time).","type":"boolean"},"live":{"description":"Chooses its further actions as it goes (foes, auto battle).","type":"boolean"},"lastSkill":{"description":"The skill of the chain's previous action (none: not a skill), for combos.","type":["string","null"]}},"required":["combatantId","budget"]},"BattleAction":{"description":"Read by a hand-written reader (`tagged.rs`) that keeps the player's engine small.","oneOf":[{"type":"object","properties":{"skillId":{"type":"string"},"targets":{"type":"array","items":{"type":"string"}},"type":{"type":"string","const":"skill"}},"required":["type","skillId","targets"]},{"type":"object","properties":{"thingId":{"type":"string"},"targets":{"type":"array","items":{"type":"string"}},"type":{"type":"string","const":"thing"}},"required":["type","thingId","targets"]},{"type":"object","properties":{"type":{"type":"string","const":"defend"}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"flee"}},"required":["type"]},{"description":"Rows (L-69): to the other row; takes the turn.","type":"object","properties":{"type":{"type":"string","const":"change_row"}},"required":["type"]},{"description":"One of the encounter's scene actions (L-95); takes the turn.","type":"object","properties":{"sceneActionId":{"type":"string"},"targets":{"type":"array","items":{"type":"string"}},"type":{"type":"string","const":"scene_action"}},"required":["type","sceneActionId","targets"]}]},"LastAction":{"type":"object","properties":{"combatantId":{"type":"string"},"skillId":{"type":["string","null"]}},"required":["combatantId"]},"TurnOrder":{"oneOf":[{"type":"string","enum":["round_by_speed","party_first"]},{"description":"Time gauges fill with speed; whoever's is full acts.","type":"string","const":"active_time"},{"description":"Each round is planned as chains of actions, then played on one timeline (L-84).","type":"string","const":"planned"}]},"ToldIntent":{"description":"A foe's next action chosen ahead and its line (L-98).","type":"object","properties":{"combatantId":{"type":"string"},"action":{"$ref":"#/$defs/BattleAction"},"text":{"description":"The behaviour row's `tell` as shown (none: the row has none).","type":["string","null"]}},"required":["combatantId","action"]},"HeldDice":{"description":"A throw held for rerolls (L-99).","type":"object","properties":{"fighterId":{"type":"string"},"dice":{"type":"array","items":{"type":"integer","format":"uint32","minimum":0}},"rerollsLeft":{"type":"integer","format":"uint32","minimum":0},"paid":{"description":"Skills paid with a die (L-105): the skills paid from this throw this turn.","type":"array","items":{"type":"string"}},"run":{"description":"Extending a run (L-99): the run as extended so far (none: not extended).","anyOf":[{"$ref":"#/$defs/HeldRun"},{"type":"null"}]}},"required":["fighterId","dice","rerollsLeft"]},"HeldRun":{"description":"Extending a run (L-99): a held run grown by `extend_run`.","type":"object","properties":{"low":{"description":"The run's lowest and highest die now.","type":"integer","format":"uint32","minimum":0},"high":{"type":"integer","format":"uint32","minimum":0},"steps":{"description":"The dice that continued it.","type":"integer","format":"uint32","minimum":0},"ended":{"description":"A die did not fit: no more extending.","type":"boolean"},"lost":{"description":"With `risk`: the miss lost the run's bonus for this attack.","type":"boolean"}},"required":["low","high","steps"]},"DefenceWait":{"description":"A foe's attack waiting for the party's defence throw (L-99).","type":"object","properties":{"attackerId":{"type":"string"},"action":{"$ref":"#/$defs/BattleAction"},"throw":{"description":"Dice tricks (L-101): the attack's throw, already on the table while the party may use a\ntrick on it.","anyOf":[{"$ref":"#/$defs/PendingThrow"},{"type":"null"}]},"defenceBonus":{"description":"Hidden throws (L-102): `plus` on the defender's dice, added to its defence throw.","type":"integer","format":"uint32","minimum":0},"dice":{"description":"Die against die (P8-27): the party's defence dice, thrown and held until they are paired\nwith the attack's dice.","type":["array","null"],"items":{"type":"integer","format":"uint32","minimum":0}},"rerolled":{"description":"P8-91: the held defence's pair reroll was used.","type":"boolean"}},"required":["attackerId","action"]},"PendingThrow":{"description":"Dice tricks (L-101): a foe's attack throw lying on the table before the party defends.","type":"object","properties":{"dice":{"type":"array","items":{"type":"integer","format":"uint32","minimum":0}},"first":{"description":"The first throw, before the thrower's rerolls (`lock` goes back to it).","type":"array","items":{"type":"integer","format":"uint32","minimum":0}},"kept":{"type":"array","items":{"type":"boolean"}},"broken":{"description":"`break`: its combination does not count.","type":"boolean"},"shown":{"description":"Hidden throws (L-102): per die whether it is face up (empty: all are).","type":"array","items":{"type":"boolean"}},"later":{"description":"Hidden throws (L-102): `plus`/`minus` to each die at the reveal.","type":"integer","format":"int32"}},"required":["dice","first","kept"]},"OutplayWait":{"description":"P8-56: a party attack whose `feint` or `shatter` waits for the player's choice (`outplay`):\nthe action, the foe's defence dice as thrown, and what the player sees at each place.","type":"object","properties":{"attackerId":{"type":"string"},"targetId":{"type":"string"},"action":{"$ref":"#/$defs/BattleAction"},"dice":{"description":"The defence dice as thrown (set against the attack again when the blow is made).","type":"array","items":{"type":"integer","format":"uint32","minimum":0}},"kinds":{"description":"The outplays to choose (`feint`, `shatter`).","type":"array","items":{"$ref":"#/$defs/DiceEffectKind"}},"attack":{"description":"Per place: the attack die, the defence die set against it (none: unguarded), and the\nplace's own armour (none: nothing reaches it).","type":"array","items":{"type":"integer","format":"uint32","minimum":0}},"defence":{"type":"array","items":{"type":["integer","null"],"format":"uint32","minimum":0}},"armour":{"type":"array","items":{"type":["number","null"],"format":"double"}},"stealth":{"description":"P8-66: per place, whether the attack die is a stealth 1 (none: no stealth 1s).","type":"array","items":{"type":"boolean"}}},"required":["attackerId","targetId","action","dice","kinds","attack","defence","armour"]},"DiceEffectKind":{"description":"`extraDamage`: added to the sum; `unblockable`: a blocked throw still deals 1; `critical`:\nmore damage (`amount` percent, none: 50, rounded down, at least 1 more); `wound`: a status on the target that lasts (see `StatusEffect.lasts`);\n`status`: a status on the target or the thrower; `extraTurn`: the thrower acts once more.\nL-108: `ignoreArmour`: the throw ignores `amount` (none: 2) of the target's Armour (with hit\nzones, of each zone's); `foeFewerDice`: the target throws one die fewer at its next throw\n(never below one); `keepInitiative`: the thrower acts again before the foe's next turn, once\na round; `breakGuard`: the target's Armour, shield and defence count nothing until the end of\nthe thrower's next turn. Like statuses, these four act when the throw hit.\nL-109, a defence throw's combinations: `brace` (the attack's `ignoreArmour` and\n`unblockable` do not count), `footwork` (half damage; with hit zones the highest attack die\nmoves to the better guarded neighbouring zone), `riposte` (the attack is turned away and the\ndefender strikes back), `disarm` (the attacker's weapons count nothing until the end of its\nnext turn), `perfectGuard` (the attack's damage goes back to the attacker); `clash` names the\nclash in a defence's event (not a combination's effect).","oneOf":[{"type":"string","enum":["extraDamage","unblockable","critical","wound","status","extraTurn","ignoreArmour","foeFewerDice","keepInitiative","breakGuard","brace","footwork","riposte","disarm","perfectGuard","clash"]},{"description":"P8-30, on a set defence throw: two of the attack's dice swap places (zones), the swap that\ngets most through.","type":"string","const":"feint"},{"description":"P8-30: the defence die that blocks most is taken away.","type":"string","const":"shatter"},{"description":"P8-30: no defence die counts on this blow (armour and shields still do).","type":"string","const":"breakthrough"},{"description":"P8-39, a run's: the run's dice all count as its highest die (3 · 4 · 5 → 5 · 5 · 5), turned\nbefore the defence meets them.","type":"string","const":"raiseToHighest"},{"description":"P8-42: the combination's dice count `amount` more each (a pair of 3s counts 4 · 4; a 6\ncounts 7), changed before the defence meets them.","type":"string","const":"raise"}]},"UsedTrick":{"description":"Dice tricks (L-101): a trick a fighter used in this battle.","type":"object","properties":{"fighterId":{"type":"string"},"sourceId":{"description":"The skill or thing.","type":"string"},"times":{"type":"integer","format":"uint32","minimum":0},"thisTurn":{"description":"Used in the turn running (once per turn).","type":"boolean"}},"required":["fighterId","sourceId","times"]},"LaidDefence":{"description":"Hidden throws (L-102): a foe's defence thrown ahead, face down, for the party member's turn.","type":"object","properties":{"fighterId":{"type":"string"},"throw":{"$ref":"#/$defs/PendingThrow"}},"required":["fighterId","throw"]},"FighterSelect":{"description":"A fighter select waiting (L-218): its fighters as they stood when it opened.","type":"object","properties":{"fighters":{"type":"array","items":{"$ref":"#/$defs/RosterFighter"}},"foePicks":{"description":"The engine picks the foe from the roster (`pick`); false: the encounter's own foes.","type":"boolean"},"canFlee":{"type":"boolean"}},"required":["fighters","foePicks","canFlee"]},"RosterFighter":{"description":"One fighter of a fighter select (L-218), as the player shows it.","type":"object","properties":{"characterId":{"type":"string"},"locked":{"type":"boolean"},"hint":{"description":"A locked fighter's hint (rendered).","type":["string","null"]},"hp":{"description":"Its defeat bar at its fullest, as it starts a fight (none: the game has no defeat bar).","type":["number","null"],"format":"double"},"worn":{"description":"The things it wears (their IDs, slot by slot): its weapons and shields on the card.","type":"array","items":{"type":"string"}},"noFoe":{"description":"L-220: not picked as the foe now (its `foeUnless` holds).","type":"boolean"}},"required":["characterId"]},"DungeonState":{"description":"Where the party is in a dungeon and what it changed there (L-155): saved with the game, kept\nwhen the dungeon is left.","type":"object","properties":{"passageId":{"type":"string"},"floorId":{"type":"string"},"x":{"type":"integer","format":"uint32","minimum":0},"y":{"type":"integer","format":"uint32","minimum":0},"facing":{"anyOf":[{"$ref":"#/$defs/Dir"},{"type":"null"}]},"seen":{"description":"The cells seen, per floor: `x,y`.","type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},"opened":{"description":"Locked doors opened: `floor:x,y:side`.","type":"array","items":{"type":"string"}},"done":{"description":"Features used up: `floor:x,y` (a chest opened, a battle won, a visit marked once, a\nteleport used).","type":"array","items":{"type":"string"}},"arrive":{"description":"The party fell through a teleport whose check failed (L-166): what stands where it landed\ncomes as the dungeon shows again.","type":"boolean"},"roamers":{"description":"The dungeon's roamers by ID (L-170), from the first step on.","type":"object","additionalProperties":{"$ref":"#/$defs/RoamerState"}}},"required":["passageId","floorId","x","y"]},"Dir":{"description":"A side of a cell, as the compass names it: north is up on the map.","type":"string","enum":["n","e","s","w"]},"RoamerState":{"description":"Where a roamer is and what became of it (L-170), saved with the game.","type":"object","properties":{"x":{"type":"integer","format":"uint32","minimum":0},"y":{"type":"integer","format":"uint32","minimum":0},"at":{"description":"Steps taken along its round.","type":"integer","format":"uint32","minimum":0},"chasing":{"type":"boolean"},"beaten":{"type":"boolean"}},"required":["x","y"]}}}