From 047e645ca0163018393aac3296895cd90c54c1f1 Mon Sep 17 00:00:00 2001 From: Shane Kidd <33380501+StarshipSuperjam@users.noreply.github.com> Date: Wed, 12 Aug 2026 08:47:55 -0700 Subject: [PATCH 1/5] Fix: correct locked formation-index rule to match its cited reference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The locked difficulty-and-formations spec described the set-formation table index as "that offset plus the current AI level, doubled". The reference it cites does not add the AI level on that path: - sub_2_fn_2__set_flying_enemies indexes by the record's signed offset alone (sign-extended, doubled to address the 2-byte entries). - sub_2_fn_3 (the raise record) indexes the SAME table by the raised, folded AI level instead — with no record offset. The spec fused the two paths into one wrong "offset + level" formula. Under that reading the real committed schedules drive the index to 233, far past the table's -32..127 domain; under the reference reading, set offsets (-26..126) and the folded AI level (0..127) both land in range. The committed formations.json (domain -32..127, sized to the offset range) independently corroborates the reference, so only the prose was wrong — no data changes. Correcting a status:locked spec — carries guardrail-ack at merge. Co-Authored-By: Claude Opus 4.8 --- docs/spec/difficulty-and-formations.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/spec/difficulty-and-formations.md b/docs/spec/difficulty-and-formations.md index 00781d5..caa2368 100644 --- a/docs/spec/difficulty-and-formations.md +++ b/docs/spec/difficulty-and-formations.md @@ -26,7 +26,8 @@ read; the extractor proves no Super data reaches the committed files. **The AI level and difficulty setting.** A single AI-level value accumulates during play. Schedule records of the `raise_ai_level_and_set_formation` kind — one of the schedule's two most common record kinds — add the cabinet difficulty increment to the AI level *and then re-select the incoming formation from the -new level* (the same lookup the set-formation record uses, with the raised level as the index): the four DIP-selectable settings add +new level* (indexing the same formation table the set-formation record reads, but by the raised AI level in +place of a record offset): the four DIP-selectable settings add 2, 0, 6, or 16 respectively (`xevious_sub.68k` `difficulty_tbl` 338–342, decoded in [data/difficulty.json](data/difficulty.json); consumed by `sub_2_fn_3__inc_enemy_AI_and_flying_enemies` 317–329). If the raise would take the level to 0x80 or above, 0x40 is subtracted first (same routine) — the @@ -39,9 +40,11 @@ craft in reserve, capped at 16, and added to the AI level (`xevious_sub.68k` `sub_2_fn_23__adjust_AI_level_based_on_score` 344–353 and `avg_score_per_solvalou` 360–372). A player scoring heavily with many lives left meets sharply higher pressure; a struggling player is spared. -**Formation selection.** Schedule records of the *set-formation* kind carry a signed offset. The effective -index is that offset plus the current AI level, doubled, into the formation table -(`xevious_sub.68k` `sub_2_fn_2__set_flying_enemies` 300–311). The table — decoded completely, including +**Formation selection.** Schedule records of the *set-formation* kind carry a signed offset that is itself +the index into the formation table (`sub_2_fn_2__set_flying_enemies` sign-extends the record byte and doubles +it to address the two-byte entries — `xevious_sub.68k` 300–311); the AI level is **not** added on the +set-formation path. The raise record indexes the *same* table instead by the raised AI level (see "The AI +level and difficulty setting" above), with no record offset. The table — decoded completely, including its 32 negative-index entries, in [data/formations.json](data/formations.json) (`flying_enemy_type_offset_tbl_normal`; exact lines in the data file) — yields two values per entry: the number of flying enemies in the incoming wave (observed range 1–6) and an offset into the flying-enemy type table that @@ -67,7 +70,7 @@ carries their own difficulty state ([Cabinet flow](cabinet-flow.md)). | --- | --- | --- | | The committed formation table (including negative indices) and difficulty tables match a re-derivation from the pinned commit | `python3 tools/reference_extract.py --verify --checkout ` with a fresh clone at the pin (clone recipe in [the index](index.md)); the run passes or names the failing table | operator | | The four difficulty-setting increments are 2, 0, 6, 16 and the build's data matches the committed file | Data-table comparison in the deterministic build fixtures | engine | -| A model fixture over the committed data reproduces formation lookups (AI level + offset, fold-back at 0x80); the build's in-game selection is confirmed in play (a runtime-harness candidate once the enemy/formation slice ships) | Python fixture over the committed tables; operator play for the in-game half | engine | +| A model fixture over the committed data reproduces formation lookups (set-formation indexed by the record offset; raise indexed by the folded AI level; fold-back at 0x80); the build's in-game selection is confirmed in play (a runtime-harness candidate once the enemy/formation slice ships) | Python fixture over the committed tables; operator play for the in-game half | engine | | A model fixture over representative score/lives pairs computes the re-tune rule (score per reserve craft, capped at 16); the build's in-game re-tune is confirmed in play (a runtime-harness candidate once the lives slice ships) | Python fixture implementing the documented rule; operator play for the in-game half | engine | | Wave sizes stay within the table's recorded range and grow as the game progresses at a fixed setting | Play several areas at one setting; waves grow denser and never exceed six enemies | operator | | Playing better produces visibly harder waves | Play one area twice — once scoring heavily, once minimally — and compare wave pressure (paired with the seeded re-tune fixture above, since the two runs also differ in what was destroyed) | operator | From 130e2b2d19402cd8693eeea8878f8632446f3950 Mon Sep 17 00:00:00 2001 From: Shane Kidd <33380501+StarshipSuperjam@users.noreply.github.com> Date: Sat, 15 Aug 2026 13:34:58 -0700 Subject: [PATCH 2/5] Feature: live difficulty AI level and normal flying formations (DIF-01, FORM-01) Wire the first behaviour into slice 6's empty schedule-dispatch seam, to the reference-faithful model the spec correction (prior commit) restored: - DIF-01: an `ai level` accumulates live from `raise_ai_level_and_set_formation` records (cabinet increment [2,0,6,16] at a project-defined DIP index 0 = +2), folding back below 0x80. Its own `difficulty_reset` receiver zeroes it on a world reset; it persists across a life. - FORM-01: the incoming wave's `formation count` + `formation type offset` are selected from the normal formation table baked as two parallel 160-lists (index -32..127). set-formation indexes by the record offset; raise by the folded AI level; reset zeroes. A two-sided guard skips an out-of-domain index (Scratch item-of-list returns "" out of range); a range fixture proves the guard is a dead defensive branch under this slice's raise/set dynamics. - A 4th parallel schedule column `schedule arg` carries the one runtime-readable scalar each dispatched record needs (Scratch can't parse the JSON payload). Verification: model fixtures over the committed data (baked-table golden, full lookup reproduction, the in-domain range proof, the fold-back math) in test_spec_docs; the extended round-trip golden covers the new column; the `area-scheduler` structural checks track the now-wired dispatch; a live scratch-vm harness scenario (difficulty-and-formations) with a biting negative; build_hash re-pinned; two builds byte-identical + round-trip. Records 019/020; catalog DIF-01/FORM-01 -> present; playtest step 4 gains the difficulty watchers. Co-Authored-By: Claude Opus 4.8 --- docs/MECHANICS_CATALOG.md | 4 +- docs/PLAYTEST_CHECKLIST.md | 10 +- docs/mechanics/019-difficulty-ai-level.md | 15 + .../mechanics/020-normal-flying-formations.md | 15 + harness/lib/catalog.js | 39 + src/xevious/project.json | 5481 ++++++++++++----- src/xevious/runtime_identifiers.json | 40 + tests/test_scratch_project.py | 119 +- tests/test_spec_docs.py | 121 +- tools/game_director.py | 275 +- 10 files changed, 4444 insertions(+), 1675 deletions(-) create mode 100644 docs/mechanics/019-difficulty-ai-level.md create mode 100644 docs/mechanics/020-normal-flying-formations.md diff --git a/docs/MECHANICS_CATALOG.md b/docs/MECHANICS_CATALOG.md index da911c0..17edfed 100644 --- a/docs/MECHANICS_CATALOG.md +++ b/docs/MECHANICS_CATALOG.md @@ -49,10 +49,10 @@ document differ, the spec document wins. | AREA-02 | Area object scheduler | partial | AREA-01, SYS-02 | sub: `sub_fn_2__handle_objects`, `obj_fn_tbl`, `area_object_tbl_tbl_normal` | Normal events spawn in recorded order and position. The ordered schedule consume, a lossless slice-6-ready representation of one fixture area (area 1) with a materialized sentinel, and the `schedule fired` observable are built ([016](mechanics/016-area-scheduler.md)); foundation-only — the per-record dispatch is an empty seam (handlers arrive slices 8+) and all 16 tables + the full trace are slice 6. | | AREA-03 | All 16 normal area tables | present | AREA-02 | sub: `area_1_obj_tbl_normal` through `area_16_obj_tbl_normal` | An accelerated trace consumes every normal table without unknown or Super objects. All 16 normal schedules are ingested into the flattened columns with per-area offsets and the accelerated 1–16→7 data trace passes ([017](mechanics/017-all-area-schedules.md)); the trace/round-trip prove the data, the built per-area consume rests on the offset golden + operator playtest. | | AREA-04 | Transitions and 16-to-7 loop | present | AREA-03 | main: `main_gameplay_loop`; sub: `sub_fn_3__handle_next_area` | Areas advance 1–16 then continue at 7, with no win screen. The advance/wrap shipped in AREA-01; with all 16 schedules ingested the loop is data-complete and the accelerated trace confirms 1–16→7 with no win screen ([018](mechanics/018-area-transitions-and-loop.md)) — a data trace, runtime traversal on the operator playtest. | -| DIF-01 | Difficulty setting | missing | AREA-02 | sub: `difficulty_tbl`, `sub_2_fn_3__inc_enemy_AI_and_flying_enemies` | Each normal setting starts at its recorded pressure. | +| DIF-01 | Difficulty setting | present | AREA-02 | sub: `difficulty_tbl`, `sub_2_fn_3__inc_enemy_AI_and_flying_enemies` | Each normal setting starts at its recorded pressure. The adaptive AI level accumulates live from the schedule's raise records and folds back below 0x80 ([019](mechanics/019-difficulty-ai-level.md)); foundation — the AI level is live/observable, its consumption as enemy pressure is slices 8+, and the cabinet DIP is a project-defined placeholder (increment +2). | | DIF-02 | Score-per-life adaptive AI | missing | DIF-01, ECO-01 | sub: `sub_2_fn_23__adjust_AI_level_based_on_score`, `avg_score_per_solvalou` | Fixtures show ordered AI changes from score per craft. | | DIF-03 | Per-family fire frequency | missing | DIF-01, SYS-04 | sub: `sub_2_fn_8__fire_freq_mask_derota` through `sub_2_fn_22__fire_freq_mask_andor_genesis` | Family fire fixtures follow recorded masks. | -| FORM-01 | Normal flying formations | missing | AREA-02, DIF-01 | sub: `flying_enemy_type_offset_tbl_normal`, `sub_2_fn_2__set_flying_enemies` | Fixtures preserve normal type, count, offsets, and order. | +| FORM-01 | Normal flying formations | present | AREA-02, DIF-01 | sub: `flying_enemy_type_offset_tbl_normal`, `sub_2_fn_2__set_flying_enemies` | Fixtures preserve normal type, count, offsets, and order. The wave size + type-table offset are selected live — set-formation by the record offset, raise by the folded AI level, reset zeroes ([020](mechanics/020-normal-flying-formations.md)); foundation — selection is live/observable, spawning the wave is slice 8. | ## Flying enemies and projectiles diff --git a/docs/PLAYTEST_CHECKLIST.md b/docs/PLAYTEST_CHECKLIST.md index f9427e2..a5af4fe 100644 --- a/docs/PLAYTEST_CHECKLIST.md +++ b/docs/PLAYTEST_CHECKLIST.md @@ -55,7 +55,15 @@ so area position is read from the `area progress`/`area number` variable watcher area runs its own schedule. (Some areas legitimately share a record count, so two areas showing the *same* peak is **not** itself a bug; the exact per-area correctness is guaranteed by the build-time round-trip test, not the eye.) The visual terrain is not yet driven by the clock, so these are - variable-watcher checks, not on-screen ones. + variable-watcher checks, not on-screen ones. **Also tick `ai level`, `formation count`, and + `formation type offset`** (DIF-01 / FORM-01): as you fly, `ai level` climbs a little each time a raise + record fires and stays below **128** (a raise folds it back — you should never see it reach 128), and + `formation count` / `formation type offset` change to a new wave (count in **1–6**) when a raise or a + set-formation record fires, and drop to 0 on a reset-formation. **Read the `ai level` growth *rate* as a + placeholder, not fidelity:** the cabinet difficulty is a project-chosen default (increment +2), so how + *fast* the level climbs is not meaningful yet — only that it climbs, folds, and drives a valid formation + is. No enemies spawn from the formation this slice, so this is a watcher check, not an on-screen one; the + exact table correctness is the build-time model fixture's, not the eye's. 5. **Repeated deaths and the near-end checkpoint.** Die several times in a row (today: press D; once killers exist, die to a bullet, an enemy, and a Bacura): the full death presentation and sound complete uncut, the craft respawns immediately vulnerable, and nothing from the previous life diff --git a/docs/mechanics/019-difficulty-ai-level.md b/docs/mechanics/019-difficulty-ai-level.md new file mode 100644 index 0000000..7aa515e --- /dev/null +++ b/docs/mechanics/019-difficulty-ai-level.md @@ -0,0 +1,15 @@ +# Difficulty AI level — the accumulating pressure the schedule raises + +- Mechanic: DIF-01 (partial, foundation) — one adaptive "AI level" accumulates live during play. The schedule's `raise_ai_level_and_set_formation` records add the cabinet difficulty increment to it and fold it back below 0x80, and re-select the incoming formation from the new level ([FORM-01](020-normal-flying-formations.md)). The AI level is durable per-game state: it persists across death and respawn and resets for a new game. +- Derived behavior: While an area scrolls, each raise record (one of the schedule's two most common kinds) adds the cabinet DIP-selected increment to the AI level; if that would take the level to 0x80 (128) or above, 0x40 (64) is subtracted first, so the level *saturates by folding back, not by clamping*. The four DIP settings add 2, 0, 6, or 16 respectively. The raised level then indexes the flying-formation table (the raise's re-select path). The AI level is the number every later enemy behaviour reads to scale its pressure; the accumulation and fold-back are this mechanic. +- Reference provenance: `jotd666/xevious@71473685a8c7856c8401c8519276cd97a38d4183`; `src/xevious_sub.68k`: `sub_2_fn_3__inc_enemy_AI_and_flying_enemies` (317–329) — the increment add, the `cmp #0x80` / `sub #0x40` fold-back, and the branch that re-selects the formation with the raised level as the index. The four increments are the committed, hash-pinned `difficulty_tbl` in [docs/spec/data/difficulty.json](../spec/data/difficulty.json) (`[2, 0, 6, 16]`, source lines 338–342); the behaviour is the settled [difficulty and formations](../spec/difficulty-and-formations.md) document. +- Transfer class: General behavior and numeric constant (instruction-derived rule and a derived numeric table; no source text or media copied). +- Scratch interpretation: The Stage owns `ai level`. The raise branch of the schedule consume (`_consume_schedule`) reads the increment from the baked `difficulty increment` list at the project's DIP index, adds it to `ai level` (through the centralized `op_*` helpers — never inline operator blocks), then, in a single `if`, subtracts 64 when the level exceeds 127 (the fold-back), and re-selects the formation using the new `ai level` as the table index (FORM-01). The cabinet DIP is a project-defined constant `DIFFICULTY_DIP_INDEX = 0` (increment +2) — a four-marker placeholder, since the spec records no arcade power-on default (like the RNG cold-start seed); index 0 is the lowest increment that still *progresses* (index 1 = +0 would make raises inert), and it is an independent switch from the starting-lives / bonus DIPs. A separate Stage `director reset` receiver (`difficulty_reset`) zeroes `ai level` on a world reset (cold-start / new-game) only, so it persists across a new life. +- Scratch evidence: the DIF-01 constants, the raise branch and `difficulty_reset` receiver, the `ai level` Stage variable, and the `difficulty increment` Stage list, all in `tools/game_director.py`. Model fixtures in `tests/test_spec_docs.py` (`DifficultyAndFormations`): `test_baked_tables_match_committed_data` (the baked increments equal `difficulty.json`) and `test_ai_level_fold_back` (the raise math + fold-back below 0x80). Dynamic check in the scratch-vm harness (`harness/lib/catalog.js` `difficulty-and-formations`): real play drives `ai level` above zero and confirms it never reaches 0x80, with a negative that breaks the raise dispatch so it never rises. The `difficulty_state` variable category and the write-forbid set in `tests/test_scratch_project.py` guard the new state. +- Acceptance criteria: The four difficulty-setting increments are `[2, 0, 6, 16]` and the build's baked list matches the committed file (engine, data-table fixture). The raise adds the increment and folds back once at 0x80 (engine, model fixture). In real play the AI level climbs as raise records fire and never reaches 0x80 (engine, scratch-vm harness). Operator: with the `ai level` watcher open, it climbs as the area scrolls and resets on a new game — an inspectable confirmation; the growth *rate* reflects the placeholder DIP and is not itself fidelity evidence. +- Fidelity status: DIF-01 is **partial** (foundation) — the AI-level accumulation and fold-back are built, live, and observable, and the rule is reference-faithful. What is deferred: the *consumption* of the AI level as enemy pressure (formation size feeds spawning, and per-family firing) arrives with the enemy slices (8+), and the score-adaptive re-tune (DIF-02, a later commit of this slice) is not yet wired — so this commit moves the AI level only by raises. +- License status: The pinned reference states no reusable license; only derived behavior and the committed, hash-pinned `difficulty.json` increments are used, cited to the settled spec and the data file, and no reference source text or media was reproduced. +- Known deviations or uncertainty: The DIP index (`0`, increment +2) is a **project-defined placeholder** with no arcade basis. Unlike the dormant RNG cold-start seed, it is **consumed live this slice** and directly scales the observable AI-level growth, so the growth *rate* an operator sees is placeholder-driven and is **not** a fidelity claim — only the growth *mechanism* is confirmed. The AI level moves only via raises this commit (the score re-tune lands with DIF-02); with raises alone the fold-back keeps it in `[0, 127]`, so the fold-back is exercised by the model fixture rather than the short live playtest. +- [x] No assembly or other source code was copied into the Scratch project. +- [x] No arcade ROM files were acquired, opened, extracted, or distributed. +- [x] Any transferred graphics or audio are recorded in `src/xevious/assets/provenance.json`. diff --git a/docs/mechanics/020-normal-flying-formations.md b/docs/mechanics/020-normal-flying-formations.md new file mode 100644 index 0000000..9122706 --- /dev/null +++ b/docs/mechanics/020-normal-flying-formations.md @@ -0,0 +1,15 @@ +# Normal flying formations — the wave size and type the schedule selects + +- Mechanic: FORM-01 (partial, foundation) — the incoming flying wave's size and its flying-enemy type-table offset are selected live from the normal formation table. A set-formation record indexes the table by its own signed offset; a raise record ([DIF-01](019-difficulty-ai-level.md)) re-selects using the folded AI level as the index; a reset-formation record zeroes the wave between formations. +- Derived behavior: The formation table yields two values per entry — the number of flying enemies in the incoming wave (observed range 1–6) and an offset into the flying-enemy type table that determines *which* types compose it. Two schedule record kinds pick the entry, by two different indices: a `set_flying_formation` record uses **its signed offset as the index** (the AI level is *not* added on this path), and a `raise_ai_level_and_set_formation` record uses **the raised, folded AI level as the index** (with no record offset). A `reset_flying_formation` record sets both values to zero, ending the pressure between waves. +- Reference provenance: `jotd666/xevious@71473685a8c7856c8401c8519276cd97a38d4183`; `src/xevious_sub.68k`: `sub_2_fn_2__set_flying_enemies` (300–311) — the signed record offset, sign-extended and doubled to address the two-byte entries, indexes the table with **no AI level added**; `sub_2_fn_3` (317–329) enters the same lookup with the AI level as the index; `sub_2_fn_5__reset_flying_enemies` (331–335) zeroes both. The table, decoded completely (including its 32 negative-index entries, index −32..127), is the committed, hash-pinned `flying_enemy_type_offset_tbl_normal` in [docs/spec/data/formations.json](../spec/data/formations.json); the behaviour is the settled [difficulty and formations](../spec/difficulty-and-formations.md) document, whose formation-index wording was corrected to match this reference in the same pull request. +- Transfer class: General behavior and structured table. +- Scratch interpretation: The formation table is baked into two parallel Stage lists — `formation count table` and `formation type offset table` — of 160 logical entries in index order −32..127 (the reference's byte "doubling" is already absorbed by decoding to logical entries, so no doubling is needed at runtime). The Stage owns `formation count` and `formation type offset` (the selected wave, which the slice-8 spawner will read) and the transient `formation index` working register. The shared `_select_formation` helper writes `formation index`, then — because Scratch `item N of list` returns the empty string for an out-of-range N, which would silently poison arithmetic — GUARDS both bounds: only when the index is in −32..127 does it set the two values from the table at slot `index − (−32) + 1`; an out-of-domain index leaves the prior formation unchanged (no faithful ROM-adjacent value exists to fabricate). The set / raise / reset branches of `_consume_schedule` call it with the record offset, the folded AI level, and a zeroing, respectively. +- Scratch evidence: `_select_formation` and the set/raise/reset branches of `_consume_schedule`, the `formation count table` / `formation type offset table` Stage lists, the `formation count` / `formation type offset` / `formation index` variables, and the new `schedule arg` schedule column (the runtime-readable set-formation offset), all in `tools/game_director.py`. Model fixtures in `tests/test_spec_docs.py` (`DifficultyAndFormations`): `test_baked_tables_match_committed_data`, `test_formation_lookup_reproduces_committed_table` (every entry across the domain), and `test_formation_index_in_domain_over_committed_schedules` (walking the real 1–16→7 schedules with the AI-level dynamics, proving every selection index stays in −32..127 so the guard is a proven-dead defensive branch this slice, and both selection paths are exercised). The extended round-trip golden (`test_all_area_schedules_round_trip_from_json`) re-derives the `schedule arg` column from source. Dynamic check in the scratch-vm harness (`difficulty-and-formations`): real play selects a live formation whose wave size stays in 1–6, with a negative that bites. +- Acceptance criteria: The baked count/type-offset lists equal a re-derivation from `formations.json` (engine, golden). The selection reproduces every committed entry across the −32..127 domain (engine, model fixture). Over the real committed schedules the selection index never leaves the table's domain (engine, range fixture). In real play a formation is selected whose recorded wave size is 1–6 (engine, scratch-vm harness). Operator: with the `formation count` / `formation type offset` watchers open, they change as set-formation and raise records fire and zero on a reset — an inspectable confirmation; no enemies spawn from the selection yet. +- Fidelity status: FORM-01 is **partial** (foundation) — the formation *selection* (both index paths, the reset, and the guarded table read) is built, live, and observable, and matches the reference. What is deferred: *spawning* the selected wave — the slice-8 flying-enemy vertical slice reads `formation count` / `formation type offset` (and the type table in [aerial enemies](../spec/aerial-enemies.md)) to place enemies — so no enemies appear from the formation this slice. +- License status: The pinned reference states no reusable license; only derived behavior and the committed, hash-pinned `formations.json` table are used, cited to the settled spec and the data file, and no reference source text or media was reproduced. +- Known deviations or uncertainty: The locked spec previously described the set-formation index as "that offset plus the current AI level"; the reference adds no AI level on that path (it is the offset alone), and the AI level is the index only for the raise path — the spec prose was corrected to match its own cited reference in this pull request, with no data change. The two-sided formation guard leaves the prior formation on an out-of-domain index rather than fabricating a value; the range fixture proves it is never reached under this slice's raise/set dynamics — the score-adaptive term (DIF-02, a later commit of this slice) is the only thing that could in principle drive the index out of domain, and will be recorded there. +- [x] No assembly or other source code was copied into the Scratch project. +- [x] No arcade ROM files were acquired, opened, extracted, or distributed. +- [x] Any transferred graphics or audio are recorded in `src/xevious/assets/provenance.json`. diff --git a/harness/lib/catalog.js b/harness/lib/catalog.js index 25ecde1..2ae5193 100644 --- a/harness/lib/catalog.js +++ b/harness/lib/catalog.js @@ -306,6 +306,45 @@ export const SCENARIOS = [ // in-window advances never happen → the advance assertions fail. negativeMutation: (p) => mutate.raiseGreaterThreshold(p, 'Stage', 13, 999), }, + { + key: 'difficulty-and-formations', + behavior: + 'The area schedule raises the AI level (folding back below 0x80) and selects a valid flying formation live', + playtestStep: 4, + async drive(vm) { + assert.ok(reachPlaying(vm), 'precondition: game reaches playing'); + // Live pacing (like area-clock-scheduler): as raise / set-formation records fire, `ai level` + // climbs and `formation count` takes a formation-table value. The AI level starts at 0 on a + // new game and must never reach 0x80 — a raise folds it back first. The EXACT (count, offset) + // table correspondence is the model fixture's job (test_spec_docs); this proves it runs live. + let aiRose = false; + let maxAi = 0; + let formationSelections = 0; + let countInRange = true; + for (let i = 0; i < 140; i += 1) { + step(vm, 1); + const ai = readVar(vm, 'difficulty-ai-level'); + const count = readVar(vm, 'formation-count'); + if (ai > 0) aiRose = true; + maxAi = Math.max(maxAi, ai); + if (count > 0) { + formationSelections += 1; + if (count < 1 || count > 6) countInRange = false; + } + } + return { aiRose, maxAi, formationSelections, countInRange }; + }, + assert(obs) { + assert.equal(obs.aiRose, true, 'the AI level climbs as raise records fire'); + assert.ok(obs.maxAi < 128, 'the AI level stays below 0x80 (a raise folds it back)'); + assert.ok(obs.formationSelections >= 1, 'a flying formation is selected live (count set)'); + assert.equal(obs.countInRange, true, 'the selected wave size stays in the recorded range 1..6'); + }, + // Break the raise dispatch (its handler == comparison never matches) so the AI level never + // rises → the aiRose assertion fails. + negativeMutation: (p) => + mutate.changeEqualsOperand(p, 'Stage', 'raise_ai_level_and_set_formation', '__never__'), + }, ]; // VM-cannot-observe behaviors that stay the operator playtest's job, named so "complete" diff --git a/src/xevious/project.json b/src/xevious/project.json index e07c343..0f2fab4 100644 --- a/src/xevious/project.json +++ b/src/xevious/project.json @@ -115,6 +115,22 @@ "area-schedule-fired": [ "schedule fired", 0 + ], + "difficulty-ai-level": [ + "ai level", + 0 + ], + "formation-count": [ + "formation count", + 0 + ], + "formation-type-offset": [ + "formation type offset", + 0 + ], + "formation-index": [ + "formation index", + 0 ] }, "lists": { @@ -2695,323 +2711,2179 @@ "" ] ], - "area-schedule-start": [ - "area schedule start", + "area-schedule-arg": [ + "schedule arg", [ + 0, + 15, + 255, + 18, + 31, + 7, + 31, + 31, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 31, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 3, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, 1, - 55, - 107, - 149, - 187, - 241, - 280, - 315, - 370, - 400, - 451, - 502, - 564, - 610, - 644, - 698 - ] - ], - "area-schedule-end": [ - "area schedule end", - [ - 54, - 106, - 148, - 186, - 240, - 279, - 314, - 369, - 399, - 450, - 501, - 563, - 609, - 643, - 697, - 764 - ] - ] - }, - "broadcasts": { - "broadcastMsgId-director-enter": "director enter", - "broadcastMsgId-director-stop": "director stop", - "broadcastMsgId-director-reset": "director reset", - "broadcastMsgId-ready-complete": "ready complete", - "broadcastMsgId-death-complete": "death complete", - "broadcastMsgId-game-over-complete": "game over complete", - "broadcastMsgId-craft-changed": "craft changed", - "broadcastMsgId-bomb-release": "bomb", - "broadcastMsgId-target-bounds-bottom": "target_b", - "broadcastMsgId-target-bounds-left": "target_l", - "broadcastMsgId-target-bounds-right": "target_r", - "broadcastMsgId-target-bounds-top": "target_t" - }, - "blocks": { - "gd-stage-001": { - "opcode": "procedures_definition", - "next": "gd-stage-020", - "parent": null, - "inputs": { - "custom_block": [ - 1, - "gd-stage-002" - ] - }, - "fields": {}, - "shadow": false, - "topLevel": true, - "x": 20, - "y": 20 - }, - "gd-stage-002": { - "opcode": "procedures_prototype", - "next": null, - "parent": "gd-stage-001", - "inputs": { - "director-destination": [ - 1, - "gd-stage-003" - ], - "director-scope": [ - 1, - "gd-stage-004" - ] - }, - "fields": {}, - "shadow": true, - "topLevel": false, - "mutation": { - "tagName": "mutation", - "children": [], - "proccode": "transition to %s reset %s", - "argumentids": "[\"director-destination\",\"director-scope\"]", - "argumentnames": "[\"destination\",\"scope\"]", - "argumentdefaults": "[\"\",\"none\"]", - "warp": "false" - } - }, - "gd-stage-003": { - "opcode": "argument_reporter_string_number", - "next": null, - "parent": "gd-stage-002", - "inputs": {}, - "fields": { - "VALUE": [ - "destination", - null - ] - }, - "shadow": true, - "topLevel": false - }, - "gd-stage-004": { - "opcode": "argument_reporter_string_number", - "next": null, - "parent": "gd-stage-002", - "inputs": {}, - "fields": { - "VALUE": [ - "scope", - null - ] - }, - "shadow": true, - "topLevel": false - }, - "gd-stage-005": { - "opcode": "data_changevariableby", - "next": "gd-stage-006", - "parent": "gd-stage-020", - "inputs": { - "VALUE": [ - 1, - [ - 4, - 1 - ] - ] - }, - "fields": { - "VARIABLE": [ - "state epoch", - "game-director-epoch" - ] - }, - "shadow": false, - "topLevel": false - }, - "gd-stage-006": { - "opcode": "data_setvariableto", - "next": "gd-stage-007", - "parent": "gd-stage-005", - "inputs": { - "VALUE": [ - 1, - [ - 10, - "resetting" - ] - ] - }, - "fields": { - "VARIABLE": [ - "game state", - "game-director-state" - ] - }, - "shadow": false, - "topLevel": false - }, - "gd-stage-007": { - "opcode": "event_broadcastandwait", - "next": "gd-stage-008", - "parent": "gd-stage-006", - "inputs": { - "BROADCAST_INPUT": [ - 1, - [ - 11, - "director stop", - "broadcastMsgId-director-stop" - ] - ] - }, - "fields": {}, - "shadow": false, - "topLevel": false - }, - "gd-stage-008": { - "opcode": "sound_stopallsounds", - "next": "gd-stage-009", - "parent": "gd-stage-007", - "inputs": {}, - "fields": {}, - "shadow": false, - "topLevel": false - }, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 24, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 20, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 3, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 69, + 47, + 0, + 0, + 69, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 7, + 15, + 15, + 28, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 15, + 15, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 255, + 0, + 0, + 0, + 0, + 15, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 63, + 0, + 0, + 0, + 0, + 0, + 0, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 255, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 31, + 0, + 0, + 0, + 0, + 0, + 56, + 0, + 0, + 0, + 0, + 0, + 111, + 0, + 0, + 0, + 0, + 15, + 0, + 69, + 0, + 0, + 101, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 63, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 15, + 15, + 3, + 3, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + -20, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + -26, + 0, + 0, + 109, + 0, + 0, + 0, + 15, + -15, + 0, + 0, + 52, + 0, + 73, + 0, + 62, + 0, + 0, + 0, + 0, + 70, + 0, + 0, + 0, + 102, + 0, + 33, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 63, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + -26, + 0, + 0, + 0, + 0, + 0, + 0, + 126, + 0, + 31, + 0 + ] + ], + "area-schedule-start": [ + "area schedule start", + [ + 1, + 55, + 107, + 149, + 187, + 241, + 280, + 315, + 370, + 400, + 451, + 502, + 564, + 610, + 644, + 698 + ] + ], + "area-schedule-end": [ + "area schedule end", + [ + 54, + 106, + 148, + 186, + 240, + 279, + 314, + 369, + 399, + 450, + 501, + 563, + 609, + 643, + 697, + 764 + ] + ], + "difficulty-increment": [ + "difficulty increment", + [ + 2, + 0, + 6, + 16 + ] + ], + "formation-count-table": [ + "formation count table", + [ + 4, + 5, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 4, + 4, + 5, + 6, + 6, + 6, + 6, + 2, + 3, + 4, + 2, + 3, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 3, + 3, + 3, + 4, + 4, + 4, + 5, + 5, + 5, + 2, + 2, + 2, + 4, + 4, + 4, + 4, + 4, + 4, + 5, + 5, + 6, + 6, + 3, + 3, + 4, + 4, + 5, + 5, + 3, + 3, + 4, + 4, + 5, + 5, + 3, + 3, + 4, + 4, + 5, + 5, + 3, + 3, + 4, + 4, + 5, + 5, + 3, + 3, + 3, + 3, + 4, + 4, + 3, + 3, + 4, + 4, + 5, + 5, + 4, + 4, + 4, + 4, + 5, + 5, + 5, + 5, + 6, + 6, + 2, + 3, + 3, + 4, + 4, + 5, + 5, + 5, + 6, + 6, + 2, + 3, + 3, + 4, + 4, + 5, + 5, + 5, + 6, + 6, + 4, + 4, + 5, + 5, + 6, + 6, + 5, + 5, + 6, + 6, + 2, + 3, + 3, + 4, + 4, + 5, + 6, + 6, + 6, + 6, + 6, + 6, + 2, + 3, + 3, + 4, + 4, + 5, + 6, + 6, + 6, + 6, + 1, + 2, + 6, + 6, + 6, + 6, + 1, + 2 + ] + ], + "formation-type-offset-table": [ + "formation type offset table", + [ + 11, + 10, + 9, + 37, + 92, + 41, + 94, + 100, + 102, + 114, + 48, + 49, + 48, + 48, + 63, + 72, + 75, + 84, + 84, + 84, + 88, + 88, + 88, + 88, + 88, + 88, + 88, + 88, + 88, + 88, + 88, + 88, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 25, + 25, + 25, + 1, + 1, + 4, + 4, + 5, + 5, + 5, + 5, + 5, + 5, + 25, + 25, + 25, + 25, + 25, + 25, + 39, + 39, + 39, + 39, + 39, + 39, + 31, + 31, + 31, + 31, + 31, + 31, + 19, + 19, + 19, + 19, + 19, + 19, + 54, + 54, + 55, + 55, + 55, + 55, + 45, + 45, + 45, + 45, + 45, + 45, + 18, + 18, + 17, + 17, + 17, + 17, + 23, + 23, + 23, + 23, + 60, + 60, + 60, + 60, + 60, + 60, + 25, + 25, + 25, + 25, + 69, + 69, + 69, + 69, + 69, + 69, + 45, + 45, + 45, + 45, + 39, + 39, + 39, + 39, + 39, + 39, + 13, + 13, + 13, + 13, + 109, + 108, + 108, + 108, + 108, + 108, + 13, + 13, + 7, + 7, + 7, + 7, + 78, + 78, + 78, + 78, + 78, + 78, + 7, + 7, + 7, + 7, + 84, + 84, + 7, + 7, + 7, + 7, + 88, + 88 + ] + ] + }, + "broadcasts": { + "broadcastMsgId-director-enter": "director enter", + "broadcastMsgId-director-stop": "director stop", + "broadcastMsgId-director-reset": "director reset", + "broadcastMsgId-ready-complete": "ready complete", + "broadcastMsgId-death-complete": "death complete", + "broadcastMsgId-game-over-complete": "game over complete", + "broadcastMsgId-craft-changed": "craft changed", + "broadcastMsgId-bomb-release": "bomb", + "broadcastMsgId-target-bounds-bottom": "target_b", + "broadcastMsgId-target-bounds-left": "target_l", + "broadcastMsgId-target-bounds-right": "target_r", + "broadcastMsgId-target-bounds-top": "target_t" + }, + "blocks": { + "gd-stage-001": { + "opcode": "procedures_definition", + "next": "gd-stage-020", + "parent": null, + "inputs": { + "custom_block": [ + 1, + "gd-stage-002" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": true, + "x": 20, + "y": 20 + }, + "gd-stage-002": { + "opcode": "procedures_prototype", + "next": null, + "parent": "gd-stage-001", + "inputs": { + "director-destination": [ + 1, + "gd-stage-003" + ], + "director-scope": [ + 1, + "gd-stage-004" + ] + }, + "fields": {}, + "shadow": true, + "topLevel": false, + "mutation": { + "tagName": "mutation", + "children": [], + "proccode": "transition to %s reset %s", + "argumentids": "[\"director-destination\",\"director-scope\"]", + "argumentnames": "[\"destination\",\"scope\"]", + "argumentdefaults": "[\"\",\"none\"]", + "warp": "false" + } + }, + "gd-stage-003": { + "opcode": "argument_reporter_string_number", + "next": null, + "parent": "gd-stage-002", + "inputs": {}, + "fields": { + "VALUE": [ + "destination", + null + ] + }, + "shadow": true, + "topLevel": false + }, + "gd-stage-004": { + "opcode": "argument_reporter_string_number", + "next": null, + "parent": "gd-stage-002", + "inputs": {}, + "fields": { + "VALUE": [ + "scope", + null + ] + }, + "shadow": true, + "topLevel": false + }, + "gd-stage-005": { + "opcode": "data_changevariableby", + "next": "gd-stage-006", + "parent": "gd-stage-020", + "inputs": { + "VALUE": [ + 1, + [ + 4, + 1 + ] + ] + }, + "fields": { + "VARIABLE": [ + "state epoch", + "game-director-epoch" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-006": { + "opcode": "data_setvariableto", + "next": "gd-stage-007", + "parent": "gd-stage-005", + "inputs": { + "VALUE": [ + 1, + [ + 10, + "resetting" + ] + ] + }, + "fields": { + "VARIABLE": [ + "game state", + "game-director-state" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-007": { + "opcode": "event_broadcastandwait", + "next": "gd-stage-008", + "parent": "gd-stage-006", + "inputs": { + "BROADCAST_INPUT": [ + 1, + [ + 11, + "director stop", + "broadcastMsgId-director-stop" + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-008": { + "opcode": "sound_stopallsounds", + "next": "gd-stage-009", + "parent": "gd-stage-007", + "inputs": {}, + "fields": {}, + "shadow": false, + "topLevel": false + }, "gd-stage-009": { "opcode": "data_setvariableto", - "next": "gd-stage-012", - "parent": "gd-stage-008", + "next": "gd-stage-012", + "parent": "gd-stage-008", + "inputs": { + "VALUE": [ + 3, + "gd-stage-010", + [ + 10, + "" + ] + ] + }, + "fields": { + "VARIABLE": [ + "reset scope", + "game-director-reset-scope" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-010": { + "opcode": "argument_reporter_string_number", + "next": null, + "parent": "gd-stage-009", + "inputs": {}, + "fields": { + "VALUE": [ + "scope", + null + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-011": { + "opcode": "data_setvariableto", + "next": null, + "parent": "gd-stage-012", + "inputs": { + "VALUE": [ + 1, + [ + 10, + "" + ] + ] + }, + "fields": { + "VARIABLE": [ + "death outcome", + "game-director-death-outcome" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-012": { + "opcode": "control_if", + "next": "gd-stage-016", + "parent": "gd-stage-009", + "inputs": { + "CONDITION": [ + 2, + "gd-stage-013" + ], + "SUBSTACK": [ + 2, + "gd-stage-011" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-013": { + "opcode": "operator_or", + "next": null, + "parent": "gd-stage-012", + "inputs": { + "OPERAND1": [ + 2, + "gd-stage-014" + ], + "OPERAND2": [ + 2, + "gd-stage-015" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-014": { + "opcode": "operator_equals", + "next": null, + "parent": "gd-stage-013", + "inputs": { + "OPERAND1": [ + 3, + [ + 12, + "reset scope", + "game-director-reset-scope" + ], + [ + 10, + "" + ] + ], + "OPERAND2": [ + 1, + [ + 10, + "cold-start" + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-015": { + "opcode": "operator_equals", + "next": null, + "parent": "gd-stage-013", + "inputs": { + "OPERAND1": [ + 3, + [ + 12, + "reset scope", + "game-director-reset-scope" + ], + [ + 10, + "" + ] + ], + "OPERAND2": [ + 1, + [ + 10, + "cold-start" + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-016": { + "opcode": "event_broadcastandwait", + "next": "gd-stage-017", + "parent": "gd-stage-012", + "inputs": { + "BROADCAST_INPUT": [ + 1, + [ + 11, + "director reset", + "broadcastMsgId-director-reset" + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-017": { + "opcode": "data_setvariableto", + "next": "gd-stage-019", + "parent": "gd-stage-016", + "inputs": { + "VALUE": [ + 3, + "gd-stage-018", + [ + 10, + "" + ] + ] + }, + "fields": { + "VARIABLE": [ + "game state", + "game-director-state" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-018": { + "opcode": "argument_reporter_string_number", + "next": null, + "parent": "gd-stage-017", + "inputs": {}, + "fields": { + "VALUE": [ + "destination", + null + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-019": { + "opcode": "event_broadcast", + "next": null, + "parent": "gd-stage-017", + "inputs": { + "BROADCAST_INPUT": [ + 1, + [ + 11, + "director enter", + "broadcastMsgId-director-enter" + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-020": { + "opcode": "control_if", + "next": null, + "parent": "gd-stage-001", + "inputs": { + "CONDITION": [ + 2, + "gd-stage-021" + ], + "SUBSTACK": [ + 2, + "gd-stage-005" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-021": { + "opcode": "data_listcontainsitem", + "next": null, + "parent": "gd-stage-020", + "inputs": { + "ITEM": [ + 3, + "gd-stage-022", + [ + 10, + "" + ] + ] + }, + "fields": { + "LIST": [ + "allowed transitions", + "game-director-allowed-transitions" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-022": { + "opcode": "operator_join", + "next": null, + "parent": "gd-stage-021", + "inputs": { + "STRING1": [ + 3, + "gd-stage-023", + [ + 10, + "" + ] + ], + "STRING2": [ + 3, + "gd-stage-024", + [ + 10, + "" + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-023": { + "opcode": "operator_join", + "next": null, + "parent": "gd-stage-022", + "inputs": { + "STRING1": [ + 3, + [ + 12, + "game state", + "game-director-state" + ], + [ + 10, + "" + ] + ], + "STRING2": [ + 1, + [ + 10, + " -> " + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-024": { + "opcode": "argument_reporter_string_number", + "next": null, + "parent": "gd-stage-022", + "inputs": {}, + "fields": { + "VALUE": [ + "destination", + null + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-025": { + "opcode": "procedures_definition", + "next": "gd-stage-029", + "parent": null, + "inputs": { + "custom_block": [ + 1, + "gd-stage-026" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": true, + "x": 20, + "y": 170 + }, + "gd-stage-026": { + "opcode": "procedures_prototype", + "next": null, + "parent": "gd-stage-025", + "inputs": {}, + "fields": {}, + "shadow": true, + "topLevel": false, + "mutation": { + "tagName": "mutation", + "children": [], + "proccode": "rng step", + "argumentids": "[]", + "argumentnames": "[]", + "argumentdefaults": "[]", + "warp": "true" + } + }, + "gd-stage-027": { + "opcode": "operator_divide", + "next": null, + "parent": "gd-stage-028", + "inputs": { + "NUM1": [ + 3, + [ + 12, + "rng state", + "rng-state" + ], + [ + 10, + "" + ] + ], + "NUM2": [ + 1, + [ + 4, + 256 + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-028": { + "opcode": "operator_mathop", + "next": null, + "parent": "gd-stage-029", + "inputs": { + "NUM": [ + 2, + "gd-stage-027" + ] + }, + "fields": { + "OPERATOR": [ + "floor", + null + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-029": { + "opcode": "data_setvariableto", + "next": "gd-stage-034", + "parent": "gd-stage-025", "inputs": { "VALUE": [ 3, - "gd-stage-010", + "gd-stage-028", + [ + 10, + "" + ] + ] + }, + "fields": { + "VARIABLE": [ + "rng high", + "rng-high" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-030": { + "opcode": "operator_mod", + "next": null, + "parent": "gd-stage-031", + "inputs": { + "NUM1": [ + 3, + [ + 12, + "rng state", + "rng-state" + ], + [ + 10, + "" + ] + ], + "NUM2": [ + 1, + [ + 4, + 256 + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-031": { + "opcode": "operator_multiply", + "next": null, + "parent": "gd-stage-032", + "inputs": { + "NUM1": [ + 1, + [ + 4, + 5 + ] + ], + "NUM2": [ + 2, + "gd-stage-030" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-032": { + "opcode": "operator_add", + "next": null, + "parent": "gd-stage-033", + "inputs": { + "NUM1": [ + 2, + "gd-stage-031" + ], + "NUM2": [ + 1, + [ + 4, + 1 + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-033": { + "opcode": "operator_mod", + "next": null, + "parent": "gd-stage-034", + "inputs": { + "NUM1": [ + 2, + "gd-stage-032" + ], + "NUM2": [ + 1, + [ + 4, + 256 + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-034": { + "opcode": "data_setvariableto", + "next": "gd-stage-035", + "parent": "gd-stage-029", + "inputs": { + "VALUE": [ + 3, + "gd-stage-033", + [ + 10, + "" + ] + ] + }, + "fields": { + "VARIABLE": [ + "rng new low", + "rng-new-low" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-035": { + "opcode": "data_setvariableto", + "next": "gd-stage-038", + "parent": "gd-stage-034", + "inputs": { + "VALUE": [ + 1, + [ + 4, + 0 + ] + ] + }, + "fields": { + "VARIABLE": [ + "rng extend", + "rng-extend-flag" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-036": { + "opcode": "operator_equals", + "next": null, + "parent": "gd-stage-038", + "inputs": { + "OPERAND1": [ + 3, + [ + 12, + "rng new low", + "rng-new-low" + ], + [ + 10, + "" + ] + ], + "OPERAND2": [ + 1, + [ + 4, + 0 + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-037": { + "opcode": "data_setvariableto", + "next": null, + "parent": "gd-stage-038", + "inputs": { + "VALUE": [ + 1, + [ + 4, + 1 + ] + ] + }, + "fields": { + "VARIABLE": [ + "rng extend", + "rng-extend-flag" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-038": { + "opcode": "control_if", + "next": "gd-stage-047", + "parent": "gd-stage-035", + "inputs": { + "CONDITION": [ + 2, + "gd-stage-036" + ], + "SUBSTACK": [ + 2, + "gd-stage-037" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-039": { + "opcode": "operator_divide", + "next": null, + "parent": "gd-stage-040", + "inputs": { + "NUM1": [ + 3, + [ + 12, + "rng high", + "rng-high" + ], [ 10, "" ] + ], + "NUM2": [ + 1, + [ + 4, + 128 + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-040": { + "opcode": "operator_mathop", + "next": null, + "parent": "gd-stage-041", + "inputs": { + "NUM": [ + 2, + "gd-stage-039" ] }, "fields": { - "VARIABLE": [ - "reset scope", - "game-director-reset-scope" + "OPERATOR": [ + "floor", + null ] }, "shadow": false, "topLevel": false }, - "gd-stage-010": { - "opcode": "argument_reporter_string_number", + "gd-stage-041": { + "opcode": "operator_mod", "next": null, - "parent": "gd-stage-009", - "inputs": {}, - "fields": { - "VALUE": [ - "scope", - null + "parent": "gd-stage-045", + "inputs": { + "NUM1": [ + 2, + "gd-stage-040" + ], + "NUM2": [ + 1, + [ + 4, + 2 + ] ] }, + "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-011": { - "opcode": "data_setvariableto", + "gd-stage-042": { + "opcode": "operator_divide", "next": null, - "parent": "gd-stage-012", + "parent": "gd-stage-043", "inputs": { - "VALUE": [ - 1, + "NUM1": [ + 3, + [ + 12, + "rng high", + "rng-high" + ], [ 10, "" ] + ], + "NUM2": [ + 1, + [ + 4, + 4 + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-043": { + "opcode": "operator_mathop", + "next": null, + "parent": "gd-stage-044", + "inputs": { + "NUM": [ + 2, + "gd-stage-042" ] }, "fields": { - "VARIABLE": [ - "death outcome", - "game-director-death-outcome" + "OPERATOR": [ + "floor", + null ] }, "shadow": false, "topLevel": false }, - "gd-stage-012": { - "opcode": "control_if", - "next": "gd-stage-016", - "parent": "gd-stage-009", + "gd-stage-044": { + "opcode": "operator_mod", + "next": null, + "parent": "gd-stage-045", "inputs": { - "CONDITION": [ + "NUM1": [ 2, - "gd-stage-013" + "gd-stage-043" ], - "SUBSTACK": [ - 2, - "gd-stage-011" + "NUM2": [ + 1, + [ + 4, + 2 + ] ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-013": { - "opcode": "operator_or", + "gd-stage-045": { + "opcode": "operator_equals", "next": null, - "parent": "gd-stage-012", + "parent": "gd-stage-047", "inputs": { "OPERAND1": [ 2, - "gd-stage-014" + "gd-stage-041" ], "OPERAND2": [ 2, - "gd-stage-015" + "gd-stage-044" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-014": { - "opcode": "operator_equals", + "gd-stage-046": { + "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-013", + "parent": "gd-stage-047", "inputs": { - "OPERAND1": [ + "VALUE": [ + 1, + [ + 4, + 1 + ] + ] + }, + "fields": { + "VARIABLE": [ + "rng extend", + "rng-extend-flag" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-047": { + "opcode": "control_if", + "next": "gd-stage-051", + "parent": "gd-stage-038", + "inputs": { + "CONDITION": [ + 2, + "gd-stage-045" + ], + "SUBSTACK": [ + 2, + "gd-stage-046" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-048": { + "opcode": "operator_multiply", + "next": null, + "parent": "gd-stage-049", + "inputs": { + "NUM1": [ 3, [ 12, - "reset scope", - "game-director-reset-scope" + "rng high", + "rng-high" ], [ 10, "" ] ], - "OPERAND2": [ + "NUM2": [ 1, [ - 10, - "cold-start" + 4, + 2 ] ] }, @@ -3019,46 +4891,46 @@ "shadow": false, "topLevel": false }, - "gd-stage-015": { - "opcode": "operator_equals", + "gd-stage-049": { + "opcode": "operator_add", "next": null, - "parent": "gd-stage-013", + "parent": "gd-stage-050", "inputs": { - "OPERAND1": [ + "NUM1": [ + 2, + "gd-stage-048" + ], + "NUM2": [ 3, [ 12, - "reset scope", - "game-director-reset-scope" + "rng extend", + "rng-extend-flag" ], [ 10, "" ] - ], - "OPERAND2": [ - 1, - [ - 10, - "cold-start" - ] ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-016": { - "opcode": "event_broadcastandwait", - "next": "gd-stage-017", - "parent": "gd-stage-012", + "gd-stage-050": { + "opcode": "operator_mod", + "next": null, + "parent": "gd-stage-051", "inputs": { - "BROADCAST_INPUT": [ + "NUM1": [ + 2, + "gd-stage-049" + ], + "NUM2": [ 1, [ - 11, - "director reset", - "broadcastMsgId-director-reset" + 4, + 256 ] ] }, @@ -3066,14 +4938,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-017": { + "gd-stage-051": { "opcode": "data_setvariableto", - "next": "gd-stage-019", - "parent": "gd-stage-016", + "next": "gd-stage-054", + "parent": "gd-stage-047", "inputs": { "VALUE": [ 3, - "gd-stage-018", + "gd-stage-050", [ 10, "" @@ -3082,38 +4954,40 @@ }, "fields": { "VARIABLE": [ - "game state", - "game-director-state" - ] - }, - "shadow": false, - "topLevel": false - }, - "gd-stage-018": { - "opcode": "argument_reporter_string_number", - "next": null, - "parent": "gd-stage-017", - "inputs": {}, - "fields": { - "VALUE": [ - "destination", - null + "rng new high", + "rng-new-high" ] }, "shadow": false, "topLevel": false }, - "gd-stage-019": { - "opcode": "event_broadcast", + "gd-stage-052": { + "opcode": "operator_add", "next": null, - "parent": "gd-stage-017", + "parent": "gd-stage-053", "inputs": { - "BROADCAST_INPUT": [ - 1, + "NUM1": [ + 3, + [ + 12, + "rng new low", + "rng-new-low" + ], + [ + 10, + "" + ] + ], + "NUM2": [ + 3, + [ + 12, + "rng new high", + "rng-new-high" + ], [ - 11, - "director enter", - "broadcastMsgId-director-enter" + 10, + "" ] ] }, @@ -3121,32 +4995,35 @@ "shadow": false, "topLevel": false }, - "gd-stage-020": { - "opcode": "control_if", + "gd-stage-053": { + "opcode": "operator_mod", "next": null, - "parent": "gd-stage-001", + "parent": "gd-stage-054", "inputs": { - "CONDITION": [ + "NUM1": [ 2, - "gd-stage-021" + "gd-stage-052" ], - "SUBSTACK": [ - 2, - "gd-stage-005" + "NUM2": [ + 1, + [ + 4, + 256 + ] ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-021": { - "opcode": "data_listcontainsitem", - "next": null, - "parent": "gd-stage-020", + "gd-stage-054": { + "opcode": "data_setvariableto", + "next": "gd-stage-057", + "parent": "gd-stage-051", "inputs": { - "ITEM": [ + "VALUE": [ 3, - "gd-stage-022", + "gd-stage-053", [ 10, "" @@ -3154,33 +5031,36 @@ ] }, "fields": { - "LIST": [ - "allowed transitions", - "game-director-allowed-transitions" + "VARIABLE": [ + "rng out", + "rng-out" ] }, "shadow": false, "topLevel": false }, - "gd-stage-022": { - "opcode": "operator_join", + "gd-stage-055": { + "opcode": "operator_multiply", "next": null, - "parent": "gd-stage-021", + "parent": "gd-stage-056", "inputs": { - "STRING1": [ + "NUM1": [ 3, - "gd-stage-023", + [ + 12, + "rng new high", + "rng-new-high" + ], [ 10, "" ] ], - "STRING2": [ - 3, - "gd-stage-024", + "NUM2": [ + 1, [ - 10, - "" + 4, + 256 ] ] }, @@ -3188,69 +5068,75 @@ "shadow": false, "topLevel": false }, - "gd-stage-023": { - "opcode": "operator_join", + "gd-stage-056": { + "opcode": "operator_add", "next": null, - "parent": "gd-stage-022", + "parent": "gd-stage-057", "inputs": { - "STRING1": [ + "NUM1": [ + 2, + "gd-stage-055" + ], + "NUM2": [ 3, [ 12, - "game state", - "game-director-state" + "rng new low", + "rng-new-low" ], [ 10, "" ] - ], - "STRING2": [ - 1, - [ - 10, - " -> " - ] ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-024": { - "opcode": "argument_reporter_string_number", + "gd-stage-057": { + "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-022", - "inputs": {}, - "fields": { + "parent": "gd-stage-054", + "inputs": { "VALUE": [ - "destination", - null + 3, + "gd-stage-056", + [ + 10, + "" + ] + ] + }, + "fields": { + "VARIABLE": [ + "rng state", + "rng-state" ] }, "shadow": false, "topLevel": false }, - "gd-stage-025": { + "gd-stage-058": { "opcode": "procedures_definition", - "next": "gd-stage-029", + "next": "gd-stage-060", "parent": null, "inputs": { "custom_block": [ 1, - "gd-stage-026" + "gd-stage-059" ] }, "fields": {}, "shadow": false, "topLevel": true, "x": 20, - "y": 170 + "y": 320 }, - "gd-stage-026": { + "gd-stage-059": { "opcode": "procedures_prototype", "next": null, - "parent": "gd-stage-025", + "parent": "gd-stage-058", "inputs": {}, "fields": {}, "shadow": true, @@ -3258,144 +5144,130 @@ "mutation": { "tagName": "mutation", "children": [], - "proccode": "rng step", + "proccode": "clear slots", "argumentids": "[]", "argumentnames": "[]", "argumentdefaults": "[]", "warp": "true" } }, - "gd-stage-027": { - "opcode": "operator_divide", - "next": null, - "parent": "gd-stage-028", + "gd-stage-060": { + "opcode": "data_setvariableto", + "next": "gd-stage-061", + "parent": "gd-stage-058", "inputs": { - "NUM1": [ - 3, - [ - 12, - "rng state", - "rng-state" - ], - [ - 10, - "" - ] - ], - "NUM2": [ + "VALUE": [ 1, [ 4, - 256 + 1 ] ] }, - "fields": {}, + "fields": { + "VARIABLE": [ + "slot index", + "slot-index" + ] + }, "shadow": false, "topLevel": false }, - "gd-stage-028": { - "opcode": "operator_mathop", + "gd-stage-061": { + "opcode": "control_repeat", "next": null, - "parent": "gd-stage-029", + "parent": "gd-stage-060", "inputs": { - "NUM": [ + "TIMES": [ + 1, + [ + 4, + 64 + ] + ], + "SUBSTACK": [ 2, - "gd-stage-027" - ] - }, - "fields": { - "OPERATOR": [ - "floor", - null + "gd-stage-062" ] }, + "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-029": { - "opcode": "data_setvariableto", - "next": "gd-stage-034", - "parent": "gd-stage-025", + "gd-stage-062": { + "opcode": "data_replaceitemoflist", + "next": "gd-stage-063", + "parent": "gd-stage-061", "inputs": { - "VALUE": [ + "INDEX": [ 3, - "gd-stage-028", + [ + 12, + "slot index", + "slot-index" + ], [ 10, "" ] + ], + "ITEM": [ + 1, + [ + 4, + 0 + ] ] }, "fields": { - "VARIABLE": [ - "rng high", - "rng-high" + "LIST": [ + "slot type", + "slot-type" ] }, "shadow": false, "topLevel": false }, - "gd-stage-030": { - "opcode": "operator_mod", - "next": null, - "parent": "gd-stage-031", + "gd-stage-063": { + "opcode": "data_replaceitemoflist", + "next": "gd-stage-064", + "parent": "gd-stage-062", "inputs": { - "NUM1": [ + "INDEX": [ 3, [ 12, - "rng state", - "rng-state" + "slot index", + "slot-index" ], [ 10, "" ] ], - "NUM2": [ + "ITEM": [ 1, [ 4, - 256 + 0 ] ] }, - "fields": {}, - "shadow": false, - "topLevel": false - }, - "gd-stage-031": { - "opcode": "operator_multiply", - "next": null, - "parent": "gd-stage-032", - "inputs": { - "NUM1": [ - 1, - [ - 4, - 5 - ] - ], - "NUM2": [ - 2, - "gd-stage-030" + "fields": { + "LIST": [ + "slot state", + "slot-state" ] }, - "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-032": { - "opcode": "operator_add", + "gd-stage-064": { + "opcode": "data_changevariableby", "next": null, - "parent": "gd-stage-033", + "parent": "gd-stage-063", "inputs": { - "NUM1": [ - 2, - "gd-stage-031" - ], - "NUM2": [ + "VALUE": [ 1, [ 4, @@ -3403,92 +5275,149 @@ ] ] }, - "fields": {}, + "fields": { + "VARIABLE": [ + "slot index", + "slot-index" + ] + }, "shadow": false, "topLevel": false }, - "gd-stage-033": { - "opcode": "operator_mod", - "next": null, - "parent": "gd-stage-034", + "gd-stage-065": { + "opcode": "procedures_definition", + "next": "gd-stage-067", + "parent": null, "inputs": { - "NUM1": [ - 2, - "gd-stage-032" - ], - "NUM2": [ + "custom_block": [ 1, - [ - 4, - 256 - ] + "gd-stage-066" ] }, "fields": {}, "shadow": false, - "topLevel": false + "topLevel": true, + "x": 20, + "y": 470 }, - "gd-stage-034": { - "opcode": "data_setvariableto", - "next": "gd-stage-035", - "parent": "gd-stage-029", + "gd-stage-066": { + "opcode": "procedures_prototype", + "next": null, + "parent": "gd-stage-065", + "inputs": {}, + "fields": {}, + "shadow": true, + "topLevel": false, + "mutation": { + "tagName": "mutation", + "children": [], + "proccode": "advance slots", + "argumentids": "[]", + "argumentnames": "[]", + "argumentdefaults": "[]", + "warp": "true" + } + }, + "gd-stage-067": { + "opcode": "data_changevariableby", + "next": "gd-stage-068", + "parent": "gd-stage-065", "inputs": { "VALUE": [ - 3, - "gd-stage-033", + 1, [ - 10, - "" + 4, + 1 ] ] }, "fields": { "VARIABLE": [ - "rng new low", - "rng-new-low" + "tick", + "tick" ] }, "shadow": false, "topLevel": false }, - "gd-stage-035": { + "gd-stage-068": { "opcode": "data_setvariableto", - "next": "gd-stage-038", - "parent": "gd-stage-034", + "next": "gd-stage-069", + "parent": "gd-stage-067", "inputs": { "VALUE": [ 1, [ 4, - 0 + 1 ] ] }, "fields": { "VARIABLE": [ - "rng extend", - "rng-extend-flag" + "slot index", + "slot-index" ] }, "shadow": false, "topLevel": false }, - "gd-stage-036": { - "opcode": "operator_equals", + "gd-stage-069": { + "opcode": "control_repeat", "next": null, - "parent": "gd-stage-038", + "parent": "gd-stage-068", "inputs": { - "OPERAND1": [ + "TIMES": [ + 1, + [ + 4, + 64 + ] + ], + "SUBSTACK": [ + 2, + "gd-stage-073" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-070": { + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-071", + "inputs": { + "INDEX": [ 3, [ 12, - "rng new low", - "rng-new-low" + "slot index", + "slot-index" ], [ 10, "" ] + ] + }, + "fields": { + "LIST": [ + "slot type", + "slot-type" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-071": { + "opcode": "operator_equals", + "next": null, + "parent": "gd-stage-072", + "inputs": { + "OPERAND1": [ + 2, + "gd-stage-070" ], "OPERAND2": [ 1, @@ -3502,177 +5431,176 @@ "shadow": false, "topLevel": false }, - "gd-stage-037": { - "opcode": "data_setvariableto", + "gd-stage-072": { + "opcode": "operator_not", "next": null, - "parent": "gd-stage-038", + "parent": "gd-stage-073", "inputs": { - "VALUE": [ - 1, - [ - 4, - 1 - ] - ] - }, - "fields": { - "VARIABLE": [ - "rng extend", - "rng-extend-flag" + "OPERAND": [ + 2, + "gd-stage-071" ] }, + "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-038": { + "gd-stage-073": { "opcode": "control_if", - "next": "gd-stage-047", - "parent": "gd-stage-035", + "next": "gd-stage-074", + "parent": "gd-stage-069", "inputs": { "CONDITION": [ 2, - "gd-stage-036" - ], - "SUBSTACK": [ - 2, - "gd-stage-037" + "gd-stage-072" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-039": { - "opcode": "operator_divide", + "gd-stage-074": { + "opcode": "data_changevariableby", "next": null, - "parent": "gd-stage-040", + "parent": "gd-stage-073", "inputs": { - "NUM1": [ - 3, - [ - 12, - "rng high", - "rng-high" - ], - [ - 10, - "" - ] - ], - "NUM2": [ + "VALUE": [ 1, [ 4, - 128 + 1 ] ] }, - "fields": {}, + "fields": { + "VARIABLE": [ + "slot index", + "slot-index" + ] + }, "shadow": false, "topLevel": false }, - "gd-stage-040": { - "opcode": "operator_mathop", - "next": null, - "parent": "gd-stage-041", + "gd-stage-075": { + "opcode": "procedures_definition", + "next": "gd-stage-077", + "parent": null, "inputs": { - "NUM": [ - 2, - "gd-stage-039" - ] - }, - "fields": { - "OPERATOR": [ - "floor", - null + "custom_block": [ + 1, + "gd-stage-076" ] }, + "fields": {}, "shadow": false, - "topLevel": false + "topLevel": true, + "x": 20, + "y": 620 }, - "gd-stage-041": { - "opcode": "operator_mod", + "gd-stage-076": { + "opcode": "procedures_prototype", "next": null, - "parent": "gd-stage-045", - "inputs": { - "NUM1": [ - 2, - "gd-stage-040" - ], - "NUM2": [ + "parent": "gd-stage-075", + "inputs": {}, + "fields": {}, + "shadow": true, + "topLevel": false, + "mutation": { + "tagName": "mutation", + "children": [], + "proccode": "advance area", + "argumentids": "[]", + "argumentnames": "[]", + "argumentdefaults": "[]", + "warp": "true" + } + }, + "gd-stage-077": { + "opcode": "data_changevariableby", + "next": "gd-stage-082", + "parent": "gd-stage-075", + "inputs": { + "VALUE": [ 1, [ 4, - 2 + 32 ] ] }, - "fields": {}, + "fields": { + "VARIABLE": [ + "area progress", + "area-progress" + ] + }, "shadow": false, "topLevel": false }, - "gd-stage-042": { - "opcode": "operator_divide", + "gd-stage-078": { + "opcode": "operator_subtract", "next": null, - "parent": "gd-stage-043", + "parent": "gd-stage-079", "inputs": { "NUM1": [ + 1, + [ + 4, + 3328 + ] + ], + "NUM2": [ 3, [ 12, - "rng high", - "rng-high" + "area progress", + "area-progress" ], [ 10, "" ] - ], - "NUM2": [ - 1, - [ - 4, - 4 - ] ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-043": { - "opcode": "operator_mathop", + "gd-stage-079": { + "opcode": "operator_mod", "next": null, - "parent": "gd-stage-044", + "parent": "gd-stage-080", "inputs": { - "NUM": [ + "NUM1": [ 2, - "gd-stage-042" - ] - }, - "fields": { - "OPERATOR": [ - "floor", - null + "gd-stage-078" + ], + "NUM2": [ + 1, + [ + 4, + 65536 + ] ] }, + "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-044": { - "opcode": "operator_mod", + "gd-stage-080": { + "opcode": "operator_divide", "next": null, - "parent": "gd-stage-045", + "parent": "gd-stage-081", "inputs": { "NUM1": [ 2, - "gd-stage-043" + "gd-stage-079" ], "NUM2": [ 1, [ 4, - 2 + 256 ] ] }, @@ -3680,86 +5608,92 @@ "shadow": false, "topLevel": false }, - "gd-stage-045": { - "opcode": "operator_equals", + "gd-stage-081": { + "opcode": "operator_mathop", "next": null, - "parent": "gd-stage-047", + "parent": "gd-stage-082", "inputs": { - "OPERAND1": [ - 2, - "gd-stage-041" - ], - "OPERAND2": [ + "NUM": [ 2, - "gd-stage-044" + "gd-stage-080" + ] + }, + "fields": { + "OPERATOR": [ + "floor", + null ] }, - "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-046": { + "gd-stage-082": { "opcode": "data_setvariableto", - "next": null, - "parent": "gd-stage-047", + "next": "gd-stage-083", + "parent": "gd-stage-077", "inputs": { "VALUE": [ - 1, + 3, + "gd-stage-081", [ - 4, - 1 + 10, + "" ] ] }, "fields": { "VARIABLE": [ - "rng extend", - "rng-extend-flag" + "scroll row", + "area-scroll-row" ] }, "shadow": false, "topLevel": false }, - "gd-stage-047": { - "opcode": "control_if", - "next": "gd-stage-051", - "parent": "gd-stage-038", + "gd-stage-083": { + "opcode": "control_if_else", + "next": null, + "parent": "gd-stage-082", "inputs": { "CONDITION": [ 2, - "gd-stage-045" + "gd-stage-084" ], "SUBSTACK": [ 2, - "gd-stage-046" + "gd-stage-085" + ], + "SUBSTACK2": [ + 2, + "gd-stage-096" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-048": { - "opcode": "operator_multiply", + "gd-stage-084": { + "opcode": "operator_equals", "next": null, - "parent": "gd-stage-049", + "parent": "gd-stage-083", "inputs": { - "NUM1": [ + "OPERAND1": [ 3, [ 12, - "rng high", - "rng-high" + "scroll row", + "area-scroll-row" ], [ 10, "" ] ], - "NUM2": [ + "OPERAND2": [ 1, [ 4, - 2 + 14 ] ] }, @@ -3767,46 +5701,50 @@ "shadow": false, "topLevel": false }, - "gd-stage-049": { - "opcode": "operator_add", - "next": null, - "parent": "gd-stage-050", + "gd-stage-085": { + "opcode": "control_if_else", + "next": "gd-stage-089", + "parent": "gd-stage-083", "inputs": { - "NUM1": [ + "CONDITION": [ 2, - "gd-stage-048" + "gd-stage-086" ], - "NUM2": [ - 3, - [ - 12, - "rng extend", - "rng-extend-flag" - ], - [ - 10, - "" - ] + "SUBSTACK": [ + 2, + "gd-stage-087" + ], + "SUBSTACK2": [ + 2, + "gd-stage-088" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-050": { - "opcode": "operator_mod", + "gd-stage-086": { + "opcode": "operator_equals", "next": null, - "parent": "gd-stage-051", + "parent": "gd-stage-085", "inputs": { - "NUM1": [ - 2, - "gd-stage-049" + "OPERAND1": [ + 3, + [ + 12, + "area number", + "area-number" + ], + [ + 10, + "" + ] ], - "NUM2": [ + "OPERAND2": [ 1, [ 4, - 256 + 16 ] ] }, @@ -3814,151 +5752,155 @@ "shadow": false, "topLevel": false }, - "gd-stage-051": { + "gd-stage-087": { "opcode": "data_setvariableto", - "next": "gd-stage-054", - "parent": "gd-stage-047", + "next": null, + "parent": "gd-stage-085", "inputs": { "VALUE": [ - 3, - "gd-stage-050", + 1, [ - 10, - "" + 4, + 7 ] ] }, "fields": { "VARIABLE": [ - "rng new high", - "rng-new-high" + "area number", + "area-number" ] }, "shadow": false, "topLevel": false }, - "gd-stage-052": { - "opcode": "operator_add", + "gd-stage-088": { + "opcode": "data_changevariableby", "next": null, - "parent": "gd-stage-053", + "parent": "gd-stage-085", "inputs": { - "NUM1": [ - 3, - [ - 12, - "rng new low", - "rng-new-low" - ], - [ - 10, - "" - ] - ], - "NUM2": [ - 3, - [ - 12, - "rng new high", - "rng-new-high" - ], + "VALUE": [ + 1, [ - 10, - "" + 4, + 1 ] ] }, - "fields": {}, + "fields": { + "VARIABLE": [ + "area number", + "area-number" + ] + }, "shadow": false, "topLevel": false }, - "gd-stage-053": { - "opcode": "operator_mod", - "next": null, - "parent": "gd-stage-054", + "gd-stage-089": { + "opcode": "data_setvariableto", + "next": "gd-stage-090", + "parent": "gd-stage-085", "inputs": { - "NUM1": [ - 2, - "gd-stage-052" - ], - "NUM2": [ + "VALUE": [ 1, [ 4, - 256 + 0 ] ] }, - "fields": {}, + "fields": { + "VARIABLE": [ + "area progress", + "area-progress" + ] + }, "shadow": false, "topLevel": false }, - "gd-stage-054": { + "gd-stage-090": { "opcode": "data_setvariableto", - "next": "gd-stage-057", - "parent": "gd-stage-051", + "next": "gd-stage-092", + "parent": "gd-stage-089", "inputs": { "VALUE": [ - 3, - "gd-stage-053", + 1, [ - 10, - "" + 4, + 13 ] ] }, "fields": { "VARIABLE": [ - "rng out", - "rng-out" + "scroll row", + "area-scroll-row" ] }, "shadow": false, "topLevel": false }, - "gd-stage-055": { - "opcode": "operator_multiply", + "gd-stage-091": { + "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-056", + "parent": "gd-stage-092", "inputs": { - "NUM1": [ + "INDEX": [ 3, [ 12, - "rng new high", - "rng-new-high" + "area number", + "area-number" ], [ 10, "" ] - ], - "NUM2": [ - 1, + ] + }, + "fields": { + "LIST": [ + "area map column", + "area-map-column" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-092": { + "opcode": "data_setvariableto", + "next": "gd-stage-094", + "parent": "gd-stage-090", + "inputs": { + "VALUE": [ + 3, + "gd-stage-091", [ - 4, - 256 + 10, + "" ] ] }, - "fields": {}, + "fields": { + "VARIABLE": [ + "terrain column", + "area-terrain-column" + ] + }, "shadow": false, "topLevel": false }, - "gd-stage-056": { - "opcode": "operator_add", + "gd-stage-093": { + "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-057", + "parent": "gd-stage-094", "inputs": { - "NUM1": [ - 2, - "gd-stage-055" - ], - "NUM2": [ + "INDEX": [ 3, [ 12, - "rng new low", - "rng-new-low" + "area number", + "area-number" ], [ 10, @@ -3966,18 +5908,23 @@ ] ] }, - "fields": {}, + "fields": { + "LIST": [ + "area schedule start", + "area-schedule-start" + ] + }, "shadow": false, "topLevel": false }, - "gd-stage-057": { + "gd-stage-094": { "opcode": "data_setvariableto", - "next": null, - "parent": "gd-stage-054", + "next": "gd-stage-095", + "parent": "gd-stage-092", "inputs": { "VALUE": [ 3, - "gd-stage-056", + "gd-stage-093", [ 10, "" @@ -3986,242 +5933,197 @@ }, "fields": { "VARIABLE": [ - "rng state", - "rng-state" + "schedule cursor", + "area-schedule-cursor" ] }, "shadow": false, "topLevel": false }, - "gd-stage-058": { - "opcode": "procedures_definition", - "next": "gd-stage-060", - "parent": null, - "inputs": { - "custom_block": [ - 1, - "gd-stage-059" - ] - }, - "fields": {}, - "shadow": false, - "topLevel": true, - "x": 20, - "y": 320 - }, - "gd-stage-059": { - "opcode": "procedures_prototype", - "next": null, - "parent": "gd-stage-058", - "inputs": {}, - "fields": {}, - "shadow": true, - "topLevel": false, - "mutation": { - "tagName": "mutation", - "children": [], - "proccode": "clear slots", - "argumentids": "[]", - "argumentnames": "[]", - "argumentdefaults": "[]", - "warp": "true" - } - }, - "gd-stage-060": { + "gd-stage-095": { "opcode": "data_setvariableto", - "next": "gd-stage-061", - "parent": "gd-stage-058", + "next": null, + "parent": "gd-stage-094", "inputs": { "VALUE": [ 1, [ 4, - 1 + 0 ] ] }, "fields": { "VARIABLE": [ - "slot index", - "slot-index" + "schedule fired", + "area-schedule-fired" ] }, "shadow": false, "topLevel": false }, - "gd-stage-061": { - "opcode": "control_repeat", + "gd-stage-096": { + "opcode": "control_repeat_until", "next": null, - "parent": "gd-stage-060", + "parent": "gd-stage-083", "inputs": { - "TIMES": [ - 1, - [ - 4, - 64 - ] + "CONDITION": [ + 2, + "gd-stage-102" ], "SUBSTACK": [ 2, - "gd-stage-062" + "gd-stage-122" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-062": { - "opcode": "data_replaceitemoflist", - "next": "gd-stage-063", - "parent": "gd-stage-061", + "gd-stage-097": { + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-098", "inputs": { "INDEX": [ 3, [ 12, - "slot index", - "slot-index" + "area number", + "area-number" ], [ 10, "" ] - ], - "ITEM": [ - 1, - [ - 4, - 0 - ] ] }, "fields": { "LIST": [ - "slot type", - "slot-type" + "area schedule end", + "area-schedule-end" ] }, "shadow": false, "topLevel": false }, - "gd-stage-063": { - "opcode": "data_replaceitemoflist", - "next": "gd-stage-064", - "parent": "gd-stage-062", + "gd-stage-098": { + "opcode": "operator_gt", + "next": null, + "parent": "gd-stage-102", "inputs": { - "INDEX": [ + "OPERAND1": [ 3, [ 12, - "slot index", - "slot-index" + "schedule cursor", + "area-schedule-cursor" ], [ 10, "" ] ], - "ITEM": [ - 1, - [ - 4, - 0 - ] - ] - }, - "fields": { - "LIST": [ - "slot state", - "slot-state" + "OPERAND2": [ + 2, + "gd-stage-097" ] }, + "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-064": { - "opcode": "data_changevariableby", + "gd-stage-099": { + "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-063", + "parent": "gd-stage-100", "inputs": { - "VALUE": [ - 1, + "INDEX": [ + 3, [ - 4, - 1 + 12, + "schedule cursor", + "area-schedule-cursor" + ], + [ + 10, + "" ] ] }, "fields": { - "VARIABLE": [ - "slot index", - "slot-index" + "LIST": [ + "schedule trigger row", + "area-schedule-trigger-row" ] }, "shadow": false, "topLevel": false }, - "gd-stage-065": { - "opcode": "procedures_definition", - "next": "gd-stage-067", - "parent": null, + "gd-stage-100": { + "opcode": "operator_equals", + "next": null, + "parent": "gd-stage-101", "inputs": { - "custom_block": [ - 1, - "gd-stage-066" + "OPERAND1": [ + 2, + "gd-stage-099" + ], + "OPERAND2": [ + 3, + [ + 12, + "scroll row", + "area-scroll-row" + ], + [ + 10, + "" + ] ] }, "fields": {}, "shadow": false, - "topLevel": true, - "x": 20, - "y": 470 + "topLevel": false }, - "gd-stage-066": { - "opcode": "procedures_prototype", + "gd-stage-101": { + "opcode": "operator_not", "next": null, - "parent": "gd-stage-065", - "inputs": {}, - "fields": {}, - "shadow": true, - "topLevel": false, - "mutation": { - "tagName": "mutation", - "children": [], - "proccode": "advance slots", - "argumentids": "[]", - "argumentnames": "[]", - "argumentdefaults": "[]", - "warp": "true" - } - }, - "gd-stage-067": { - "opcode": "data_changevariableby", - "next": "gd-stage-068", - "parent": "gd-stage-065", + "parent": "gd-stage-102", "inputs": { - "VALUE": [ - 1, - [ - 4, - 1 - ] + "OPERAND": [ + 2, + "gd-stage-100" ] }, - "fields": { - "VARIABLE": [ - "tick", - "tick" + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-102": { + "opcode": "operator_or", + "next": null, + "parent": null, + "inputs": { + "OPERAND1": [ + 2, + "gd-stage-098" + ], + "OPERAND2": [ + 2, + "gd-stage-101" ] }, + "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-068": { - "opcode": "data_setvariableto", - "next": "gd-stage-069", - "parent": "gd-stage-067", + "gd-stage-103": { + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-104", "inputs": { - "VALUE": [ + "INDEX": [ 1, [ 4, @@ -4230,47 +6132,48 @@ ] }, "fields": { - "VARIABLE": [ - "slot index", - "slot-index" + "LIST": [ + "difficulty increment", + "difficulty-increment" ] }, "shadow": false, "topLevel": false }, - "gd-stage-069": { - "opcode": "control_repeat", + "gd-stage-104": { + "opcode": "operator_add", "next": null, - "parent": "gd-stage-068", + "parent": "gd-stage-105", "inputs": { - "TIMES": [ - 1, + "NUM1": [ + 3, [ - 4, - 64 + 12, + "ai level", + "difficulty-ai-level" + ], + [ + 10, + "" ] ], - "SUBSTACK": [ + "NUM2": [ 2, - "gd-stage-073" + "gd-stage-103" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-070": { - "opcode": "data_itemoflist", - "next": null, - "parent": "gd-stage-071", + "gd-stage-105": { + "opcode": "data_setvariableto", + "next": "gd-stage-108", + "parent": "gd-stage-122", "inputs": { - "INDEX": [ + "VALUE": [ 3, - [ - 12, - "slot index", - "slot-index" - ], + "gd-stage-104", [ 10, "" @@ -4278,28 +6181,36 @@ ] }, "fields": { - "LIST": [ - "slot type", - "slot-type" + "VARIABLE": [ + "ai level", + "difficulty-ai-level" ] }, "shadow": false, "topLevel": false }, - "gd-stage-071": { - "opcode": "operator_equals", + "gd-stage-106": { + "opcode": "operator_gt", "next": null, - "parent": "gd-stage-072", + "parent": "gd-stage-108", "inputs": { "OPERAND1": [ - 2, - "gd-stage-070" + 3, + [ + 12, + "ai level", + "difficulty-ai-level" + ], + [ + 10, + "" + ] ], "OPERAND2": [ 1, [ 4, - 0 + 127 ] ] }, @@ -4307,130 +6218,138 @@ "shadow": false, "topLevel": false }, - "gd-stage-072": { - "opcode": "operator_not", + "gd-stage-107": { + "opcode": "data_changevariableby", "next": null, - "parent": "gd-stage-073", + "parent": "gd-stage-108", "inputs": { - "OPERAND": [ - 2, - "gd-stage-071" + "VALUE": [ + 1, + [ + 4, + -64 + ] + ] + }, + "fields": { + "VARIABLE": [ + "ai level", + "difficulty-ai-level" ] }, - "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-073": { + "gd-stage-108": { "opcode": "control_if", - "next": "gd-stage-074", - "parent": "gd-stage-069", + "next": "gd-stage-109", + "parent": "gd-stage-105", "inputs": { "CONDITION": [ 2, - "gd-stage-072" + "gd-stage-106" + ], + "SUBSTACK": [ + 2, + "gd-stage-107" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-074": { - "opcode": "data_changevariableby", - "next": null, - "parent": "gd-stage-073", + "gd-stage-109": { + "opcode": "data_setvariableto", + "next": "gd-stage-119", + "parent": "gd-stage-108", "inputs": { "VALUE": [ - 1, + 3, [ - 4, - 1 + 12, + "ai level", + "difficulty-ai-level" + ], + [ + 10, + "" ] ] }, "fields": { "VARIABLE": [ - "slot index", - "slot-index" + "formation index", + "formation-index" ] }, "shadow": false, "topLevel": false }, - "gd-stage-075": { - "opcode": "procedures_definition", - "next": "gd-stage-077", - "parent": null, + "gd-stage-110": { + "opcode": "operator_and", + "next": null, + "parent": "gd-stage-119", "inputs": { - "custom_block": [ - 1, - "gd-stage-076" + "OPERAND1": [ + 2, + "gd-stage-111" + ], + "OPERAND2": [ + 2, + "gd-stage-112" ] }, "fields": {}, "shadow": false, - "topLevel": true, - "x": 20, - "y": 620 + "topLevel": false }, - "gd-stage-076": { - "opcode": "procedures_prototype", + "gd-stage-111": { + "opcode": "operator_gt", "next": null, - "parent": "gd-stage-075", - "inputs": {}, - "fields": {}, - "shadow": true, - "topLevel": false, - "mutation": { - "tagName": "mutation", - "children": [], - "proccode": "advance area", - "argumentids": "[]", - "argumentnames": "[]", - "argumentdefaults": "[]", - "warp": "true" - } - }, - "gd-stage-077": { - "opcode": "data_changevariableby", - "next": "gd-stage-082", - "parent": "gd-stage-075", + "parent": "gd-stage-110", "inputs": { - "VALUE": [ + "OPERAND1": [ + 3, + [ + 12, + "formation index", + "formation-index" + ], + [ + 10, + "" + ] + ], + "OPERAND2": [ 1, [ 4, - 32 + -33 ] ] }, - "fields": { - "VARIABLE": [ - "area progress", - "area-progress" - ] - }, + "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-078": { - "opcode": "operator_subtract", + "gd-stage-112": { + "opcode": "operator_gt", "next": null, - "parent": "gd-stage-079", + "parent": "gd-stage-110", "inputs": { - "NUM1": [ + "OPERAND1": [ 1, [ 4, - 3328 + 128 ] ], - "NUM2": [ + "OPERAND2": [ 3, [ 12, - "area progress", - "area-progress" + "formation index", + "formation-index" ], [ 10, @@ -4442,20 +6361,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-079": { - "opcode": "operator_mod", + "gd-stage-113": { + "opcode": "operator_add", "next": null, - "parent": "gd-stage-080", + "parent": "gd-stage-114", "inputs": { "NUM1": [ - 2, - "gd-stage-078" + 3, + [ + 12, + "formation index", + "formation-index" + ], + [ + 10, + "" + ] ], "NUM2": [ 1, [ 4, - 65536 + 33 ] ] }, @@ -4463,20 +6390,70 @@ "shadow": false, "topLevel": false }, - "gd-stage-080": { - "opcode": "operator_divide", + "gd-stage-114": { + "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-081", + "parent": "gd-stage-115", "inputs": { - "NUM1": [ + "INDEX": [ 2, - "gd-stage-079" + "gd-stage-113" + ] + }, + "fields": { + "LIST": [ + "formation count table", + "formation-count-table" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-115": { + "opcode": "data_setvariableto", + "next": "gd-stage-118", + "parent": "gd-stage-119", + "inputs": { + "VALUE": [ + 3, + "gd-stage-114", + [ + 10, + "" + ] + ] + }, + "fields": { + "VARIABLE": [ + "formation count", + "formation-count" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-116": { + "opcode": "operator_add", + "next": null, + "parent": "gd-stage-117", + "inputs": { + "NUM1": [ + 3, + [ + 12, + "formation index", + "formation-index" + ], + [ + 10, + "" + ] ], "NUM2": [ 1, [ 4, - 256 + 33 ] ] }, @@ -4484,33 +6461,33 @@ "shadow": false, "topLevel": false }, - "gd-stage-081": { - "opcode": "operator_mathop", + "gd-stage-117": { + "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-082", + "parent": "gd-stage-118", "inputs": { - "NUM": [ + "INDEX": [ 2, - "gd-stage-080" + "gd-stage-116" ] }, "fields": { - "OPERATOR": [ - "floor", - null + "LIST": [ + "formation type offset table", + "formation-type-offset-table" ] }, "shadow": false, "topLevel": false }, - "gd-stage-082": { + "gd-stage-118": { "opcode": "data_setvariableto", - "next": "gd-stage-083", - "parent": "gd-stage-077", + "next": null, + "parent": "gd-stage-115", "inputs": { "VALUE": [ 3, - "gd-stage-081", + "gd-stage-117", [ 10, "" @@ -4519,57 +6496,72 @@ }, "fields": { "VARIABLE": [ - "scroll row", - "area-scroll-row" + "formation type offset", + "formation-type-offset" ] }, "shadow": false, "topLevel": false }, - "gd-stage-083": { - "opcode": "control_if_else", + "gd-stage-119": { + "opcode": "control_if", "next": null, - "parent": "gd-stage-082", + "parent": "gd-stage-109", "inputs": { "CONDITION": [ 2, - "gd-stage-084" + "gd-stage-110" ], "SUBSTACK": [ 2, - "gd-stage-085" - ], - "SUBSTACK2": [ - 2, - "gd-stage-096" + "gd-stage-115" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-084": { - "opcode": "operator_equals", + "gd-stage-120": { + "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-083", + "parent": "gd-stage-121", "inputs": { - "OPERAND1": [ + "INDEX": [ 3, [ 12, - "scroll row", - "area-scroll-row" + "schedule cursor", + "area-schedule-cursor" ], [ 10, "" ] + ] + }, + "fields": { + "LIST": [ + "schedule handler", + "area-schedule-handler" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-121": { + "opcode": "operator_equals", + "next": null, + "parent": "gd-stage-122", + "inputs": { + "OPERAND1": [ + 2, + "gd-stage-120" ], "OPERAND2": [ 1, [ - 4, - 14 + 10, + "raise_ai_level_and_set_formation" ] ] }, @@ -4577,230 +6569,254 @@ "shadow": false, "topLevel": false }, - "gd-stage-085": { - "opcode": "control_if_else", - "next": "gd-stage-089", - "parent": "gd-stage-083", + "gd-stage-122": { + "opcode": "control_if", + "next": "gd-stage-137", + "parent": "gd-stage-096", "inputs": { "CONDITION": [ 2, - "gd-stage-086" + "gd-stage-121" ], "SUBSTACK": [ 2, - "gd-stage-087" - ], - "SUBSTACK2": [ - 2, - "gd-stage-088" + "gd-stage-105" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-086": { - "opcode": "operator_equals", + "gd-stage-123": { + "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-085", + "parent": "gd-stage-124", "inputs": { - "OPERAND1": [ + "INDEX": [ 3, [ 12, - "area number", - "area-number" + "schedule cursor", + "area-schedule-cursor" ], [ 10, "" ] - ], - "OPERAND2": [ - 1, - [ - 4, - 16 - ] - ] - }, - "fields": {}, - "shadow": false, - "topLevel": false - }, - "gd-stage-087": { - "opcode": "data_setvariableto", - "next": null, - "parent": "gd-stage-085", - "inputs": { - "VALUE": [ - 1, - [ - 4, - 7 - ] ] }, "fields": { - "VARIABLE": [ - "area number", - "area-number" + "LIST": [ + "schedule handler", + "area-schedule-handler" ] }, "shadow": false, "topLevel": false }, - "gd-stage-088": { - "opcode": "data_changevariableby", + "gd-stage-124": { + "opcode": "operator_equals", "next": null, - "parent": "gd-stage-085", + "parent": "gd-stage-137", "inputs": { - "VALUE": [ + "OPERAND1": [ + 2, + "gd-stage-123" + ], + "OPERAND2": [ 1, [ - 4, - 1 + 10, + "set_flying_formation" ] ] }, - "fields": { - "VARIABLE": [ - "area number", - "area-number" - ] - }, + "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-089": { - "opcode": "data_setvariableto", - "next": "gd-stage-090", - "parent": "gd-stage-085", + "gd-stage-125": { + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-126", "inputs": { - "VALUE": [ - 1, + "INDEX": [ + 3, [ - 4, - 0 + 12, + "schedule cursor", + "area-schedule-cursor" + ], + [ + 10, + "" ] ] }, - "fields": { - "VARIABLE": [ - "area progress", - "area-progress" + "fields": { + "LIST": [ + "schedule arg", + "area-schedule-arg" ] }, "shadow": false, "topLevel": false }, - "gd-stage-090": { + "gd-stage-126": { "opcode": "data_setvariableto", - "next": "gd-stage-092", - "parent": "gd-stage-089", + "next": "gd-stage-136", + "parent": "gd-stage-137", "inputs": { "VALUE": [ - 1, + 3, + "gd-stage-125", [ - 4, - 13 + 10, + "" ] ] }, "fields": { "VARIABLE": [ - "scroll row", - "area-scroll-row" + "formation index", + "formation-index" ] }, "shadow": false, "topLevel": false }, - "gd-stage-091": { - "opcode": "data_itemoflist", + "gd-stage-127": { + "opcode": "operator_and", "next": null, - "parent": "gd-stage-092", + "parent": "gd-stage-136", "inputs": { - "INDEX": [ + "OPERAND1": [ + 2, + "gd-stage-128" + ], + "OPERAND2": [ + 2, + "gd-stage-129" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-128": { + "opcode": "operator_gt", + "next": null, + "parent": "gd-stage-127", + "inputs": { + "OPERAND1": [ 3, [ 12, - "area number", - "area-number" + "formation index", + "formation-index" ], [ 10, "" ] + ], + "OPERAND2": [ + 1, + [ + 4, + -33 + ] ] }, - "fields": { - "LIST": [ - "area map column", - "area-map-column" - ] - }, + "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-092": { - "opcode": "data_setvariableto", - "next": "gd-stage-094", - "parent": "gd-stage-090", + "gd-stage-129": { + "opcode": "operator_gt", + "next": null, + "parent": "gd-stage-127", "inputs": { - "VALUE": [ + "OPERAND1": [ + 1, + [ + 4, + 128 + ] + ], + "OPERAND2": [ 3, - "gd-stage-091", + [ + 12, + "formation index", + "formation-index" + ], [ 10, "" ] ] }, - "fields": { - "VARIABLE": [ - "terrain column", - "area-terrain-column" - ] - }, + "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-093": { - "opcode": "data_itemoflist", + "gd-stage-130": { + "opcode": "operator_add", "next": null, - "parent": "gd-stage-094", + "parent": "gd-stage-131", "inputs": { - "INDEX": [ + "NUM1": [ 3, [ 12, - "area number", - "area-number" + "formation index", + "formation-index" ], [ 10, "" ] + ], + "NUM2": [ + 1, + [ + 4, + 33 + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-131": { + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-132", + "inputs": { + "INDEX": [ + 2, + "gd-stage-130" ] }, "fields": { "LIST": [ - "area schedule start", - "area-schedule-start" + "formation count table", + "formation-count-table" ] }, "shadow": false, "topLevel": false }, - "gd-stage-094": { + "gd-stage-132": { "opcode": "data_setvariableto", - "next": "gd-stage-095", - "parent": "gd-stage-092", + "next": "gd-stage-135", + "parent": "gd-stage-136", "inputs": { "VALUE": [ 3, - "gd-stage-093", + "gd-stage-131", [ 10, "" @@ -4809,65 +6825,69 @@ }, "fields": { "VARIABLE": [ - "schedule cursor", - "area-schedule-cursor" + "formation count", + "formation-count" ] }, "shadow": false, "topLevel": false }, - "gd-stage-095": { - "opcode": "data_setvariableto", + "gd-stage-133": { + "opcode": "operator_add", "next": null, - "parent": "gd-stage-094", + "parent": "gd-stage-134", "inputs": { - "VALUE": [ + "NUM1": [ + 3, + [ + 12, + "formation index", + "formation-index" + ], + [ + 10, + "" + ] + ], + "NUM2": [ 1, [ 4, - 0 + 33 ] ] }, - "fields": { - "VARIABLE": [ - "schedule fired", - "area-schedule-fired" - ] - }, + "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-096": { - "opcode": "control_repeat_until", + "gd-stage-134": { + "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-083", + "parent": "gd-stage-135", "inputs": { - "CONDITION": [ - 2, - "gd-stage-102" - ], - "SUBSTACK": [ + "INDEX": [ 2, - "gd-stage-103" + "gd-stage-133" + ] + }, + "fields": { + "LIST": [ + "formation type offset table", + "formation-type-offset-table" ] }, - "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-097": { - "opcode": "data_itemoflist", + "gd-stage-135": { + "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-098", + "parent": "gd-stage-132", "inputs": { - "INDEX": [ + "VALUE": [ 3, - [ - 12, - "area number", - "area-number" - ], + "gd-stage-134", [ 10, "" @@ -4875,44 +6895,54 @@ ] }, "fields": { - "LIST": [ - "area schedule end", - "area-schedule-end" + "VARIABLE": [ + "formation type offset", + "formation-type-offset" ] }, "shadow": false, "topLevel": false }, - "gd-stage-098": { - "opcode": "operator_gt", + "gd-stage-136": { + "opcode": "control_if", "next": null, - "parent": "gd-stage-102", + "parent": "gd-stage-126", "inputs": { - "OPERAND1": [ - 3, - [ - 12, - "schedule cursor", - "area-schedule-cursor" - ], - [ - 10, - "" - ] + "CONDITION": [ + 2, + "gd-stage-127" ], - "OPERAND2": [ + "SUBSTACK": [ 2, - "gd-stage-097" + "gd-stage-132" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-099": { + "gd-stage-137": { + "opcode": "control_if", + "next": "gd-stage-142", + "parent": "gd-stage-122", + "inputs": { + "CONDITION": [ + 2, + "gd-stage-124" + ], + "SUBSTACK": [ + 2, + "gd-stage-126" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-138": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-100", + "parent": "gd-stage-139", "inputs": { "INDEX": [ 3, @@ -4929,75 +6959,100 @@ }, "fields": { "LIST": [ - "schedule trigger row", - "area-schedule-trigger-row" + "schedule handler", + "area-schedule-handler" ] }, "shadow": false, "topLevel": false }, - "gd-stage-100": { + "gd-stage-139": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-101", + "parent": "gd-stage-142", "inputs": { "OPERAND1": [ 2, - "gd-stage-099" + "gd-stage-138" ], "OPERAND2": [ - 3, - [ - 12, - "scroll row", - "area-scroll-row" - ], + 1, [ 10, - "" + "reset_flying_formation" + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-140": { + "opcode": "data_setvariableto", + "next": "gd-stage-141", + "parent": "gd-stage-142", + "inputs": { + "VALUE": [ + 1, + [ + 4, + 0 ] ] }, - "fields": {}, + "fields": { + "VARIABLE": [ + "formation count", + "formation-count" + ] + }, "shadow": false, "topLevel": false }, - "gd-stage-101": { - "opcode": "operator_not", + "gd-stage-141": { + "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-102", + "parent": "gd-stage-140", "inputs": { - "OPERAND": [ - 2, - "gd-stage-100" + "VALUE": [ + 1, + [ + 4, + 0 + ] + ] + }, + "fields": { + "VARIABLE": [ + "formation type offset", + "formation-type-offset" ] }, - "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-102": { - "opcode": "operator_or", - "next": null, - "parent": null, + "gd-stage-142": { + "opcode": "control_if", + "next": "gd-stage-143", + "parent": "gd-stage-137", "inputs": { - "OPERAND1": [ + "CONDITION": [ 2, - "gd-stage-098" + "gd-stage-139" ], - "OPERAND2": [ + "SUBSTACK": [ 2, - "gd-stage-101" + "gd-stage-140" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-103": { + "gd-stage-143": { "opcode": "data_changevariableby", - "next": "gd-stage-104", - "parent": "gd-stage-096", + "next": "gd-stage-144", + "parent": "gd-stage-142", "inputs": { "VALUE": [ 1, @@ -5016,10 +7071,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-104": { + "gd-stage-144": { "opcode": "data_changevariableby", "next": null, - "parent": "gd-stage-103", + "parent": "gd-stage-143", "inputs": { "VALUE": [ 1, @@ -5038,14 +7093,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-105": { + "gd-stage-145": { "opcode": "procedures_definition", - "next": "gd-stage-107", + "next": "gd-stage-147", "parent": null, "inputs": { "custom_block": [ 1, - "gd-stage-106" + "gd-stage-146" ] }, "fields": {}, @@ -5054,10 +7109,10 @@ "x": 20, "y": 770 }, - "gd-stage-106": { + "gd-stage-146": { "opcode": "procedures_prototype", "next": null, - "parent": "gd-stage-105", + "parent": "gd-stage-145", "inputs": {}, "fields": {}, "shadow": true, @@ -5072,10 +7127,10 @@ "warp": "true" } }, - "gd-stage-107": { + "gd-stage-147": { "opcode": "data_changevariableby", - "next": "gd-stage-108", - "parent": "gd-stage-105", + "next": "gd-stage-148", + "parent": "gd-stage-145", "inputs": { "VALUE": [ 3, @@ -5099,28 +7154,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-108": { + "gd-stage-148": { "opcode": "control_if", - "next": "gd-stage-111", - "parent": "gd-stage-107", + "next": "gd-stage-151", + "parent": "gd-stage-147", "inputs": { "CONDITION": [ 2, - "gd-stage-109" + "gd-stage-149" ], "SUBSTACK": [ 2, - "gd-stage-110" + "gd-stage-150" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-109": { + "gd-stage-149": { "opcode": "operator_gt", "next": null, - "parent": "gd-stage-108", + "parent": "gd-stage-148", "inputs": { "OPERAND1": [ 3, @@ -5146,10 +7201,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-110": { + "gd-stage-150": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-108", + "parent": "gd-stage-148", "inputs": { "VALUE": [ 1, @@ -5168,28 +7223,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-111": { + "gd-stage-151": { "opcode": "control_if", - "next": "gd-stage-114", - "parent": "gd-stage-108", + "next": "gd-stage-154", + "parent": "gd-stage-148", "inputs": { "CONDITION": [ 2, - "gd-stage-112" + "gd-stage-152" ], "SUBSTACK": [ 2, - "gd-stage-113" + "gd-stage-153" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-112": { + "gd-stage-152": { "opcode": "operator_gt", "next": null, - "parent": "gd-stage-111", + "parent": "gd-stage-151", "inputs": { "OPERAND1": [ 3, @@ -5220,10 +7275,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-113": { + "gd-stage-153": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-111", + "parent": "gd-stage-151", "inputs": { "VALUE": [ 3, @@ -5247,10 +7302,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-114": { + "gd-stage-154": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-111", + "parent": "gd-stage-151", "inputs": {}, "fields": {}, "shadow": false, @@ -5263,14 +7318,14 @@ "warp": "true" } }, - "gd-stage-115": { + "gd-stage-155": { "opcode": "procedures_definition", - "next": "gd-stage-133", + "next": "gd-stage-173", "parent": null, "inputs": { "custom_block": [ 1, - "gd-stage-116" + "gd-stage-156" ] }, "fields": {}, @@ -5279,10 +7334,10 @@ "x": 20, "y": 920 }, - "gd-stage-116": { + "gd-stage-156": { "opcode": "procedures_prototype", "next": null, - "parent": "gd-stage-115", + "parent": "gd-stage-155", "inputs": {}, "fields": {}, "shadow": true, @@ -5297,10 +7352,10 @@ "warp": "true" } }, - "gd-stage-117": { + "gd-stage-157": { "opcode": "operator_lt", "next": null, - "parent": "gd-stage-118", + "parent": "gd-stage-158", "inputs": { "OPERAND1": [ 3, @@ -5331,24 +7386,24 @@ "shadow": false, "topLevel": false }, - "gd-stage-118": { + "gd-stage-158": { "opcode": "operator_not", "next": null, - "parent": "gd-stage-126", + "parent": "gd-stage-166", "inputs": { "OPERAND": [ 2, - "gd-stage-117" + "gd-stage-157" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-119": { + "gd-stage-159": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-120", + "parent": "gd-stage-160", "inputs": { "INDEX": [ 1, @@ -5367,10 +7422,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-120": { + "gd-stage-160": { "opcode": "operator_add", "next": null, - "parent": "gd-stage-121", + "parent": "gd-stage-161", "inputs": { "NUM1": [ 3, @@ -5386,21 +7441,21 @@ ], "NUM2": [ 2, - "gd-stage-119" + "gd-stage-159" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-121": { + "gd-stage-161": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-125", + "parent": "gd-stage-165", "inputs": { "VALUE": [ 3, - "gd-stage-120", + "gd-stage-160", [ 10, "" @@ -5416,10 +7471,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-122": { + "gd-stage-162": { "opcode": "data_changevariableby", - "next": "gd-stage-124", - "parent": "gd-stage-126", + "next": "gd-stage-164", + "parent": "gd-stage-166", "inputs": { "VALUE": [ 1, @@ -5438,10 +7493,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-123": { + "gd-stage-163": { "opcode": "sound_sounds_menu", "next": null, - "parent": "gd-stage-124", + "parent": "gd-stage-164", "inputs": {}, "fields": { "SOUND_MENU": [ @@ -5452,24 +7507,24 @@ "shadow": true, "topLevel": false }, - "gd-stage-124": { + "gd-stage-164": { "opcode": "sound_play", - "next": "gd-stage-125", - "parent": "gd-stage-122", + "next": "gd-stage-165", + "parent": "gd-stage-162", "inputs": { "SOUND_MENU": [ 1, - "gd-stage-123" + "gd-stage-163" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-125": { + "gd-stage-165": { "opcode": "event_broadcast", - "next": "gd-stage-121", - "parent": "gd-stage-124", + "next": "gd-stage-161", + "parent": "gd-stage-164", "inputs": { "BROADCAST_INPUT": [ 1, @@ -5484,50 +7539,50 @@ "shadow": false, "topLevel": false }, - "gd-stage-126": { + "gd-stage-166": { "opcode": "control_if", "next": null, - "parent": "gd-stage-127", + "parent": "gd-stage-167", "inputs": { "CONDITION": [ 2, - "gd-stage-118" + "gd-stage-158" ], "SUBSTACK": [ 2, - "gd-stage-122" + "gd-stage-162" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-127": { + "gd-stage-167": { "opcode": "control_if_else", "next": null, - "parent": "gd-stage-133", + "parent": "gd-stage-173", "inputs": { "CONDITION": [ 2, - "gd-stage-128" + "gd-stage-168" ], "SUBSTACK": [ 2, - "gd-stage-129" + "gd-stage-169" ], "SUBSTACK2": [ 2, - "gd-stage-126" + "gd-stage-166" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-128": { + "gd-stage-168": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-127", + "parent": "gd-stage-167", "inputs": { "OPERAND1": [ 3, @@ -5553,10 +7608,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-129": { + "gd-stage-169": { "opcode": "data_changevariableby", - "next": "gd-stage-131", - "parent": "gd-stage-127", + "next": "gd-stage-171", + "parent": "gd-stage-167", "inputs": { "VALUE": [ 1, @@ -5575,10 +7630,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-130": { + "gd-stage-170": { "opcode": "sound_sounds_menu", "next": null, - "parent": "gd-stage-131", + "parent": "gd-stage-171", "inputs": {}, "fields": { "SOUND_MENU": [ @@ -5589,24 +7644,24 @@ "shadow": true, "topLevel": false }, - "gd-stage-131": { + "gd-stage-171": { "opcode": "sound_play", - "next": "gd-stage-132", - "parent": "gd-stage-129", + "next": "gd-stage-172", + "parent": "gd-stage-169", "inputs": { "SOUND_MENU": [ 1, - "gd-stage-130" + "gd-stage-170" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-132": { + "gd-stage-172": { "opcode": "event_broadcast", "next": null, - "parent": "gd-stage-131", + "parent": "gd-stage-171", "inputs": { "BROADCAST_INPUT": [ 1, @@ -5621,28 +7676,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-133": { + "gd-stage-173": { "opcode": "control_if", "next": null, - "parent": "gd-stage-115", + "parent": "gd-stage-155", "inputs": { "CONDITION": [ 2, - "gd-stage-134" + "gd-stage-174" ], "SUBSTACK": [ 2, - "gd-stage-127" + "gd-stage-167" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-134": { + "gd-stage-174": { "opcode": "operator_gt", "next": null, - "parent": "gd-stage-133", + "parent": "gd-stage-173", "inputs": { "OPERAND1": [ 3, @@ -5668,14 +7723,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-135": { + "gd-stage-175": { "opcode": "procedures_definition", - "next": "gd-stage-137", + "next": "gd-stage-177", "parent": null, "inputs": { "custom_block": [ 1, - "gd-stage-136" + "gd-stage-176" ] }, "fields": {}, @@ -5684,10 +7739,10 @@ "x": 20, "y": 1070 }, - "gd-stage-136": { + "gd-stage-176": { "opcode": "procedures_prototype", "next": null, - "parent": "gd-stage-135", + "parent": "gd-stage-175", "inputs": {}, "fields": {}, "shadow": true, @@ -5702,10 +7757,10 @@ "warp": "true" } }, - "gd-stage-137": { + "gd-stage-177": { "opcode": "data_replaceitemoflist", - "next": "gd-stage-138", - "parent": "gd-stage-135", + "next": "gd-stage-178", + "parent": "gd-stage-175", "inputs": { "INDEX": [ 3, @@ -5736,10 +7791,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-138": { + "gd-stage-178": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-137", + "parent": "gd-stage-177", "inputs": {}, "fields": {}, "shadow": false, @@ -5752,14 +7807,14 @@ "warp": "true" } }, - "gd-stage-139": { + "gd-stage-179": { "opcode": "procedures_definition", - "next": "gd-stage-141", + "next": "gd-stage-181", "parent": null, "inputs": { "custom_block": [ 1, - "gd-stage-140" + "gd-stage-180" ] }, "fields": {}, @@ -5768,10 +7823,10 @@ "x": 20, "y": 1220 }, - "gd-stage-140": { + "gd-stage-180": { "opcode": "procedures_prototype", "next": null, - "parent": "gd-stage-139", + "parent": "gd-stage-179", "inputs": {}, "fields": {}, "shadow": true, @@ -5786,10 +7841,10 @@ "warp": "true" } }, - "gd-stage-141": { + "gd-stage-181": { "opcode": "data_setvariableto", - "next": "gd-stage-142", - "parent": "gd-stage-139", + "next": "gd-stage-182", + "parent": "gd-stage-179", "inputs": { "VALUE": [ 1, @@ -5808,10 +7863,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-142": { + "gd-stage-182": { "opcode": "data_setvariableto", - "next": "gd-stage-143", - "parent": "gd-stage-141", + "next": "gd-stage-183", + "parent": "gd-stage-181", "inputs": { "VALUE": [ 1, @@ -5830,10 +7885,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-143": { + "gd-stage-183": { "opcode": "control_repeat", "next": null, - "parent": "gd-stage-142", + "parent": "gd-stage-182", "inputs": { "TIMES": [ 1, @@ -5844,17 +7899,17 @@ ], "SUBSTACK": [ 2, - "gd-stage-151" + "gd-stage-191" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-144": { + "gd-stage-184": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-147", + "parent": "gd-stage-187", "inputs": { "OPERAND1": [ 3, @@ -5880,10 +7935,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-145": { + "gd-stage-185": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-146", + "parent": "gd-stage-186", "inputs": { "INDEX": [ 3, @@ -5907,14 +7962,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-146": { + "gd-stage-186": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-147", + "parent": "gd-stage-187", "inputs": { "OPERAND1": [ 2, - "gd-stage-145" + "gd-stage-185" ], "OPERAND2": [ 1, @@ -5928,28 +7983,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-147": { + "gd-stage-187": { "opcode": "operator_and", "next": null, - "parent": "gd-stage-151", + "parent": "gd-stage-191", "inputs": { "OPERAND1": [ 2, - "gd-stage-144" + "gd-stage-184" ], "OPERAND2": [ 2, - "gd-stage-146" + "gd-stage-186" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-148": { + "gd-stage-188": { "opcode": "data_replaceitemoflist", - "next": "gd-stage-149", - "parent": "gd-stage-151", + "next": "gd-stage-189", + "parent": "gd-stage-191", "inputs": { "INDEX": [ 3, @@ -5980,10 +8035,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-149": { + "gd-stage-189": { "opcode": "data_replaceitemoflist", - "next": "gd-stage-150", - "parent": "gd-stage-148", + "next": "gd-stage-190", + "parent": "gd-stage-188", "inputs": { "INDEX": [ 3, @@ -6014,10 +8069,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-150": { + "gd-stage-190": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-149", + "parent": "gd-stage-189", "inputs": { "VALUE": [ 3, @@ -6041,28 +8096,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-151": { + "gd-stage-191": { "opcode": "control_if", - "next": "gd-stage-152", - "parent": "gd-stage-143", + "next": "gd-stage-192", + "parent": "gd-stage-183", "inputs": { "CONDITION": [ 2, - "gd-stage-147" + "gd-stage-187" ], "SUBSTACK": [ 2, - "gd-stage-148" + "gd-stage-188" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-152": { + "gd-stage-192": { "opcode": "data_changevariableby", "next": null, - "parent": "gd-stage-151", + "parent": "gd-stage-191", "inputs": { "VALUE": [ 1, @@ -6081,9 +8136,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-153": { + "gd-stage-193": { "opcode": "event_whenflagclicked", - "next": "gd-stage-154", + "next": "gd-stage-194", "parent": null, "inputs": {}, "fields": {}, @@ -6092,10 +8147,10 @@ "x": 20, "y": 1370 }, - "gd-stage-154": { + "gd-stage-194": { "opcode": "data_setvariableto", - "next": "gd-stage-155", - "parent": "gd-stage-153", + "next": "gd-stage-195", + "parent": "gd-stage-193", "inputs": { "VALUE": [ 1, @@ -6114,10 +8169,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-155": { + "gd-stage-195": { "opcode": "data_setvariableto", - "next": "gd-stage-156", - "parent": "gd-stage-154", + "next": "gd-stage-196", + "parent": "gd-stage-194", "inputs": { "VALUE": [ 1, @@ -6136,10 +8191,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-156": { + "gd-stage-196": { "opcode": "data_setvariableto", - "next": "gd-stage-157", - "parent": "gd-stage-155", + "next": "gd-stage-197", + "parent": "gd-stage-195", "inputs": { "VALUE": [ 1, @@ -6158,10 +8213,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-157": { + "gd-stage-197": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-156", + "parent": "gd-stage-196", "inputs": { "director-destination": [ 1, @@ -6189,9 +8244,9 @@ "warp": "false" } }, - "gd-stage-158": { + "gd-stage-198": { "opcode": "event_whenkeypressed", - "next": "gd-stage-160", + "next": "gd-stage-200", "parent": null, "inputs": {}, "fields": { @@ -6205,10 +8260,10 @@ "x": 20, "y": 1520 }, - "gd-stage-159": { + "gd-stage-199": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-160", + "parent": "gd-stage-200", "inputs": { "director-destination": [ 1, @@ -6236,28 +8291,28 @@ "warp": "false" } }, - "gd-stage-160": { + "gd-stage-200": { "opcode": "control_if", "next": null, - "parent": "gd-stage-158", + "parent": "gd-stage-198", "inputs": { "CONDITION": [ 2, - "gd-stage-161" + "gd-stage-201" ], "SUBSTACK": [ 2, - "gd-stage-159" + "gd-stage-199" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-161": { + "gd-stage-201": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-160", + "parent": "gd-stage-200", "inputs": { "OPERAND1": [ 3, @@ -6283,9 +8338,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-162": { + "gd-stage-202": { "opcode": "event_whenkeypressed", - "next": "gd-stage-166", + "next": "gd-stage-206", "parent": null, "inputs": {}, "fields": { @@ -6299,10 +8354,10 @@ "x": 20, "y": 1670 }, - "gd-stage-163": { + "gd-stage-203": { "opcode": "data_changevariableby", - "next": "gd-stage-164", - "parent": "gd-stage-166", + "next": "gd-stage-204", + "parent": "gd-stage-206", "inputs": { "VALUE": [ 1, @@ -6321,10 +8376,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-164": { + "gd-stage-204": { "opcode": "event_broadcast", - "next": "gd-stage-165", - "parent": "gd-stage-163", + "next": "gd-stage-205", + "parent": "gd-stage-203", "inputs": { "BROADCAST_INPUT": [ 1, @@ -6339,10 +8394,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-165": { + "gd-stage-205": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-164", + "parent": "gd-stage-204", "inputs": { "director-destination": [ 1, @@ -6370,28 +8425,28 @@ "warp": "false" } }, - "gd-stage-166": { + "gd-stage-206": { "opcode": "control_if", "next": null, - "parent": "gd-stage-162", + "parent": "gd-stage-202", "inputs": { "CONDITION": [ 2, - "gd-stage-167" + "gd-stage-207" ], "SUBSTACK": [ 2, - "gd-stage-163" + "gd-stage-203" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-167": { + "gd-stage-207": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-166", + "parent": "gd-stage-206", "inputs": { "OPERAND1": [ 3, @@ -6417,9 +8472,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-168": { + "gd-stage-208": { "opcode": "event_whenkeypressed", - "next": "gd-stage-172", + "next": "gd-stage-212", "parent": null, "inputs": {}, "fields": { @@ -6433,10 +8488,10 @@ "x": 20, "y": 1820 }, - "gd-stage-169": { + "gd-stage-209": { "opcode": "data_setvariableto", - "next": "gd-stage-170", - "parent": "gd-stage-172", + "next": "gd-stage-210", + "parent": "gd-stage-212", "inputs": { "VALUE": [ 1, @@ -6455,10 +8510,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-170": { + "gd-stage-210": { "opcode": "event_broadcast", - "next": "gd-stage-171", - "parent": "gd-stage-169", + "next": "gd-stage-211", + "parent": "gd-stage-209", "inputs": { "BROADCAST_INPUT": [ 1, @@ -6473,10 +8528,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-171": { + "gd-stage-211": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-170", + "parent": "gd-stage-210", "inputs": { "director-destination": [ 1, @@ -6504,28 +8559,28 @@ "warp": "false" } }, - "gd-stage-172": { + "gd-stage-212": { "opcode": "control_if", "next": null, - "parent": "gd-stage-168", + "parent": "gd-stage-208", "inputs": { "CONDITION": [ 2, - "gd-stage-173" + "gd-stage-213" ], "SUBSTACK": [ 2, - "gd-stage-169" + "gd-stage-209" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-173": { + "gd-stage-213": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-172", + "parent": "gd-stage-212", "inputs": { "OPERAND1": [ 3, @@ -6551,9 +8606,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-174": { + "gd-stage-214": { "opcode": "event_whenkeypressed", - "next": "gd-stage-178", + "next": "gd-stage-218", "parent": null, "inputs": {}, "fields": { @@ -6567,10 +8622,10 @@ "x": 20, "y": 1970 }, - "gd-stage-175": { + "gd-stage-215": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-176", + "parent": "gd-stage-216", "inputs": { "INDEX": [ 1, @@ -6589,14 +8644,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-176": { + "gd-stage-216": { "opcode": "data_setvariableto", - "next": "gd-stage-177", - "parent": "gd-stage-178", + "next": "gd-stage-217", + "parent": "gd-stage-218", "inputs": { "VALUE": [ 3, - "gd-stage-175", + "gd-stage-215", [ 10, "" @@ -6612,10 +8667,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-177": { + "gd-stage-217": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-176", + "parent": "gd-stage-216", "inputs": {}, "fields": {}, "shadow": false, @@ -6628,28 +8683,28 @@ "warp": "true" } }, - "gd-stage-178": { + "gd-stage-218": { "opcode": "control_if", "next": null, - "parent": "gd-stage-174", + "parent": "gd-stage-214", "inputs": { "CONDITION": [ 2, - "gd-stage-179" + "gd-stage-219" ], "SUBSTACK": [ 2, - "gd-stage-176" + "gd-stage-216" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-179": { + "gd-stage-219": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-178", + "parent": "gd-stage-218", "inputs": { "OPERAND1": [ 3, @@ -6675,9 +8730,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-180": { + "gd-stage-220": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-182", + "next": "gd-stage-222", "parent": null, "inputs": {}, "fields": { @@ -6691,10 +8746,10 @@ "x": 20, "y": 2120 }, - "gd-stage-181": { + "gd-stage-221": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-182", + "parent": "gd-stage-222", "inputs": { "director-destination": [ 1, @@ -6722,46 +8777,46 @@ "warp": "false" } }, - "gd-stage-182": { + "gd-stage-222": { "opcode": "control_if", "next": null, - "parent": "gd-stage-180", + "parent": "gd-stage-220", "inputs": { "CONDITION": [ 2, - "gd-stage-183" + "gd-stage-223" ], "SUBSTACK": [ 2, - "gd-stage-181" + "gd-stage-221" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-183": { + "gd-stage-223": { "opcode": "operator_or", "next": null, - "parent": "gd-stage-182", + "parent": "gd-stage-222", "inputs": { "OPERAND1": [ 2, - "gd-stage-184" + "gd-stage-224" ], "OPERAND2": [ 2, - "gd-stage-185" + "gd-stage-225" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-184": { + "gd-stage-224": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-183", + "parent": "gd-stage-223", "inputs": { "OPERAND1": [ 3, @@ -6787,10 +8842,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-185": { + "gd-stage-225": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-183", + "parent": "gd-stage-223", "inputs": { "OPERAND1": [ 3, @@ -6816,9 +8871,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-186": { + "gd-stage-226": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-193", + "next": "gd-stage-233", "parent": null, "inputs": {}, "fields": { @@ -6832,32 +8887,32 @@ "x": 20, "y": 2270 }, - "gd-stage-187": { + "gd-stage-227": { "opcode": "control_if_else", "next": null, - "parent": "gd-stage-193", + "parent": "gd-stage-233", "inputs": { "CONDITION": [ 2, - "gd-stage-188" + "gd-stage-228" ], "SUBSTACK": [ 2, - "gd-stage-189" + "gd-stage-229" ], "SUBSTACK2": [ 2, - "gd-stage-191" + "gd-stage-231" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-188": { + "gd-stage-228": { "opcode": "operator_gt", "next": null, - "parent": "gd-stage-187", + "parent": "gd-stage-227", "inputs": { "OPERAND1": [ 3, @@ -6883,10 +8938,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-189": { + "gd-stage-229": { "opcode": "data_setvariableto", - "next": "gd-stage-190", - "parent": "gd-stage-187", + "next": "gd-stage-230", + "parent": "gd-stage-227", "inputs": { "VALUE": [ 1, @@ -6905,10 +8960,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-190": { + "gd-stage-230": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-189", + "parent": "gd-stage-229", "inputs": { "director-destination": [ 1, @@ -6936,10 +8991,10 @@ "warp": "false" } }, - "gd-stage-191": { + "gd-stage-231": { "opcode": "data_setvariableto", - "next": "gd-stage-192", - "parent": "gd-stage-187", + "next": "gd-stage-232", + "parent": "gd-stage-227", "inputs": { "VALUE": [ 1, @@ -6958,10 +9013,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-192": { + "gd-stage-232": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-191", + "parent": "gd-stage-231", "inputs": { "director-destination": [ 1, @@ -6989,28 +9044,28 @@ "warp": "false" } }, - "gd-stage-193": { + "gd-stage-233": { "opcode": "control_if", "next": null, - "parent": "gd-stage-186", + "parent": "gd-stage-226", "inputs": { "CONDITION": [ 2, - "gd-stage-194" + "gd-stage-234" ], "SUBSTACK": [ 2, - "gd-stage-187" + "gd-stage-227" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-194": { + "gd-stage-234": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-193", + "parent": "gd-stage-233", "inputs": { "OPERAND1": [ 3, @@ -7036,9 +9091,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-195": { + "gd-stage-235": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-200", + "next": "gd-stage-240", "parent": null, "inputs": {}, "fields": { @@ -7052,10 +9107,10 @@ "x": 20, "y": 2420 }, - "gd-stage-196": { + "gd-stage-236": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-197", + "parent": "gd-stage-237", "inputs": { "INDEX": [ 1, @@ -7074,10 +9129,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-197": { + "gd-stage-237": { "opcode": "operator_gt", "next": null, - "parent": "gd-stage-198", + "parent": "gd-stage-238", "inputs": { "OPERAND1": [ 3, @@ -7093,21 +9148,21 @@ ], "OPERAND2": [ 2, - "gd-stage-196" + "gd-stage-236" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-198": { + "gd-stage-238": { "opcode": "data_setvariableto", - "next": "gd-stage-199", - "parent": "gd-stage-200", + "next": "gd-stage-239", + "parent": "gd-stage-240", "inputs": { "VALUE": [ 3, - "gd-stage-197", + "gd-stage-237", [ 10, "" @@ -7123,10 +9178,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-199": { + "gd-stage-239": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-198", + "parent": "gd-stage-238", "inputs": { "director-destination": [ 1, @@ -7154,28 +9209,28 @@ "warp": "false" } }, - "gd-stage-200": { + "gd-stage-240": { "opcode": "control_if", "next": null, - "parent": "gd-stage-195", + "parent": "gd-stage-235", "inputs": { "CONDITION": [ 2, - "gd-stage-201" + "gd-stage-241" ], "SUBSTACK": [ 2, - "gd-stage-198" + "gd-stage-238" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-201": { + "gd-stage-241": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-200", + "parent": "gd-stage-240", "inputs": { "OPERAND1": [ 3, @@ -7201,9 +9256,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-202": { + "gd-stage-242": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-210", + "next": "gd-stage-250", "parent": null, "inputs": {}, "fields": { @@ -7217,10 +9272,10 @@ "x": 20, "y": 2570 }, - "gd-stage-203": { + "gd-stage-243": { "opcode": "sound_sounds_menu", "next": null, - "parent": "gd-stage-204", + "parent": "gd-stage-244", "inputs": {}, "fields": { "SOUND_MENU": [ @@ -7231,56 +9286,56 @@ "shadow": true, "topLevel": false }, - "gd-stage-204": { + "gd-stage-244": { "opcode": "sound_playuntildone", - "next": "gd-stage-205", - "parent": "gd-stage-210", + "next": "gd-stage-245", + "parent": "gd-stage-250", "inputs": { "SOUND_MENU": [ 1, - "gd-stage-203" + "gd-stage-243" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-205": { + "gd-stage-245": { "opcode": "control_repeat_until", "next": null, - "parent": "gd-stage-204", + "parent": "gd-stage-244", "inputs": { "CONDITION": [ 2, - "gd-stage-206" + "gd-stage-246" ], "SUBSTACK": [ 2, - "gd-stage-209" + "gd-stage-249" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-206": { + "gd-stage-246": { "opcode": "operator_not", "next": null, - "parent": "gd-stage-205", + "parent": "gd-stage-245", "inputs": { "OPERAND": [ 2, - "gd-stage-207" + "gd-stage-247" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-207": { + "gd-stage-247": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-206", + "parent": "gd-stage-246", "inputs": { "OPERAND1": [ 3, @@ -7306,10 +9361,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-208": { + "gd-stage-248": { "opcode": "sound_sounds_menu", "next": null, - "parent": "gd-stage-209", + "parent": "gd-stage-249", "inputs": {}, "fields": { "SOUND_MENU": [ @@ -7320,42 +9375,42 @@ "shadow": true, "topLevel": false }, - "gd-stage-209": { + "gd-stage-249": { "opcode": "sound_playuntildone", "next": null, - "parent": "gd-stage-205", + "parent": "gd-stage-245", "inputs": { "SOUND_MENU": [ 1, - "gd-stage-208" + "gd-stage-248" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-210": { + "gd-stage-250": { "opcode": "control_if", "next": null, - "parent": "gd-stage-202", + "parent": "gd-stage-242", "inputs": { "CONDITION": [ 2, - "gd-stage-211" + "gd-stage-251" ], "SUBSTACK": [ 2, - "gd-stage-204" + "gd-stage-244" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-211": { + "gd-stage-251": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-210", + "parent": "gd-stage-250", "inputs": { "OPERAND1": [ 3, @@ -7381,9 +9436,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-212": { + "gd-stage-252": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-218", + "next": "gd-stage-258", "parent": null, "inputs": {}, "fields": { @@ -7397,42 +9452,42 @@ "x": 20, "y": 2720 }, - "gd-stage-213": { + "gd-stage-253": { "opcode": "control_repeat_until", "next": null, - "parent": "gd-stage-218", + "parent": "gd-stage-258", "inputs": { "CONDITION": [ 2, - "gd-stage-214" + "gd-stage-254" ], "SUBSTACK": [ 2, - "gd-stage-216" + "gd-stage-256" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-214": { + "gd-stage-254": { "opcode": "operator_not", "next": null, - "parent": "gd-stage-213", + "parent": "gd-stage-253", "inputs": { "OPERAND": [ 2, - "gd-stage-215" + "gd-stage-255" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-215": { + "gd-stage-255": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-214", + "parent": "gd-stage-254", "inputs": { "OPERAND1": [ 3, @@ -7458,10 +9513,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-216": { + "gd-stage-256": { "opcode": "procedures_call", - "next": "gd-stage-217", - "parent": "gd-stage-213", + "next": "gd-stage-257", + "parent": "gd-stage-253", "inputs": {}, "fields": {}, "shadow": false, @@ -7474,10 +9529,10 @@ "warp": "true" } }, - "gd-stage-217": { + "gd-stage-257": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-216", + "parent": "gd-stage-256", "inputs": {}, "fields": {}, "shadow": false, @@ -7490,28 +9545,28 @@ "warp": "true" } }, - "gd-stage-218": { + "gd-stage-258": { "opcode": "control_if", "next": null, - "parent": "gd-stage-212", + "parent": "gd-stage-252", "inputs": { "CONDITION": [ 2, - "gd-stage-219" + "gd-stage-259" ], "SUBSTACK": [ 2, - "gd-stage-213" + "gd-stage-253" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-219": { + "gd-stage-259": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-218", + "parent": "gd-stage-258", "inputs": { "OPERAND1": [ 3, @@ -7537,9 +9592,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-220": { + "gd-stage-260": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-224", + "next": "gd-stage-264", "parent": null, "inputs": {}, "fields": { @@ -7553,28 +9608,28 @@ "x": 20, "y": 2870 }, - "gd-stage-221": { + "gd-stage-261": { "opcode": "control_if", "next": null, - "parent": "gd-stage-233", + "parent": "gd-stage-273", "inputs": { "CONDITION": [ 2, - "gd-stage-222" + "gd-stage-262" ], "SUBSTACK": [ 2, - "gd-stage-223" + "gd-stage-263" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-222": { + "gd-stage-262": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-221", + "parent": "gd-stage-261", "inputs": { "OPERAND1": [ 3, @@ -7600,10 +9655,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-223": { + "gd-stage-263": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-221", + "parent": "gd-stage-261", "inputs": { "VALUE": [ 1, @@ -7622,10 +9677,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-224": { + "gd-stage-264": { "opcode": "procedures_call", - "next": "gd-stage-233", - "parent": "gd-stage-220", + "next": "gd-stage-273", + "parent": "gd-stage-260", "inputs": {}, "fields": {}, "shadow": false, @@ -7638,10 +9693,10 @@ "warp": "true" } }, - "gd-stage-225": { + "gd-stage-265": { "opcode": "data_setvariableto", - "next": "gd-stage-226", - "parent": "gd-stage-233", + "next": "gd-stage-266", + "parent": "gd-stage-273", "inputs": { "VALUE": [ 1, @@ -7660,10 +9715,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-226": { + "gd-stage-266": { "opcode": "data_setvariableto", - "next": "gd-stage-227", - "parent": "gd-stage-225", + "next": "gd-stage-267", + "parent": "gd-stage-265", "inputs": { "VALUE": [ 1, @@ -7682,10 +9737,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-227": { + "gd-stage-267": { "opcode": "data_setvariableto", - "next": "gd-stage-228", - "parent": "gd-stage-226", + "next": "gd-stage-268", + "parent": "gd-stage-266", "inputs": { "VALUE": [ 1, @@ -7704,10 +9759,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-228": { + "gd-stage-268": { "opcode": "data_setvariableto", - "next": "gd-stage-230", - "parent": "gd-stage-227", + "next": "gd-stage-270", + "parent": "gd-stage-267", "inputs": { "VALUE": [ 1, @@ -7726,10 +9781,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-229": { + "gd-stage-269": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-230", + "parent": "gd-stage-270", "inputs": { "INDEX": [ 1, @@ -7748,14 +9803,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-230": { + "gd-stage-270": { "opcode": "data_setvariableto", - "next": "gd-stage-232", - "parent": "gd-stage-228", + "next": "gd-stage-272", + "parent": "gd-stage-268", "inputs": { "VALUE": [ 3, - "gd-stage-229", + "gd-stage-269", [ 10, "" @@ -7771,10 +9826,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-231": { + "gd-stage-271": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-232", + "parent": "gd-stage-272", "inputs": { "INDEX": [ 1, @@ -7793,14 +9848,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-232": { + "gd-stage-272": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-230", + "parent": "gd-stage-270", "inputs": { "VALUE": [ 3, - "gd-stage-231", + "gd-stage-271", [ 10, "" @@ -7816,46 +9871,46 @@ "shadow": false, "topLevel": false }, - "gd-stage-233": { + "gd-stage-273": { "opcode": "control_if", - "next": "gd-stage-221", - "parent": "gd-stage-224", + "next": "gd-stage-261", + "parent": "gd-stage-264", "inputs": { "CONDITION": [ 2, - "gd-stage-234" + "gd-stage-274" ], "SUBSTACK": [ 2, - "gd-stage-225" + "gd-stage-265" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-234": { + "gd-stage-274": { "opcode": "operator_or", "next": null, - "parent": "gd-stage-233", + "parent": "gd-stage-273", "inputs": { "OPERAND1": [ 2, - "gd-stage-235" + "gd-stage-275" ], "OPERAND2": [ 2, - "gd-stage-236" + "gd-stage-276" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-235": { + "gd-stage-275": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-234", + "parent": "gd-stage-274", "inputs": { "OPERAND1": [ 3, @@ -7881,10 +9936,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-236": { + "gd-stage-276": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-234", + "parent": "gd-stage-274", "inputs": { "OPERAND1": [ 3, @@ -7910,9 +9965,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-237": { + "gd-stage-277": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-246", + "next": "gd-stage-286", "parent": null, "inputs": {}, "fields": { @@ -7926,10 +9981,10 @@ "x": 20, "y": 3020 }, - "gd-stage-238": { + "gd-stage-278": { "opcode": "data_setvariableto", - "next": "gd-stage-239", - "parent": "gd-stage-246", + "next": "gd-stage-279", + "parent": "gd-stage-286", "inputs": { "VALUE": [ 1, @@ -7948,10 +10003,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-239": { + "gd-stage-279": { "opcode": "data_setvariableto", - "next": "gd-stage-240", - "parent": "gd-stage-238", + "next": "gd-stage-280", + "parent": "gd-stage-278", "inputs": { "VALUE": [ 1, @@ -7970,10 +10025,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-240": { + "gd-stage-280": { "opcode": "data_setvariableto", - "next": "gd-stage-242", - "parent": "gd-stage-239", + "next": "gd-stage-282", + "parent": "gd-stage-279", "inputs": { "VALUE": [ 1, @@ -7992,10 +10047,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-241": { + "gd-stage-281": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-242", + "parent": "gd-stage-282", "inputs": { "INDEX": [ 3, @@ -8019,14 +10074,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-242": { + "gd-stage-282": { "opcode": "data_setvariableto", - "next": "gd-stage-244", - "parent": "gd-stage-240", + "next": "gd-stage-284", + "parent": "gd-stage-280", "inputs": { "VALUE": [ 3, - "gd-stage-241", + "gd-stage-281", [ 10, "" @@ -8042,10 +10097,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-243": { + "gd-stage-283": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-244", + "parent": "gd-stage-284", "inputs": { "INDEX": [ 3, @@ -8069,14 +10124,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-244": { + "gd-stage-284": { "opcode": "data_setvariableto", - "next": "gd-stage-245", - "parent": "gd-stage-242", + "next": "gd-stage-285", + "parent": "gd-stage-282", "inputs": { "VALUE": [ 3, - "gd-stage-243", + "gd-stage-283", [ 10, "" @@ -8092,10 +10147,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-245": { + "gd-stage-285": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-244", + "parent": "gd-stage-284", "inputs": { "VALUE": [ 1, @@ -8114,46 +10169,46 @@ "shadow": false, "topLevel": false }, - "gd-stage-246": { + "gd-stage-286": { "opcode": "control_if", - "next": "gd-stage-250", - "parent": "gd-stage-237", + "next": "gd-stage-290", + "parent": "gd-stage-277", "inputs": { "CONDITION": [ 2, - "gd-stage-247" + "gd-stage-287" ], "SUBSTACK": [ 2, - "gd-stage-238" + "gd-stage-278" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-247": { + "gd-stage-287": { "opcode": "operator_or", "next": null, - "parent": "gd-stage-246", + "parent": "gd-stage-286", "inputs": { "OPERAND1": [ 2, - "gd-stage-248" + "gd-stage-288" ], "OPERAND2": [ 2, - "gd-stage-249" + "gd-stage-289" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-248": { + "gd-stage-288": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-247", + "parent": "gd-stage-287", "inputs": { "OPERAND1": [ 3, @@ -8179,10 +10234,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-249": { + "gd-stage-289": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-247", + "parent": "gd-stage-287", "inputs": { "OPERAND1": [ 3, @@ -8208,28 +10263,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-250": { + "gd-stage-290": { "opcode": "control_if", "next": null, - "parent": "gd-stage-246", + "parent": "gd-stage-286", "inputs": { "CONDITION": [ 2, - "gd-stage-251" + "gd-stage-291" ], "SUBSTACK": [ 2, - "gd-stage-259" + "gd-stage-299" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-251": { + "gd-stage-291": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-250", + "parent": "gd-stage-290", "inputs": { "OPERAND1": [ 3, @@ -8255,28 +10310,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-252": { + "gd-stage-292": { "opcode": "operator_and", "next": null, - "parent": "gd-stage-259", + "parent": "gd-stage-299", "inputs": { "OPERAND1": [ 2, - "gd-stage-253" + "gd-stage-293" ], "OPERAND2": [ 2, - "gd-stage-254" + "gd-stage-294" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-253": { + "gd-stage-293": { "opcode": "operator_gt", "next": null, - "parent": "gd-stage-252", + "parent": "gd-stage-292", "inputs": { "OPERAND1": [ 3, @@ -8302,10 +10357,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-254": { + "gd-stage-294": { "opcode": "operator_gt", "next": null, - "parent": "gd-stage-252", + "parent": "gd-stage-292", "inputs": { "OPERAND1": [ 1, @@ -8331,32 +10386,32 @@ "shadow": false, "topLevel": false }, - "gd-stage-255": { + "gd-stage-295": { "opcode": "control_if_else", "next": null, - "parent": "gd-stage-259", + "parent": "gd-stage-299", "inputs": { "CONDITION": [ 2, - "gd-stage-256" + "gd-stage-296" ], "SUBSTACK": [ 2, - "gd-stage-257" + "gd-stage-297" ], "SUBSTACK2": [ 2, - "gd-stage-258" + "gd-stage-298" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-256": { + "gd-stage-296": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-255", + "parent": "gd-stage-295", "inputs": { "OPERAND1": [ 3, @@ -8382,10 +10437,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-257": { + "gd-stage-297": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-255", + "parent": "gd-stage-295", "inputs": { "VALUE": [ 1, @@ -8404,10 +10459,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-258": { + "gd-stage-298": { "opcode": "data_changevariableby", "next": null, - "parent": "gd-stage-255", + "parent": "gd-stage-295", "inputs": { "VALUE": [ 1, @@ -8426,28 +10481,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-259": { + "gd-stage-299": { "opcode": "control_if", - "next": "gd-stage-260", - "parent": "gd-stage-250", + "next": "gd-stage-300", + "parent": "gd-stage-290", "inputs": { "CONDITION": [ 2, - "gd-stage-252" + "gd-stage-292" ], "SUBSTACK": [ 2, - "gd-stage-255" + "gd-stage-295" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-260": { + "gd-stage-300": { "opcode": "data_setvariableto", - "next": "gd-stage-261", - "parent": "gd-stage-259", + "next": "gd-stage-301", + "parent": "gd-stage-299", "inputs": { "VALUE": [ 1, @@ -8466,10 +10521,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-261": { + "gd-stage-301": { "opcode": "data_setvariableto", - "next": "gd-stage-263", - "parent": "gd-stage-260", + "next": "gd-stage-303", + "parent": "gd-stage-300", "inputs": { "VALUE": [ 1, @@ -8488,10 +10543,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-262": { + "gd-stage-302": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-263", + "parent": "gd-stage-303", "inputs": { "INDEX": [ 3, @@ -8515,14 +10570,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-263": { + "gd-stage-303": { "opcode": "data_setvariableto", - "next": "gd-stage-265", - "parent": "gd-stage-261", + "next": "gd-stage-305", + "parent": "gd-stage-301", "inputs": { "VALUE": [ 3, - "gd-stage-262", + "gd-stage-302", [ 10, "" @@ -8538,10 +10593,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-264": { + "gd-stage-304": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-265", + "parent": "gd-stage-305", "inputs": { "INDEX": [ 3, @@ -8565,14 +10620,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-265": { + "gd-stage-305": { "opcode": "data_setvariableto", - "next": "gd-stage-266", - "parent": "gd-stage-263", + "next": "gd-stage-306", + "parent": "gd-stage-303", "inputs": { "VALUE": [ 3, - "gd-stage-264", + "gd-stage-304", [ 10, "" @@ -8588,10 +10643,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-266": { + "gd-stage-306": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-265", + "parent": "gd-stage-305", "inputs": { "VALUE": [ 1, @@ -8609,6 +10664,182 @@ }, "shadow": false, "topLevel": false + }, + "gd-stage-307": { + "opcode": "event_whenbroadcastreceived", + "next": "gd-stage-311", + "parent": null, + "inputs": {}, + "fields": { + "BROADCAST_OPTION": [ + "director reset", + "broadcastMsgId-director-reset" + ] + }, + "shadow": false, + "topLevel": true, + "x": 20, + "y": 3170 + }, + "gd-stage-308": { + "opcode": "data_setvariableto", + "next": "gd-stage-309", + "parent": "gd-stage-311", + "inputs": { + "VALUE": [ + 1, + [ + 4, + 0 + ] + ] + }, + "fields": { + "VARIABLE": [ + "ai level", + "difficulty-ai-level" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-309": { + "opcode": "data_setvariableto", + "next": "gd-stage-310", + "parent": "gd-stage-308", + "inputs": { + "VALUE": [ + 1, + [ + 4, + 0 + ] + ] + }, + "fields": { + "VARIABLE": [ + "formation count", + "formation-count" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-310": { + "opcode": "data_setvariableto", + "next": null, + "parent": "gd-stage-309", + "inputs": { + "VALUE": [ + 1, + [ + 4, + 0 + ] + ] + }, + "fields": { + "VARIABLE": [ + "formation type offset", + "formation-type-offset" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-311": { + "opcode": "control_if", + "next": null, + "parent": "gd-stage-307", + "inputs": { + "CONDITION": [ + 2, + "gd-stage-312" + ], + "SUBSTACK": [ + 2, + "gd-stage-308" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-312": { + "opcode": "operator_or", + "next": null, + "parent": "gd-stage-311", + "inputs": { + "OPERAND1": [ + 2, + "gd-stage-313" + ], + "OPERAND2": [ + 2, + "gd-stage-314" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-313": { + "opcode": "operator_equals", + "next": null, + "parent": "gd-stage-312", + "inputs": { + "OPERAND1": [ + 3, + [ + 12, + "reset scope", + "game-director-reset-scope" + ], + [ + 10, + "" + ] + ], + "OPERAND2": [ + 1, + [ + 10, + "cold-start" + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-314": { + "opcode": "operator_equals", + "next": null, + "parent": "gd-stage-312", + "inputs": { + "OPERAND1": [ + 3, + [ + 12, + "reset scope", + "game-director-reset-scope" + ], + [ + 10, + "" + ] + ], + "OPERAND2": [ + 1, + [ + 10, + "new-game" + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false } }, "comments": {}, diff --git a/src/xevious/runtime_identifiers.json b/src/xevious/runtime_identifiers.json index 3bae1dc..5f0ecdd 100644 --- a/src/xevious/runtime_identifiers.json +++ b/src/xevious/runtime_identifiers.json @@ -19,6 +19,11 @@ "name": "area progress", "scope": "Stage" }, + "area-schedule-arg": { + "kind": "list", + "name": "schedule arg", + "scope": "Stage" + }, "area-schedule-cursor": { "kind": "variable", "name": "schedule cursor", @@ -84,6 +89,16 @@ "name": "bullet cursor", "scope": "Stage" }, + "difficulty-ai-level": { + "kind": "variable", + "name": "ai level", + "scope": "Stage" + }, + "difficulty-increment": { + "kind": "list", + "name": "difficulty increment", + "scope": "Stage" + }, "eco-award-value": { "kind": "variable", "name": "award value", @@ -149,6 +164,31 @@ "name": "value table", "scope": "Stage" }, + "formation-count": { + "kind": "variable", + "name": "formation count", + "scope": "Stage" + }, + "formation-count-table": { + "kind": "list", + "name": "formation count table", + "scope": "Stage" + }, + "formation-index": { + "kind": "variable", + "name": "formation index", + "scope": "Stage" + }, + "formation-type-offset": { + "kind": "variable", + "name": "formation type offset", + "scope": "Stage" + }, + "formation-type-offset-table": { + "kind": "list", + "name": "formation type offset table", + "scope": "Stage" + }, "game-director-allowed-transitions": { "kind": "list", "name": "allowed transitions", diff --git a/tests/test_scratch_project.py b/tests/test_scratch_project.py index d3550e6..6e35c69 100644 --- a/tests/test_scratch_project.py +++ b/tests/test_scratch_project.py @@ -890,6 +890,8 @@ def test_game_director_has_one_stage_owned_transition_path(self) -> None: # ECO-04 best-five verdict: Stage-computed only (never a sprite write, unlike # `award value`) — added to the write-forbid set below too. "qualified", + # FORM-01 transient formation-lookup register (overwritten on every selection). + "formation index", } # ECO economy state — Stage-written, HUD reads only. Held in its own category and # enforced Stage-only-write below (a HUD sprite writing `score` is the bug this guards). @@ -911,14 +913,32 @@ def test_game_director_has_one_stage_owned_transition_path(self) -> None: "schedule cursor", "schedule fired", } + # DIF-01/FORM-01 difficulty-director state — Stage-written, sprite-read, write-forbidden + # (like area/economy state, NOT machinery): the accumulating AI level and the incoming + # wave's size + type-table offset. `formation index` is the transient lookup register and + # is machinery, above. + difficulty_state_names = { + "ai level", + "formation count", + "formation type offset", + } self.assertTrue(director_state_names.isdisjoint(machinery_names)) self.assertTrue(economy_names.isdisjoint(machinery_names | director_state_names)) self.assertTrue( area_state_names.isdisjoint(machinery_names | director_state_names | economy_names) ) + self.assertTrue( + difficulty_state_names.isdisjoint( + machinery_names | director_state_names | economy_names | area_state_names + ) + ) stage_variable_names = {name for name, _value in stage["variables"].values()} self.assertEqual( - director_state_names | machinery_names | economy_names | area_state_names, + director_state_names + | machinery_names + | economy_names + | area_state_names + | difficulty_state_names, stage_variable_names, ) self.assertEqual( @@ -954,8 +974,12 @@ def test_game_director_has_one_stage_owned_transition_path(self) -> None: "schedule handler", "schedule trigger row", "schedule payload", + "schedule arg", "area schedule start", "area schedule end", + "difficulty increment", + "formation count table", + "formation type offset table", }, stage_list_names, ) @@ -1021,6 +1045,10 @@ def _proccode(definition: dict) -> str: director.TERRAIN_COLUMN_ID, director.SCHEDULE_CURSOR_ID, director.SCHEDULE_FIRED_ID, + # DIF-01/FORM-01 difficulty-director state: Stage-only-written. + director.AI_LEVEL_ID, + director.FORMATION_COUNT_ID, + director.FORMATION_TYPE_OFFSET_ID, } # Read-only reference tables: ingested, hash-pinned authority data no sprite may # mutate (the mutable slot lists are deliberately excluded — allocators write those). @@ -1036,8 +1064,12 @@ def _proccode(definition: dict) -> str: director.SCHEDULE_HANDLER_ID, director.SCHEDULE_TRIGGER_ROW_ID, director.SCHEDULE_PAYLOAD_ID, + director.SCHEDULE_ARG_ID, director.AREA_SCHEDULE_START_ID, director.AREA_SCHEDULE_END_ID, + director.DIFFICULTY_INCREMENT_ID, + director.FORMATION_COUNT_TABLE_ID, + director.FORMATION_TYPE_OFFSET_TABLE_ID, } list_write_opcodes = { "data_addtolist", @@ -2783,13 +2815,14 @@ def break_checkpoint_high(p): @staticmethod def _area02_failures(project: dict) -> set: - """AREA-02/AREA-03 area object scheduler: all 16 normal areas flattened into three parallel - columns (each area = its records + one materialized sentinel), partitioned by two 16-entry - index lists into contiguous 1-based inclusive per-area spans; an ordered consume loop guarded - by `cursor > end` OR `trigger != scroll row`, an EMPTY per-record dispatch seam, and the - observable that advances the cursor and counts fires. Structure only; the per-area JSON-faithful - content is the round-trip golden's job (test_spec_docs), and the dynamic fire-once/in-order - behaviour is exercised by the scratch-vm harness and the operator playtest.""" + """AREA-02/AREA-03 area object scheduler: all 16 normal areas flattened into four parallel + columns (handler, trigger row, payload, and DIF-01/FORM-01's runtime `arg`; each area = its + records + one materialized sentinel), partitioned by two 16-entry index lists into contiguous + 1-based inclusive per-area spans; an ordered consume loop guarded by `cursor > end` OR + `trigger != scroll row`, a per-record dispatch that now carries the DIF-01/FORM-01 handler + branches, and the observable that advances the cursor and counts fires. Structure only; the + per-area JSON-faithful content is the round-trip golden's job (test_spec_docs), and the dynamic + fire-once/in-order and dispatch behaviour is the scratch-vm harness and the operator playtest's.""" failures = set() stage = next(t for t in project["targets"] if t["isStage"]) blocks = stage["blocks"] @@ -2809,6 +2842,7 @@ def refs_var(spec, var_id): handlers = by_name.get("schedule handler", []) rows = by_name.get("schedule trigger row", []) payloads = by_name.get("schedule payload", []) + args = by_name.get("schedule arg", []) starts = by_name.get("area schedule start", []) ends = by_name.get("area schedule end", []) total = len(handlers) @@ -2820,7 +2854,13 @@ def refs_var(spec, var_id): and all(starts[i] == ends[i - 1] + 1 for i in range(1, director.AREA_MAX)) and all(starts[i] <= ends[i] for i in range(director.AREA_MAX)) ) - if not (total > 0 and len(rows) == total and len(payloads) == total and contiguous): + if not ( + total > 0 + and len(rows) == total + and len(payloads) == total + and len(args) == total # DIF-01/FORM-01: the 4th parallel column stays in lockstep + and contiguous + ): failures.add("schedule-lists-length") # EVERY area's slice ends in the materialized sentinel (handler 'sentinel', trigger 0x0D) — a @@ -2878,9 +2918,33 @@ def body_ids(loop_id): ): failures.add("consume-counts-fired") - # the per-record dispatch is an EMPTY seam: the body is only the two counters, no handler. - if any(blocks[x]["opcode"] != "data_changevariableby" for x in ids): - failures.add("empty-dispatch") + # DIF-01 / FORM-01: the per-record dispatch is now WIRED — the loop body carries at least one + # handler-keyed branch (a control_if whose condition reads the `schedule handler` column). + # The spawn/boss handlers stay unwired (slice 8); the dispatched BEHAVIOUR is the harness and + # model fixtures' job, not this structural guard — this only catches the dispatch going missing. + def reads_handler_list(bid: str, seen: set) -> bool: + if bid in seen or bid not in blocks: + return False + seen.add(bid) + blk = blocks[bid] + if ( + blk["opcode"] == "data_itemoflist" + and blk["fields"].get("LIST", [None, None])[1] == director.SCHEDULE_HANDLER_ID + ): + return True + return any( + isinstance(v, list) and len(v) > 1 and isinstance(v[1], str) and reads_handler_list(v[1], seen) + for v in blk["inputs"].values() + ) + + if not any( + blocks[x]["opcode"] == "control_if" + and isinstance(blocks[x]["inputs"].get("CONDITION"), list) + and len(blocks[x]["inputs"]["CONDITION"]) > 1 + and reads_handler_list(blocks[x]["inputs"]["CONDITION"][1], set()) + for x in ids + ): + failures.add("dispatch-present") # stop condition: operator_or( gt(cursor, end), not( eq(trigger, scroll row) ) ). def subtree(bid, acc): @@ -2973,22 +3037,21 @@ def break_fired_count(p): ) blk["inputs"]["VALUE"] = [1, [4, 0]] - def break_empty_dispatch(p): + def break_missing_dispatch(p): + # strip the DIF-01/FORM-01 handler branches from the loop body, leaving only the two + # counters — regressing to the old empty seam; the dispatch-present guard must catch it. s = stage_of(p) + b = s["blocks"] loop_id, ids = consume_loop(p) - # inject a bogus per-record dispatch block at the head of the loop body. - injected = "gd-stage-injected-dispatch" - s["blocks"][injected] = { - "opcode": "control_if", - "next": ids[0], - "parent": loop_id, - "inputs": {}, - "fields": {}, - "shadow": False, - "topLevel": False, - } - s["blocks"][ids[0]]["parent"] = injected - s["blocks"][loop_id]["inputs"]["SUBSTACK"] = [2, injected] + counters = [ + x for x in ids if b[x]["opcode"] == "data_changevariableby" + ] + b[loop_id]["inputs"]["SUBSTACK"] = [2, counters[0]] + b[counters[0]]["parent"] = loop_id + for left, right in zip(counters, counters[1:]): + b[left]["next"] = right + b[right]["parent"] = left + b[counters[-1]]["next"] = None def break_stop_condition(p): s = stage_of(p) @@ -3014,7 +3077,7 @@ def break_stop_condition(p): ("schedule-sentinel", break_sentinel), ("consume-advances-cursor", break_cursor_advance), ("consume-counts-fired", break_fired_count), - ("empty-dispatch", break_empty_dispatch), + ("dispatch-present", break_missing_dispatch), ("consume-stop-condition", break_stop_condition), ] for label, corrupt in cases: @@ -4360,7 +4423,7 @@ def test_full_repository_verification(self) -> None: original_hash, ) self.assertEqual( - "4d7c2dfd15618a5f835bf79fe3592a0719e013f5625cf891f69ce77323ba7394", + "89b9b90e8730d0b85a2f83b6fe612a86dc0be2e1ff21184e9ba43909412af57a", build_hash, ) diff --git a/tests/test_spec_docs.py b/tests/test_spec_docs.py index 3ca312f..53f80fc 100644 --- a/tests/test_spec_docs.py +++ b/tests/test_spec_docs.py @@ -14,6 +14,7 @@ import json import math import re +import sys import unittest from pathlib import Path @@ -21,6 +22,9 @@ SPEC = ROOT / "docs" / "spec" DATA = SPEC / "data" +sys.path.insert(0, str(ROOT / "tools")) +import game_director as director # noqa: E402 + def load_extractor(): spec = importlib.util.spec_from_file_location( @@ -497,9 +501,23 @@ def test_all_area_schedules_round_trip_from_json(self): handlers = by_name["schedule handler"] rows = by_name["schedule trigger row"] payloads = by_name["schedule payload"] + args = by_name["schedule arg"] gen_start = by_name["area schedule start"] gen_end = by_name["area schedule end"] + # DIF-01/FORM-01: the runtime `arg` scalar, re-decoded INDEPENDENTLY here from each source + # record (set-formation offset / fire-mask byte / ground-stop row; 0 otherwise), so a + # mis-populated column fails here rather than shipping silently. + def expected_arg(record): + handler, params = record["handler"], record.get("params", {}) + if handler == "set_flying_formation": + return params["formation_offset"] + if handler.startswith("fire_mask_"): + return params["mask"] + if handler == "ground_stop_firing_row": + return params["row"] + return 0 + areas = json.loads((DATA / "area-schedules.json").read_text())["areas"] by_area = {a["area"]: a for a in areas} self.assertEqual(16, len(areas)) @@ -514,9 +532,9 @@ def test_all_area_schedules_round_trip_from_json(self): cursor += stride self.assertEqual(expected_start, gen_start, "area schedule start offsets") self.assertEqual(expected_end, gen_end, "area schedule end offsets") - # the three columns are exactly as long as the last span says. + # the four parallel columns are exactly as long as the last span says. self.assertEqual(cursor - 1, len(handlers)) - self.assertEqual({len(handlers), len(rows)}, {len(payloads)}) + self.assertEqual({len(handlers)}, {len(rows), len(payloads), len(args)}) # each area's flattened window matches its SOURCE records + materialized sentinel. for area_number in range(1, 17): @@ -533,11 +551,110 @@ def test_all_area_schedules_round_trip_from_json(self): json.loads(payloads[idx]), f"area {area_number} payload {j}", ) + self.assertEqual(expected_arg(record), args[idx], f"area {area_number} arg {j}") # this area's window terminates in the materialized sentinel (its scalar end_sentinel). end = expected_end[area_number - 1] # 1-based, inclusive self.assertEqual("sentinel", handlers[end - 1], f"area {area_number} sentinel handler") self.assertEqual(area["end_sentinel"], rows[end - 1], f"area {area_number} sentinel row") self.assertEqual("", payloads[end - 1], f"area {area_number} sentinel payload") + self.assertEqual(0, args[end - 1], f"area {area_number} sentinel arg") + + +class DifficultyAndFormations(unittest.TestCase): + """DIF-01 / FORM-01: the difficulty AI level and normal flying formations, modelled over the + COMMITTED data independently of the generator (the engine half of the acceptance criteria). The + RULE is re-implemented here, not read back from the dispatch, so a wrong index formula fails + rather than laundering itself; only the build's DIP-index and numeric constants come from the + generator.""" + + def _stage_lists(self): + project = json.loads(PROJECT_JSON.read_text()) + stage = next(t for t in project["targets"] if t["isStage"]) + return {value[0]: value[1] for value in stage["lists"].values()} + + def _formation_table(self): + entries = json.loads((DATA / "formations.json").read_text())["formation_table"]["entries"] + ordered = sorted(entries, key=lambda e: e["index"]) + counts = [e["enemy_count"] for e in ordered] + offsets = [e["type_table_offset"] for e in ordered] + return ordered, counts, offsets + + def test_baked_tables_match_committed_data(self): + # The generator bakes difficulty.json / formations.json faithfully into the Stage lists. + lists = self._stage_lists() + diff = json.loads((DATA / "difficulty.json").read_text())["difficulty_tbl"]["values"] + self.assertEqual([2, 0, 6, 16], diff) # arcade increments, sanity-anchored + self.assertEqual(diff, lists["difficulty increment"]) + ordered, counts, offsets = self._formation_table() + self.assertEqual( + list(range(director.FORMATION_MIN_INDEX, director.FORMATION_MIN_INDEX + director.FORMATION_TABLE_LEN)), + [e["index"] for e in ordered], + "formation table domain -32..127", + ) + self.assertEqual(counts, lists["formation count table"]) + self.assertEqual(offsets, lists["formation type offset table"]) + + def test_formation_lookup_reproduces_committed_table(self): + # FORM-01 selection: slot = index - MIN (0-based into the two ordered lists) reproduces every + # committed (count, type-offset) pair across the whole domain. + ordered, counts, offsets = self._formation_table() + by_index = {e["index"]: (e["enemy_count"], e["type_table_offset"]) for e in ordered} + for index in range(director.FORMATION_MIN_INDEX, director.FORMATION_MIN_INDEX + director.FORMATION_TABLE_LEN): + slot = index - director.FORMATION_MIN_INDEX + self.assertEqual(by_index[index], (counts[slot], offsets[slot]), f"index {index}") + + def test_ai_level_fold_back(self): + # DIF-01 raise math: ai += increment; fold ONCE at >= 0x80 by subtracting 0x40, so the level + # (which the raise re-select uses as the formation index) stays below 0x80. + inc = json.loads((DATA / "difficulty.json").read_text())["difficulty_tbl"]["values"][ + director.DIFFICULTY_DIP_INDEX + ] + + def raise_once(ai): + ai += inc + if ai >= director.AI_LEVEL_FOLD_THRESHOLD: + ai -= director.AI_LEVEL_FOLD_SUBTRACT + return ai + + self.assertEqual(inc, raise_once(0)) + self.assertEqual(64, raise_once(126)) # 128 -> fold -> 64 + self.assertEqual(65, raise_once(127)) # 129 -> fold -> 65 + self.assertLess(raise_once(127), director.AI_LEVEL_FOLD_THRESHOLD) + + def test_formation_index_in_domain_over_committed_schedules(self): + # FORM-01 / DIF-01 range proof: walk the committed schedules in the accelerated 1..16 then + # 7..16 loop order, tracking the AI level through raises (fold-back) and picking the formation + # index exactly as the emitted dispatch does — set-formation: the record offset; raise: the + # folded AI level. Assert EVERY index lands in the table's -32..127 domain, so the generator's + # two-sided guard is a proven-dead defensive branch under this slice's dynamics, and that BOTH + # selection paths are actually exercised. (DIF-02's score term, a later commit, is the only + # thing that could push the index out of domain; that is recorded with DIF-02.) + areas = {a["area"]: a["records"] for a in json.loads((DATA / "area-schedules.json").read_text())["areas"]} + inc = json.loads((DATA / "difficulty.json").read_text())["difficulty_tbl"]["values"][ + director.DIFFICULTY_DIP_INDEX + ] + lo = director.FORMATION_MIN_INDEX + hi = director.FORMATION_MIN_INDEX + director.FORMATION_TABLE_LEN - 1 + order = list(range(1, 17)) + list(range(7, 17)) * 6 # a few loop cycles for steady state + ai = 0 + raises = sets = 0 + for area in order: + for record in areas[area]: + handler = record["handler"] + if handler == "raise_ai_level_and_set_formation": + ai += inc + if ai >= director.AI_LEVEL_FOLD_THRESHOLD: + ai -= director.AI_LEVEL_FOLD_SUBTRACT + index = ai + raises += 1 + elif handler == "set_flying_formation": + index = record["params"]["formation_offset"] + sets += 1 + else: + continue + self.assertTrue(lo <= index <= hi, f"formation index {index} out of domain (area {area})") + self.assertGreater(raises, 0, "the raise re-select path must be exercised") + self.assertGreater(sets, 0, "the set-formation path must be exercised") if __name__ == "__main__": diff --git a/tools/game_director.py b/tools/game_director.py index a5e8d24..0abfa76 100644 --- a/tools/game_director.py +++ b/tools/game_director.py @@ -389,20 +389,116 @@ def _load_terrain_columns() -> list[int]: SCHEDULE_FIRED_ID = "area-schedule-fired" SCHEDULE_SENTINEL_HANDLER = "sentinel" +# DIF-01 / FORM-01 adaptive difficulty and normal flying formations +# (docs/spec/difficulty-and-formations.md). One accumulating AI level, raised on a +# schedule and folded back at 0x80, plus the formation the incoming wave uses. The AI +# level and the formation are selected from the SAME table by two DIFFERENT indices, +# matching the reference the spec cites: +# * set_flying_formation (sub_2_fn_2): index = the record's signed offset (NOT the AI +# level) — sign-extended, addressing the 2-byte entries; the offset is the index. +# * raise_ai_level_and_set_formation (sub_2_fn_3): index = the raised, folded AI level +# (no record offset). +# The formation table (formations.json) is decoded to logical entries index -32..127, so +# the reference's byte "doubling" is already absorbed; we store count and type-offset as +# two parallel logical lists. `formation index` is a transient working register (the +# lookup index), machinery like the rng working vars. Fire masks / adjust arrive in the +# later commits of this slice; their schedule scalars are already decoded into the +# `schedule arg` column here so the column is complete once and for all. +AI_LEVEL_ID = "difficulty-ai-level" +FORMATION_COUNT_ID = "formation-count" +FORMATION_TYPE_OFFSET_ID = "formation-type-offset" +FORMATION_INDEX_ID = "formation-index" # transient lookup index (machinery) +SCHEDULE_ARG_ID = "area-schedule-arg" # 4th parallel schedule column (runtime scalar) +DIFFICULTY_INCREMENT_ID = "difficulty-increment" # baked [2,0,6,16], indexed by DIP +FORMATION_COUNT_TABLE_ID = "formation-count-table" # 160 entries, index -32..127 +FORMATION_TYPE_OFFSET_TABLE_ID = "formation-type-offset-table" + +# Schedule handler strings this slice dispatches on (keys into the discriminated schedule +# records). Spawn/boss handlers stay on the empty seam (slice 8). +RAISE_HANDLER = "raise_ai_level_and_set_formation" +ADJUST_HANDLER = "adjust_ai_level_from_score" +SET_FORMATION_HANDLER = "set_flying_formation" +RESET_FORMATION_HANDLER = "reset_flying_formation" +FIRE_MASK_PREFIX = "fire_mask_" +GROUND_STOP_FIRING_HANDLER = "ground_stop_firing_row" + +# Project-defined cabinet difficulty DIP index (four-marker placeholder; the spec records +# no arcade power-on default, like RNG_COLD_START_SEED). Index 0 selects increment +2 — +# the LOWEST setting that still PROGRESSES (index 1 = +0 would make every raise inert and +# the difficulty director look dead on the monitors). An INDEPENDENT cabinet switch from +# DIP_STARTING_ITEM / DIP_BONUS_ITEM. It is CONSUMED LIVE this slice (it scales the +# observable AI-level growth), so its growth RATE is placeholder-driven and is NOT a +# fidelity claim — only the growth MECHANISM is. Recorded in docs/mechanics/019. +DIFFICULTY_DIP_INDEX = 0 +AI_LEVEL_FOLD_THRESHOLD = 0x80 # a raise reaching >= 128 folds back (never clamps) +AI_LEVEL_FOLD_SUBTRACT = 0x40 # ... by subtracting 64 once +FORMATION_MIN_INDEX = -32 # formations.json domain lower bound (bytes before the label) +FORMATION_TABLE_LEN = 160 # entries, index -32..127 inclusive + + +def _load_difficulty_increments() -> list[int]: + # DIF-01: the four cabinet AI-level increments [2,0,6,16] (difficulty.json), ingested + # (never authored), verified against the hash manifest at load. + return list(_load_spec_data("difficulty.json")["difficulty_tbl"]["values"]) + + +def _load_formation_tables() -> tuple[list[int], list[int]]: + # FORM-01: the normal flying-formation table (formations.json), decoded to logical + # entries index -32..127, split into two parallel lists in list-position order (position + # p, 1-based, is index p - 1 + FORMATION_MIN_INDEX). Fail LOUD if the entries are not + # exactly that contiguous domain, once each (mirrors the area-set check). + entries = _load_spec_data("formations.json")["formation_table"]["entries"] + ordered = sorted(entries, key=lambda e: e["index"]) + expected = list(range(FORMATION_MIN_INDEX, FORMATION_MIN_INDEX + FORMATION_TABLE_LEN)) + if [e["index"] for e in ordered] != expected: + raise SystemExit( + "formations.json must define exactly the contiguous indices " + f"{FORMATION_MIN_INDEX}..{FORMATION_MIN_INDEX + FORMATION_TABLE_LEN - 1}, once each" + ) + counts = [e["enemy_count"] for e in ordered] + offsets = [e["type_table_offset"] for e in ordered] + return counts, offsets + + +DIFFICULTY_INCREMENTS = _load_difficulty_increments() +FORMATION_COUNTS, FORMATION_TYPE_OFFSETS = _load_formation_tables() + + +def _schedule_arg(record: dict) -> int: + # DIF-01/03 + FORM-01: the single runtime-readable scalar each dispatched handler needs, + # pre-decoded from the opaque JSON payload (Scratch cannot parse JSON at runtime). A + # set-formation record carries its signed formation index; a fire-mask its byte; the + # ground-stop-firing row its row. Every other handler (raise/adjust/reset, and the + # spawn/boss kinds still on the empty dispatch seam) needs no scalar -> 0. + handler = record["handler"] + params = record.get("params", {}) + if handler == SET_FORMATION_HANDLER: + return params["formation_offset"] + if handler.startswith(FIRE_MASK_PREFIX): + return params["mask"] + if handler == GROUND_STOP_FIRING_HANDLER: + return params["row"] + return 0 -def _load_area_schedule(area_number: int) -> tuple[list[str], list[int], list[str]]: - # AREA-02: ingest one area's schedule from the committed, hash-pinned reference data as three - # faithful parallel columns (handler, trigger row, opaque payload). The end sentinel (a scalar - # in the JSON) is MATERIALIZED as the terminal row so the table is self-terminating and the - # extractor's "every table decodes to its sentinel" invariant is reproduced. object_type + - # params are serialized deterministically (sorted keys) into the payload; source_line is - # provenance, not runtime data, and is deliberately not ingested. The round-trip golden in - # tests/test_spec_docs.py proves nothing is dropped. + +def _load_area_schedule( + area_number: int, +) -> tuple[list[str], list[int], list[str], list[int]]: + # AREA-02: ingest one area's schedule from the committed, hash-pinned reference data as four + # faithful parallel columns (handler, trigger row, opaque payload, and DIF-01/03+FORM-01's + # runtime scalar `arg`). The end sentinel (a scalar in the JSON) is MATERIALIZED as the terminal + # row so the table is self-terminating and the extractor's "every table decodes to its sentinel" + # invariant is reproduced. object_type + params are serialized deterministically (sorted keys) + # into the payload; source_line is provenance, not runtime data, and is deliberately not ingested. + # The `arg` column carries the one scalar the runtime dispatch reads per record (Scratch cannot + # parse the JSON payload) — see _schedule_arg; the sentinel's arg is 0. The round-trip golden in + # tests/test_spec_docs.py proves nothing is dropped and all four columns stay the same length. data = _load_spec_data("area-schedules.json") area = next(a for a in data["areas"] if a["area"] == area_number) handlers: list[str] = [] rows: list[int] = [] payloads: list[str] = [] + args: list[int] = [] for record in area["records"]: handlers.append(record["handler"]) rows.append(record["scroll_row"]) @@ -413,14 +509,16 @@ def _load_area_schedule(area_number: int) -> tuple[list[str], list[int], list[st sort_keys=True, ) ) + args.append(_schedule_arg(record)) handlers.append(SCHEDULE_SENTINEL_HANDLER) rows.append(area["end_sentinel"]) payloads.append("") - return handlers, rows, payloads + args.append(0) + return handlers, rows, payloads, args def _load_all_area_schedules() -> tuple[ - list[str], list[int], list[str], list[int], list[int] + list[str], list[int], list[str], list[int], list[int], list[int] ]: # AREA-03: flatten all 16 normal area schedules into three parallel columns, with two 16-entry # index lists giving each area's 1-based INCLUSIVE span [start..end] into those columns. Areas are @@ -442,24 +540,27 @@ def _load_all_area_schedules() -> tuple[ handlers: list[str] = [] rows: list[int] = [] payloads: list[str] = [] + args: list[int] = [] starts: list[int] = [] ends: list[int] = [] cursor = 1 # 1-based, matching Scratch list indexing and the runtime `schedule cursor` for area_number in range(AREA_FIRST, AREA_MAX + 1): - area_handlers, area_rows, area_payloads = _load_area_schedule(area_number) + area_handlers, area_rows, area_payloads, area_args = _load_area_schedule(area_number) starts.append(cursor) # this area's first index (before advancing the cursor) handlers.extend(area_handlers) rows.extend(area_rows) payloads.extend(area_payloads) + args.extend(area_args) cursor += len(area_rows) ends.append(cursor - 1) # this area's last index (after advancing; inclusive) - return handlers, rows, payloads, starts, ends + return handlers, rows, payloads, args, starts, ends ( SCHEDULE_HANDLERS, SCHEDULE_ROWS, SCHEDULE_PAYLOADS, + SCHEDULE_ARGS, AREA_SCHEDULE_START, AREA_SCHEDULE_END, ) = _load_all_area_schedules() @@ -1275,6 +1376,49 @@ def _enter_area_top(blocks: Blocks) -> list[str]: ] +def _select_formation(blocks: Blocks, index_value: Any) -> list[str]: + # FORM-01: set the incoming wave's `formation count` + `formation type offset` from the + # formation table, indexed by `index_value` (a reporter block id OR a value-input spec giving + # the signed formation index — the record offset for a set-formation record, or the raised, + # folded AI level for a raise record). The table is two parallel logical lists over index + # FORMATION_MIN_INDEX..MAX, so the 1-based slot is index - FORMATION_MIN_INDEX + 1. Scratch + # `item N of list` returns "" (not 0) for N outside 1..len, silently poisoning arithmetic, so + # the assignment is GUARDED on BOTH bounds: an out-of-domain index leaves the prior formation + # unchanged (no faithful ROM-adjacent value exists to fabricate). The build-time fixture in + # tests/test_spec_docs.py proves the real committed schedules never leave the domain under this + # slice's dynamics, so the guard is defensive; DIF-02's score term (a later commit) is where an + # index could in principle exceed it, recorded there. + if isinstance(index_value, str): + set_index = blocks.set_var_expr("formation index", FORMATION_INDEX_ID, index_value) + else: + set_index = blocks.set_var("formation index", FORMATION_INDEX_ID, index_value) + + def idx() -> list[Any]: + return variable("formation index", FORMATION_INDEX_ID) + + def slot() -> str: + return blocks.op_add(idx(), number(1 - FORMATION_MIN_INDEX)) + + in_range = blocks.add("operator_and") + lower = blocks.op_gt(idx(), number(FORMATION_MIN_INDEX - 1)) # index >= MIN + upper = blocks.op_gt(number(FORMATION_MIN_INDEX + FORMATION_TABLE_LEN), idx()) # index <= MAX + blocks.blocks[lower]["parent"] = in_range + blocks.blocks[upper]["parent"] = in_range + blocks.blocks[in_range]["inputs"] = {"OPERAND1": [2, lower], "OPERAND2": [2, upper]} + set_count = blocks.set_var_expr( + "formation count", + FORMATION_COUNT_ID, + blocks.list_item("formation count table", FORMATION_COUNT_TABLE_ID, slot()), + ) + set_type = blocks.set_var_expr( + "formation type offset", + FORMATION_TYPE_OFFSET_ID, + blocks.list_item("formation type offset table", FORMATION_TYPE_OFFSET_TABLE_ID, slot()), + ) + guard = blocks.if_reporter(in_range, [set_count, set_type]) + return [set_index, guard] + + def _consume_schedule(blocks: Blocks) -> list[str]: # AREA-02 ordered dispatch: consume every record at the cursor whose trigger row equals the # current scroll row, in order, advancing the cursor. Fire-once is guaranteed by the monotonic @@ -1282,13 +1426,19 @@ def _consume_schedule(blocks: Blocks) -> list[str]: # row OR the cursor passes the area's end index (`cursor > end`, the belt-and-suspenders bound # slice 6 relies on so one area never bleeds into the next). The sentinel never fires because # the dispatch reads the POST-increment row, which is <= 12 until the wrap and never the area-top - # row 0x0D. The per-record handler dispatch is an EMPTY seam this slice (like advance-slots); - # `schedule fired` is the observable that events fire once, in order. + # row 0x0D. The DIF-01/FORM-01 handlers (raise / set-formation / reset-formation) are wired + # below; `schedule fired` still counts every record so the fire-once observable is unchanged. loop = blocks.add("control_repeat_until") def cursor() -> list[Any]: return variable("schedule cursor", SCHEDULE_CURSOR_ID) + def handler_at_cursor() -> str: + return blocks.list_item("schedule handler", SCHEDULE_HANDLER_ID, cursor()) + + def arg_at_cursor() -> str: + return blocks.list_item("schedule arg", SCHEDULE_ARG_ID, cursor()) + end = blocks.list_item( "area schedule end", AREA_SCHEDULE_END_ID, variable("area number", AREA_NUMBER_ID) ) @@ -1303,12 +1453,54 @@ def cursor() -> list[Any]: blocks.blocks[row_differs]["parent"] = stop blocks.blocks[stop]["inputs"] = {"OPERAND1": [2, past_end], "OPERAND2": [2, row_differs]} blocks.blocks[loop]["inputs"]["CONDITION"] = [2, stop] - # ENGINE-TODO: the per-record handler dispatch (spawn / formation / difficulty / boss, keyed on - # `schedule handler` + `schedule payload`) lands with the enemy slices (8+); the consume today - # advances the cursor and counts the fire, with no per-handler behaviour. + + # DIF-01 raise: add the cabinet increment to the AI level, fold back once at >= 0x80, then + # re-select the formation using the new AI level as the table index (no record offset). + raise_body = [ + blocks.set_var_expr( + "ai level", + AI_LEVEL_ID, + blocks.op_add( + variable("ai level", AI_LEVEL_ID), + blocks.list_item( + "difficulty increment", + DIFFICULTY_INCREMENT_ID, + number(DIFFICULTY_DIP_INDEX + 1), + ), + ), + ), + blocks.if_reporter( + blocks.op_gt(variable("ai level", AI_LEVEL_ID), number(AI_LEVEL_FOLD_THRESHOLD - 1)), + [blocks.change_var("ai level", AI_LEVEL_ID, -AI_LEVEL_FOLD_SUBTRACT)], + ), + *_select_formation(blocks, variable("ai level", AI_LEVEL_ID)), + ] + raise_branch = blocks.if_reporter( + blocks.op_eq(handler_at_cursor(), text(RAISE_HANDLER)), raise_body + ) + # FORM-01 set-formation: the record's signed offset IS the table index (no AI level added). + set_branch = blocks.if_reporter( + blocks.op_eq(handler_at_cursor(), text(SET_FORMATION_HANDLER)), + _select_formation(blocks, arg_at_cursor()), + ) + # FORM-01 reset-formation: zero the wave between formations. + reset_branch = blocks.if_reporter( + blocks.op_eq(handler_at_cursor(), text(RESET_FORMATION_HANDLER)), + [ + blocks.set_var("formation count", FORMATION_COUNT_ID, number(0)), + blocks.set_var("formation type offset", FORMATION_TYPE_OFFSET_ID, number(0)), + ], + ) + # ENGINE-TODO: the spawn / boss handler dispatch (add_ground_object, add_domogram_with_path, + # add_object, *bacura*, andor_genesis_*, sheonite_*) lands with the enemy slices (8+); the + # score-adaptive AI re-tune and the fire-permission masks arrive in the later commits of this + # slice. Unhandled records still advance the cursor and count the fire, with no behaviour. blocks.substack( loop, [ + raise_branch, + set_branch, + reset_branch, blocks.change_var("schedule fired", SCHEDULE_FIRED_ID, 1), blocks.change_var("schedule cursor", SCHEDULE_CURSOR_ID, 1), ], @@ -1713,6 +1905,28 @@ def stage_blocks() -> dict[str, dict[str, Any]]: blocks.substack(new_life, [checkpoint, *_enter_area_top(blocks)]) blocks.chain(area_reset, [world_area, new_life]) + # DIF-01 / FORM-01 difficulty-director reset — its OWN `director reset` receiver (like the eight + # existing per-concern receivers, each branching on its own scope). Per the spec, the AI level, + # formation, and fire masks are per-player game state: they PERSIST across death/respawn and + # reset only for a new game — so this fires on cold-start / new-game only. It touches only the + # difficulty vars (disjoint from every other receiver's), so the unordered same-target hat + # execution is safe. (`formation index` is a transient lookup register, not reset here.) + difficulty_reset = blocks.receive("director reset") + blocks.chain( + difficulty_reset, + [ + reset_if( + blocks, + ("cold-start", "new-game"), + [ + blocks.set_var("ai level", AI_LEVEL_ID, number(0)), + blocks.set_var("formation count", FORMATION_COUNT_ID, number(0)), + blocks.set_var("formation type offset", FORMATION_TYPE_OFFSET_ID, number(0)), + ], + ) + ], + ) + return blocks.blocks @@ -2643,6 +2857,10 @@ def expected_project(project: dict[str, Any]) -> dict[str, Any]: TERRAIN_COLUMN_ID, SCHEDULE_CURSOR_ID, SCHEDULE_FIRED_ID, + AI_LEVEL_ID, + FORMATION_COUNT_ID, + FORMATION_TYPE_OFFSET_ID, + FORMATION_INDEX_ID, } preserved_variables = { variable_id: value @@ -2700,6 +2918,14 @@ def expected_project(project: dict[str, Any]) -> dict[str, Any]: # flattened schedule lists and the per-area count of records fired (the observable). SCHEDULE_CURSOR_ID: ["schedule cursor", 1], SCHEDULE_FIRED_ID: ["schedule fired", 0], + # DIF-01 / FORM-01 difficulty-director state (Stage-written, sprite-read, write-forbidden, + # like the area state): the accumulating AI level, and the incoming wave's size + type-table + # offset the slice-8 spawner will read. `formation index` is the transient lookup register + # (machinery). All reset to 0 on a world reset; they persist across death/respawn. + AI_LEVEL_ID: ["ai level", 0], + FORMATION_COUNT_ID: ["formation count", 0], + FORMATION_TYPE_OFFSET_ID: ["formation type offset", 0], + FORMATION_INDEX_ID: ["formation index", 0], } owned_lists = { ALLOWED_ID, @@ -2718,6 +2944,10 @@ def expected_project(project: dict[str, Any]) -> dict[str, Any]: SCHEDULE_PAYLOAD_ID, AREA_SCHEDULE_START_ID, AREA_SCHEDULE_END_ID, + SCHEDULE_ARG_ID, + DIFFICULTY_INCREMENT_ID, + FORMATION_COUNT_TABLE_ID, + FORMATION_TYPE_OFFSET_TABLE_ID, } preserved_lists = { list_id: value @@ -2768,8 +2998,19 @@ def expected_project(project: dict[str, Any]) -> dict[str, Any]: SCHEDULE_HANDLER_ID: ["schedule handler", list(SCHEDULE_HANDLERS)], SCHEDULE_TRIGGER_ROW_ID: ["schedule trigger row", list(SCHEDULE_ROWS)], SCHEDULE_PAYLOAD_ID: ["schedule payload", list(SCHEDULE_PAYLOADS)], + # DIF-01/03 + FORM-01: the 4th parallel schedule column — the one runtime-readable scalar + # each dispatched record needs (set-formation offset / fire-mask byte / ground-stop row; 0 + # otherwise), pre-decoded from the opaque payload. Same length as the other three columns. + SCHEDULE_ARG_ID: ["schedule arg", list(SCHEDULE_ARGS)], AREA_SCHEDULE_START_ID: ["area schedule start", list(AREA_SCHEDULE_START)], AREA_SCHEDULE_END_ID: ["area schedule end", list(AREA_SCHEDULE_END)], + # DIF-01 cabinet AI-level increments [2,0,6,16] (difficulty.json), indexed by the DIP. + DIFFICULTY_INCREMENT_ID: ["difficulty increment", list(DIFFICULTY_INCREMENTS)], + # FORM-01 normal flying-formation table (formations.json), decoded to logical entries + # index -32..127, split into two parallel lists: wave size and type-table offset. Read-only + # authority, indexed at runtime by the folded AI level (raise) or the record offset (set). + FORMATION_COUNT_TABLE_ID: ["formation count table", list(FORMATION_COUNTS)], + FORMATION_TYPE_OFFSET_TABLE_ID: ["formation type offset table", list(FORMATION_TYPE_OFFSETS)], } stage["broadcasts"] = {message_id: name for name, message_id in MESSAGES.items()} From 5d13b7a225571177e36db4e5f5e6fe5c76249d5d Mon Sep 17 00:00:00 2001 From: Shane Kidd <33380501+StarshipSuperjam@users.noreply.github.com> Date: Sat, 15 Aug 2026 13:41:13 -0700 Subject: [PATCH 3/5] Feature: score-adaptive AI-level re-tune (DIF-02) Wire the adjust_ai_level_from_score handler into the schedule dispatch: when an adjust record fires it adds floor(floor(score/1000) / craft), capped at 16, to the AI level, guarded on craft > 0. Reserve is the live `craft` count (the reference divides by solvalou_number with no subtraction). Unlike the raise, the reference does not fold this add back. - `ai adjust` transient working register (machinery). - Model fixture (test_score_retune_rule) reproduces the rule: sub-1000 floor, the cap at 16, the craft-zero guard. - Fixed the PLY-02 death-decision negative fixture to target the death `craft > threshold` specifically (a control_if_else condition), not DIF-02's new `craft > 0` re-tune guard. Record 021; catalog DIF-02 -> present; playtest step 4 notes the score-adjust jump. build_hash re-pinned; two builds byte-identical + round-trip; harness green. Co-Authored-By: Claude Opus 4.8 --- docs/MECHANICS_CATALOG.md | 2 +- docs/PLAYTEST_CHECKLIST.md | 4 +- docs/mechanics/021-score-adaptive-ai-level.md | 15 + src/xevious/project.json | 1615 ++++++++++------- src/xevious/runtime_identifiers.json | 5 + tests/test_scratch_project.py | 26 +- tests/test_spec_docs.py | 16 + tools/game_director.py | 42 + 8 files changed, 1088 insertions(+), 637 deletions(-) create mode 100644 docs/mechanics/021-score-adaptive-ai-level.md diff --git a/docs/MECHANICS_CATALOG.md b/docs/MECHANICS_CATALOG.md index 17edfed..5954569 100644 --- a/docs/MECHANICS_CATALOG.md +++ b/docs/MECHANICS_CATALOG.md @@ -50,7 +50,7 @@ document differ, the spec document wins. | AREA-03 | All 16 normal area tables | present | AREA-02 | sub: `area_1_obj_tbl_normal` through `area_16_obj_tbl_normal` | An accelerated trace consumes every normal table without unknown or Super objects. All 16 normal schedules are ingested into the flattened columns with per-area offsets and the accelerated 1–16→7 data trace passes ([017](mechanics/017-all-area-schedules.md)); the trace/round-trip prove the data, the built per-area consume rests on the offset golden + operator playtest. | | AREA-04 | Transitions and 16-to-7 loop | present | AREA-03 | main: `main_gameplay_loop`; sub: `sub_fn_3__handle_next_area` | Areas advance 1–16 then continue at 7, with no win screen. The advance/wrap shipped in AREA-01; with all 16 schedules ingested the loop is data-complete and the accelerated trace confirms 1–16→7 with no win screen ([018](mechanics/018-area-transitions-and-loop.md)) — a data trace, runtime traversal on the operator playtest. | | DIF-01 | Difficulty setting | present | AREA-02 | sub: `difficulty_tbl`, `sub_2_fn_3__inc_enemy_AI_and_flying_enemies` | Each normal setting starts at its recorded pressure. The adaptive AI level accumulates live from the schedule's raise records and folds back below 0x80 ([019](mechanics/019-difficulty-ai-level.md)); foundation — the AI level is live/observable, its consumption as enemy pressure is slices 8+, and the cabinet DIP is a project-defined placeholder (increment +2). | -| DIF-02 | Score-per-life adaptive AI | missing | DIF-01, ECO-01 | sub: `sub_2_fn_23__adjust_AI_level_based_on_score`, `avg_score_per_solvalou` | Fixtures show ordered AI changes from score per craft. | +| DIF-02 | Score-per-life adaptive AI | present | DIF-01, ECO-01 | sub: `sub_2_fn_23__adjust_AI_level_based_on_score`, `avg_score_per_solvalou` | Fixtures show ordered AI changes from score per craft. The adjust records re-tune the AI level by floor(floor(score/1000)/craft) capped at 16, reading the live score and craft ([021](mechanics/021-score-adaptive-ai-level.md)); foundation — the rule is live and fixture-proven, the visible "playing better = harder" difference needs enemies (slice 8+). | | DIF-03 | Per-family fire frequency | missing | DIF-01, SYS-04 | sub: `sub_2_fn_8__fire_freq_mask_derota` through `sub_2_fn_22__fire_freq_mask_andor_genesis` | Family fire fixtures follow recorded masks. | | FORM-01 | Normal flying formations | present | AREA-02, DIF-01 | sub: `flying_enemy_type_offset_tbl_normal`, `sub_2_fn_2__set_flying_enemies` | Fixtures preserve normal type, count, offsets, and order. The wave size + type-table offset are selected live — set-formation by the record offset, raise by the folded AI level, reset zeroes ([020](mechanics/020-normal-flying-formations.md)); foundation — selection is live/observable, spawning the wave is slice 8. | diff --git a/docs/PLAYTEST_CHECKLIST.md b/docs/PLAYTEST_CHECKLIST.md index a5af4fe..69e5842 100644 --- a/docs/PLAYTEST_CHECKLIST.md +++ b/docs/PLAYTEST_CHECKLIST.md @@ -57,7 +57,9 @@ so area position is read from the `area progress`/`area number` variable watcher round-trip test, not the eye.) The visual terrain is not yet driven by the clock, so these are variable-watcher checks, not on-screen ones. **Also tick `ai level`, `formation count`, and `formation type offset`** (DIF-01 / FORM-01): as you fly, `ai level` climbs a little each time a raise - record fires and stays below **128** (a raise folds it back — you should never see it reach 128), and + record fires and stays below **128** (a raise folds it back — you should never see it reach 128); if you + have been scoring (press **S** to raise the score), it can also jump when a score-adjust record fires + (DIF-02) — the *amount* is score/craft-dependent and its visible effect on enemies is deferred to slice 8; and `formation count` / `formation type offset` change to a new wave (count in **1–6**) when a raise or a set-formation record fires, and drop to 0 on a reset-formation. **Read the `ai level` growth *rate* as a placeholder, not fidelity:** the cabinet difficulty is a project-chosen default (increment +2), so how diff --git a/docs/mechanics/021-score-adaptive-ai-level.md b/docs/mechanics/021-score-adaptive-ai-level.md new file mode 100644 index 0000000..a98286b --- /dev/null +++ b/docs/mechanics/021-score-adaptive-ai-level.md @@ -0,0 +1,15 @@ +# Score-adaptive AI level — pressure that tracks how well the player is doing + +- Mechanic: DIF-02 (partial, foundation) — the schedule's `adjust_ai_level_from_score` records re-tune the [AI level](019-difficulty-ai-level.md) from performance: a player scoring heavily with craft in reserve meets sharper pressure, a struggling player is spared. It reads the live score ([ECO-01](009-scoring-path.md)) and craft count ([ECO-03](011-lives-and-bonus-economy.md)). +- Derived behavior: While an area scrolls, each adjust record (21 across the sixteen areas, zero to four per area) adds to the AI level the player's score in thousands divided by the number of craft in reserve, floored and capped at 16 — and only when at least one craft is in reserve. Unlike the raise record, this add is **not** folded back. The result feeds the same AI level every later enemy behaviour scales its pressure by. +- Reference provenance: `jotd666/xevious@71473685a8c7856c8401c8519276cd97a38d4183`; `src/xevious_sub.68k`: `sub_2_fn_23__adjust_AI_level_based_on_score` (344–353) — the score-in-thousands input, the `avg_score_per_solvalou` divide (360–372, dividing by `solvalou_number` with no subtraction), the `cmp #16` cap, and the add to `enemy_AI_level`. The behaviour is the settled [difficulty and formations](../spec/difficulty-and-formations.md) document. +- Transfer class: General behavior (instruction-derived rule; no source text or media copied). +- Scratch interpretation: The adjust branch of the schedule consume (`_consume_schedule`), guarded on `craft > 0` (no divide-by-zero), computes the addend into the transient `ai adjust` working register as `floor(floor(score / 1000) / craft)` — through the centralized `op_*` helpers — then caps it at 16 with a single `if`, then adds it to `ai level`. Reserve is the live `craft` count (`LIVES_ID`), the same variable the death economy maintains; the reference divides by `solvalou_number`, its remaining-craft count, with no subtraction, so `craft` is the faithful divisor. +- Scratch evidence: the adjust branch in `_consume_schedule` and the `ai adjust` Stage variable (machinery) in `tools/game_director.py`. Model fixture in `tests/test_spec_docs.py` (`DifficultyAndFormations.test_score_retune_rule`): the documented rule over representative score/craft pairs — the sub-1000 floor, the cap at 16, and the craft-zero guard. The dispatch-present structural check (`tests/test_scratch_project.py` `_area02_failures`) confirms the handler branch is wired; the `ai adjust` machinery variable is guarded by the transition-path variable set. +- Acceptance criteria: A model fixture implementing the documented rule reproduces the re-tune (score per reserve craft, floored, capped at 16, guarded at zero) — engine, Python fixture. The build's in-game re-tune is confirmed in play (the spec defers this: "playing better produces visibly harder waves" needs the enemy slices to be observable) — operator, deferred. +- Fidelity status: DIF-02 is **partial** (foundation) — the re-tune is built and runs live (it fires on adjust records reading the live score and craft), and the rule is reference-faithful. What is deferred, per the spec's own acceptance table: the operator-visible *difference* ("playing better = harder waves") needs the enemy waves the AI level scales, which arrive with the enemy slices (8+). +- License status: The pinned reference states no reusable license; only the derived re-tune rule is used, cited to the settled spec, and no reference source text or media was reproduced. +- Known deviations or uncertainty: Reserve is mapped to the live `craft` count with no subtraction, matching the reference's `solvalou_number`; whether that count includes the craft currently in play (a possible off-by-one against a strict "in reserve" reading) is a residual uncertainty recorded here rather than silently chosen. The adjust does **not** fold back (per the reference), so it can push the AI level above 0x80 transiently; the next raise folds it, and because the raise's re-select uses the *post-fold* level and a set-formation uses its own offset, the formation index stays in the table's domain (the two-sided formation guard in [FORM-01](020-normal-flying-formations.md) is the backstop). In normal play the level stays well below the byte wrap because raises fold it, so no explicit mod-256 is applied — recorded rather than left implied. The generated adjust's live execution rests on the model rule plus the structural dispatch check and the operator playtest: the Python block interpreter executes only `set`/`if` (not the `repeat until` consume), and the scratch-vm harness observes the AI level but cannot isolate an adjust from the raises in the same run — matching the spec's deferral of DIF-02's in-game half. +- [x] No assembly or other source code was copied into the Scratch project. +- [x] No arcade ROM files were acquired, opened, extracted, or distributed. +- [x] Any transferred graphics or audio are recorded in `src/xevious/assets/provenance.json`. diff --git a/src/xevious/project.json b/src/xevious/project.json index 0f2fab4..7a6c228 100644 --- a/src/xevious/project.json +++ b/src/xevious/project.json @@ -131,6 +131,10 @@ "formation-index": [ "formation index", 0 + ], + "difficulty-ai-adjust": [ + "ai adjust", + 0 ] }, "lists": { @@ -6627,7 +6631,7 @@ 1, [ 10, - "set_flying_formation" + "adjust_ai_level_from_score" ] ] }, @@ -6636,96 +6640,102 @@ "topLevel": false }, "gd-stage-125": { - "opcode": "data_itemoflist", + "opcode": "operator_gt", "next": null, - "parent": "gd-stage-126", + "parent": "gd-stage-136", "inputs": { - "INDEX": [ + "OPERAND1": [ 3, [ 12, - "schedule cursor", - "area-schedule-cursor" + "craft", + "eco-craft" ], [ 10, "" ] + ], + "OPERAND2": [ + 1, + [ + 4, + 0 + ] ] }, - "fields": { - "LIST": [ - "schedule arg", - "area-schedule-arg" - ] - }, + "fields": {}, "shadow": false, "topLevel": false }, "gd-stage-126": { - "opcode": "data_setvariableto", - "next": "gd-stage-136", - "parent": "gd-stage-137", + "opcode": "operator_divide", + "next": null, + "parent": "gd-stage-127", "inputs": { - "VALUE": [ + "NUM1": [ 3, - "gd-stage-125", + [ + 12, + "score", + "eco-score" + ], [ 10, "" ] + ], + "NUM2": [ + 1, + [ + 4, + 1000 + ] ] }, - "fields": { - "VARIABLE": [ - "formation index", - "formation-index" - ] - }, + "fields": {}, "shadow": false, "topLevel": false }, "gd-stage-127": { - "opcode": "operator_and", + "opcode": "operator_mathop", "next": null, - "parent": "gd-stage-136", + "parent": "gd-stage-128", "inputs": { - "OPERAND1": [ - 2, - "gd-stage-128" - ], - "OPERAND2": [ + "NUM": [ 2, - "gd-stage-129" + "gd-stage-126" + ] + }, + "fields": { + "OPERATOR": [ + "floor", + null ] }, - "fields": {}, "shadow": false, "topLevel": false }, "gd-stage-128": { - "opcode": "operator_gt", + "opcode": "operator_divide", "next": null, - "parent": "gd-stage-127", + "parent": "gd-stage-129", "inputs": { - "OPERAND1": [ + "NUM1": [ + 2, + "gd-stage-127" + ], + "NUM2": [ 3, [ 12, - "formation index", - "formation-index" + "craft", + "eco-craft" ], [ 10, "" ] - ], - "OPERAND2": [ - 1, - [ - 4, - -33 - ] ] }, "fields": {}, @@ -6733,56 +6743,69 @@ "topLevel": false }, "gd-stage-129": { - "opcode": "operator_gt", + "opcode": "operator_mathop", "next": null, - "parent": "gd-stage-127", + "parent": "gd-stage-130", "inputs": { - "OPERAND1": [ - 1, - [ - 4, - 128 - ] - ], - "OPERAND2": [ + "NUM": [ + 2, + "gd-stage-128" + ] + }, + "fields": { + "OPERATOR": [ + "floor", + null + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-130": { + "opcode": "data_setvariableto", + "next": "gd-stage-133", + "parent": "gd-stage-136", + "inputs": { + "VALUE": [ 3, - [ - 12, - "formation index", - "formation-index" - ], + "gd-stage-129", [ 10, "" ] ] }, - "fields": {}, + "fields": { + "VARIABLE": [ + "ai adjust", + "difficulty-ai-adjust" + ] + }, "shadow": false, "topLevel": false }, - "gd-stage-130": { - "opcode": "operator_add", + "gd-stage-131": { + "opcode": "operator_gt", "next": null, - "parent": "gd-stage-131", + "parent": "gd-stage-133", "inputs": { - "NUM1": [ + "OPERAND1": [ 3, [ 12, - "formation index", - "formation-index" + "ai adjust", + "difficulty-ai-adjust" ], [ 10, "" ] ], - "NUM2": [ + "OPERAND2": [ 1, [ 4, - 33 + 16 ] ] }, @@ -6790,59 +6813,57 @@ "shadow": false, "topLevel": false }, - "gd-stage-131": { - "opcode": "data_itemoflist", + "gd-stage-132": { + "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-132", + "parent": "gd-stage-133", "inputs": { - "INDEX": [ - 2, - "gd-stage-130" + "VALUE": [ + 1, + [ + 4, + 16 + ] ] }, "fields": { - "LIST": [ - "formation count table", - "formation-count-table" + "VARIABLE": [ + "ai adjust", + "difficulty-ai-adjust" ] }, "shadow": false, "topLevel": false }, - "gd-stage-132": { - "opcode": "data_setvariableto", + "gd-stage-133": { + "opcode": "control_if", "next": "gd-stage-135", - "parent": "gd-stage-136", + "parent": "gd-stage-130", "inputs": { - "VALUE": [ - 3, - "gd-stage-131", - [ - 10, - "" - ] - ] - }, - "fields": { - "VARIABLE": [ - "formation count", - "formation-count" + "CONDITION": [ + 2, + "gd-stage-131" + ], + "SUBSTACK": [ + 2, + "gd-stage-132" ] }, + "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-133": { + "gd-stage-134": { "opcode": "operator_add", "next": null, - "parent": "gd-stage-134", + "parent": "gd-stage-135", "inputs": { "NUM1": [ 3, [ 12, - "formation index", - "formation-index" + "ai level", + "difficulty-ai-level" ], [ 10, @@ -6850,10 +6871,15 @@ ] ], "NUM2": [ - 1, + 3, [ - 4, - 33 + 12, + "ai adjust", + "difficulty-ai-adjust" + ], + [ + 10, + "" ] ] }, @@ -6861,29 +6887,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-134": { - "opcode": "data_itemoflist", - "next": null, - "parent": "gd-stage-135", - "inputs": { - "INDEX": [ - 2, - "gd-stage-133" - ] - }, - "fields": { - "LIST": [ - "formation type offset table", - "formation-type-offset-table" - ] - }, - "shadow": false, - "topLevel": false - }, "gd-stage-135": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-132", + "parent": "gd-stage-133", "inputs": { "VALUE": [ 3, @@ -6896,8 +6903,8 @@ }, "fields": { "VARIABLE": [ - "formation type offset", - "formation-type-offset" + "ai level", + "difficulty-ai-level" ] }, "shadow": false, @@ -6906,15 +6913,15 @@ "gd-stage-136": { "opcode": "control_if", "next": null, - "parent": "gd-stage-126", + "parent": "gd-stage-137", "inputs": { "CONDITION": [ 2, - "gd-stage-127" + "gd-stage-125" ], "SUBSTACK": [ 2, - "gd-stage-132" + "gd-stage-130" ] }, "fields": {}, @@ -6923,7 +6930,7 @@ }, "gd-stage-137": { "opcode": "control_if", - "next": "gd-stage-142", + "next": "gd-stage-152", "parent": "gd-stage-122", "inputs": { "CONDITION": [ @@ -6932,7 +6939,7 @@ ], "SUBSTACK": [ 2, - "gd-stage-126" + "gd-stage-136" ] }, "fields": {}, @@ -6969,7 +6976,7 @@ "gd-stage-139": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-142", + "parent": "gd-stage-152", "inputs": { "OPERAND1": [ 2, @@ -6979,7 +6986,7 @@ 1, [ 10, - "reset_flying_formation" + "set_flying_formation" ] ] }, @@ -6988,22 +6995,27 @@ "topLevel": false }, "gd-stage-140": { - "opcode": "data_setvariableto", - "next": "gd-stage-141", - "parent": "gd-stage-142", + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-141", "inputs": { - "VALUE": [ - 1, + "INDEX": [ + 3, [ - 4, - 0 + 12, + "schedule cursor", + "area-schedule-cursor" + ], + [ + 10, + "" ] ] }, "fields": { - "VARIABLE": [ - "formation count", - "formation-count" + "LIST": [ + "schedule arg", + "area-schedule-arg" ] }, "shadow": false, @@ -7011,14 +7023,233 @@ }, "gd-stage-141": { "opcode": "data_setvariableto", - "next": null, - "parent": "gd-stage-140", + "next": "gd-stage-151", + "parent": "gd-stage-152", "inputs": { "VALUE": [ - 1, + 3, + "gd-stage-140", [ - 4, - 0 + 10, + "" + ] + ] + }, + "fields": { + "VARIABLE": [ + "formation index", + "formation-index" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-142": { + "opcode": "operator_and", + "next": null, + "parent": "gd-stage-151", + "inputs": { + "OPERAND1": [ + 2, + "gd-stage-143" + ], + "OPERAND2": [ + 2, + "gd-stage-144" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-143": { + "opcode": "operator_gt", + "next": null, + "parent": "gd-stage-142", + "inputs": { + "OPERAND1": [ + 3, + [ + 12, + "formation index", + "formation-index" + ], + [ + 10, + "" + ] + ], + "OPERAND2": [ + 1, + [ + 4, + -33 + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-144": { + "opcode": "operator_gt", + "next": null, + "parent": "gd-stage-142", + "inputs": { + "OPERAND1": [ + 1, + [ + 4, + 128 + ] + ], + "OPERAND2": [ + 3, + [ + 12, + "formation index", + "formation-index" + ], + [ + 10, + "" + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-145": { + "opcode": "operator_add", + "next": null, + "parent": "gd-stage-146", + "inputs": { + "NUM1": [ + 3, + [ + 12, + "formation index", + "formation-index" + ], + [ + 10, + "" + ] + ], + "NUM2": [ + 1, + [ + 4, + 33 + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-146": { + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-147", + "inputs": { + "INDEX": [ + 2, + "gd-stage-145" + ] + }, + "fields": { + "LIST": [ + "formation count table", + "formation-count-table" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-147": { + "opcode": "data_setvariableto", + "next": "gd-stage-150", + "parent": "gd-stage-151", + "inputs": { + "VALUE": [ + 3, + "gd-stage-146", + [ + 10, + "" + ] + ] + }, + "fields": { + "VARIABLE": [ + "formation count", + "formation-count" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-148": { + "opcode": "operator_add", + "next": null, + "parent": "gd-stage-149", + "inputs": { + "NUM1": [ + 3, + [ + 12, + "formation index", + "formation-index" + ], + [ + 10, + "" + ] + ], + "NUM2": [ + 1, + [ + 4, + 33 + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-149": { + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-150", + "inputs": { + "INDEX": [ + 2, + "gd-stage-148" + ] + }, + "fields": { + "LIST": [ + "formation type offset table", + "formation-type-offset-table" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-150": { + "opcode": "data_setvariableto", + "next": null, + "parent": "gd-stage-147", + "inputs": { + "VALUE": [ + 3, + "gd-stage-149", + [ + 10, + "" ] ] }, @@ -7031,9 +7262,27 @@ "shadow": false, "topLevel": false }, - "gd-stage-142": { + "gd-stage-151": { + "opcode": "control_if", + "next": null, + "parent": "gd-stage-141", + "inputs": { + "CONDITION": [ + 2, + "gd-stage-142" + ], + "SUBSTACK": [ + 2, + "gd-stage-147" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-152": { "opcode": "control_if", - "next": "gd-stage-143", + "next": "gd-stage-157", "parent": "gd-stage-137", "inputs": { "CONDITION": [ @@ -7042,17 +7291,127 @@ ], "SUBSTACK": [ 2, - "gd-stage-140" + "gd-stage-141" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-143": { + "gd-stage-153": { + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-154", + "inputs": { + "INDEX": [ + 3, + [ + 12, + "schedule cursor", + "area-schedule-cursor" + ], + [ + 10, + "" + ] + ] + }, + "fields": { + "LIST": [ + "schedule handler", + "area-schedule-handler" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-154": { + "opcode": "operator_equals", + "next": null, + "parent": "gd-stage-157", + "inputs": { + "OPERAND1": [ + 2, + "gd-stage-153" + ], + "OPERAND2": [ + 1, + [ + 10, + "reset_flying_formation" + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-155": { + "opcode": "data_setvariableto", + "next": "gd-stage-156", + "parent": "gd-stage-157", + "inputs": { + "VALUE": [ + 1, + [ + 4, + 0 + ] + ] + }, + "fields": { + "VARIABLE": [ + "formation count", + "formation-count" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-156": { + "opcode": "data_setvariableto", + "next": null, + "parent": "gd-stage-155", + "inputs": { + "VALUE": [ + 1, + [ + 4, + 0 + ] + ] + }, + "fields": { + "VARIABLE": [ + "formation type offset", + "formation-type-offset" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-157": { + "opcode": "control_if", + "next": "gd-stage-158", + "parent": "gd-stage-152", + "inputs": { + "CONDITION": [ + 2, + "gd-stage-154" + ], + "SUBSTACK": [ + 2, + "gd-stage-155" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-158": { "opcode": "data_changevariableby", - "next": "gd-stage-144", - "parent": "gd-stage-142", + "next": "gd-stage-159", + "parent": "gd-stage-157", "inputs": { "VALUE": [ 1, @@ -7071,10 +7430,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-144": { + "gd-stage-159": { "opcode": "data_changevariableby", "next": null, - "parent": "gd-stage-143", + "parent": "gd-stage-158", "inputs": { "VALUE": [ 1, @@ -7093,14 +7452,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-145": { + "gd-stage-160": { "opcode": "procedures_definition", - "next": "gd-stage-147", + "next": "gd-stage-162", "parent": null, "inputs": { "custom_block": [ 1, - "gd-stage-146" + "gd-stage-161" ] }, "fields": {}, @@ -7109,10 +7468,10 @@ "x": 20, "y": 770 }, - "gd-stage-146": { + "gd-stage-161": { "opcode": "procedures_prototype", "next": null, - "parent": "gd-stage-145", + "parent": "gd-stage-160", "inputs": {}, "fields": {}, "shadow": true, @@ -7127,10 +7486,10 @@ "warp": "true" } }, - "gd-stage-147": { + "gd-stage-162": { "opcode": "data_changevariableby", - "next": "gd-stage-148", - "parent": "gd-stage-145", + "next": "gd-stage-163", + "parent": "gd-stage-160", "inputs": { "VALUE": [ 3, @@ -7154,28 +7513,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-148": { + "gd-stage-163": { "opcode": "control_if", - "next": "gd-stage-151", - "parent": "gd-stage-147", + "next": "gd-stage-166", + "parent": "gd-stage-162", "inputs": { "CONDITION": [ 2, - "gd-stage-149" + "gd-stage-164" ], "SUBSTACK": [ 2, - "gd-stage-150" + "gd-stage-165" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-149": { + "gd-stage-164": { "opcode": "operator_gt", "next": null, - "parent": "gd-stage-148", + "parent": "gd-stage-163", "inputs": { "OPERAND1": [ 3, @@ -7201,10 +7560,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-150": { + "gd-stage-165": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-148", + "parent": "gd-stage-163", "inputs": { "VALUE": [ 1, @@ -7223,28 +7582,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-151": { + "gd-stage-166": { "opcode": "control_if", - "next": "gd-stage-154", - "parent": "gd-stage-148", + "next": "gd-stage-169", + "parent": "gd-stage-163", "inputs": { "CONDITION": [ 2, - "gd-stage-152" + "gd-stage-167" ], "SUBSTACK": [ 2, - "gd-stage-153" + "gd-stage-168" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-152": { + "gd-stage-167": { "opcode": "operator_gt", "next": null, - "parent": "gd-stage-151", + "parent": "gd-stage-166", "inputs": { "OPERAND1": [ 3, @@ -7275,10 +7634,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-153": { + "gd-stage-168": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-151", + "parent": "gd-stage-166", "inputs": { "VALUE": [ 3, @@ -7302,10 +7661,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-154": { + "gd-stage-169": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-151", + "parent": "gd-stage-166", "inputs": {}, "fields": {}, "shadow": false, @@ -7318,14 +7677,14 @@ "warp": "true" } }, - "gd-stage-155": { + "gd-stage-170": { "opcode": "procedures_definition", - "next": "gd-stage-173", + "next": "gd-stage-188", "parent": null, "inputs": { "custom_block": [ 1, - "gd-stage-156" + "gd-stage-171" ] }, "fields": {}, @@ -7334,10 +7693,10 @@ "x": 20, "y": 920 }, - "gd-stage-156": { + "gd-stage-171": { "opcode": "procedures_prototype", "next": null, - "parent": "gd-stage-155", + "parent": "gd-stage-170", "inputs": {}, "fields": {}, "shadow": true, @@ -7352,10 +7711,10 @@ "warp": "true" } }, - "gd-stage-157": { + "gd-stage-172": { "opcode": "operator_lt", "next": null, - "parent": "gd-stage-158", + "parent": "gd-stage-173", "inputs": { "OPERAND1": [ 3, @@ -7386,24 +7745,24 @@ "shadow": false, "topLevel": false }, - "gd-stage-158": { + "gd-stage-173": { "opcode": "operator_not", "next": null, - "parent": "gd-stage-166", + "parent": "gd-stage-181", "inputs": { "OPERAND": [ 2, - "gd-stage-157" + "gd-stage-172" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-159": { + "gd-stage-174": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-160", + "parent": "gd-stage-175", "inputs": { "INDEX": [ 1, @@ -7422,10 +7781,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-160": { + "gd-stage-175": { "opcode": "operator_add", "next": null, - "parent": "gd-stage-161", + "parent": "gd-stage-176", "inputs": { "NUM1": [ 3, @@ -7441,21 +7800,21 @@ ], "NUM2": [ 2, - "gd-stage-159" + "gd-stage-174" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-161": { + "gd-stage-176": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-165", + "parent": "gd-stage-180", "inputs": { "VALUE": [ 3, - "gd-stage-160", + "gd-stage-175", [ 10, "" @@ -7471,10 +7830,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-162": { + "gd-stage-177": { "opcode": "data_changevariableby", - "next": "gd-stage-164", - "parent": "gd-stage-166", + "next": "gd-stage-179", + "parent": "gd-stage-181", "inputs": { "VALUE": [ 1, @@ -7493,10 +7852,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-163": { + "gd-stage-178": { "opcode": "sound_sounds_menu", "next": null, - "parent": "gd-stage-164", + "parent": "gd-stage-179", "inputs": {}, "fields": { "SOUND_MENU": [ @@ -7507,24 +7866,24 @@ "shadow": true, "topLevel": false }, - "gd-stage-164": { + "gd-stage-179": { "opcode": "sound_play", - "next": "gd-stage-165", - "parent": "gd-stage-162", + "next": "gd-stage-180", + "parent": "gd-stage-177", "inputs": { "SOUND_MENU": [ 1, - "gd-stage-163" + "gd-stage-178" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-165": { + "gd-stage-180": { "opcode": "event_broadcast", - "next": "gd-stage-161", - "parent": "gd-stage-164", + "next": "gd-stage-176", + "parent": "gd-stage-179", "inputs": { "BROADCAST_INPUT": [ 1, @@ -7539,50 +7898,50 @@ "shadow": false, "topLevel": false }, - "gd-stage-166": { + "gd-stage-181": { "opcode": "control_if", "next": null, - "parent": "gd-stage-167", + "parent": "gd-stage-182", "inputs": { "CONDITION": [ 2, - "gd-stage-158" + "gd-stage-173" ], "SUBSTACK": [ 2, - "gd-stage-162" + "gd-stage-177" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-167": { + "gd-stage-182": { "opcode": "control_if_else", "next": null, - "parent": "gd-stage-173", + "parent": "gd-stage-188", "inputs": { "CONDITION": [ 2, - "gd-stage-168" + "gd-stage-183" ], "SUBSTACK": [ 2, - "gd-stage-169" + "gd-stage-184" ], "SUBSTACK2": [ 2, - "gd-stage-166" + "gd-stage-181" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-168": { + "gd-stage-183": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-167", + "parent": "gd-stage-182", "inputs": { "OPERAND1": [ 3, @@ -7608,10 +7967,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-169": { + "gd-stage-184": { "opcode": "data_changevariableby", - "next": "gd-stage-171", - "parent": "gd-stage-167", + "next": "gd-stage-186", + "parent": "gd-stage-182", "inputs": { "VALUE": [ 1, @@ -7630,10 +7989,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-170": { + "gd-stage-185": { "opcode": "sound_sounds_menu", "next": null, - "parent": "gd-stage-171", + "parent": "gd-stage-186", "inputs": {}, "fields": { "SOUND_MENU": [ @@ -7644,24 +8003,24 @@ "shadow": true, "topLevel": false }, - "gd-stage-171": { + "gd-stage-186": { "opcode": "sound_play", - "next": "gd-stage-172", - "parent": "gd-stage-169", + "next": "gd-stage-187", + "parent": "gd-stage-184", "inputs": { "SOUND_MENU": [ 1, - "gd-stage-170" + "gd-stage-185" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-172": { + "gd-stage-187": { "opcode": "event_broadcast", "next": null, - "parent": "gd-stage-171", + "parent": "gd-stage-186", "inputs": { "BROADCAST_INPUT": [ 1, @@ -7676,28 +8035,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-173": { + "gd-stage-188": { "opcode": "control_if", "next": null, - "parent": "gd-stage-155", + "parent": "gd-stage-170", "inputs": { "CONDITION": [ 2, - "gd-stage-174" + "gd-stage-189" ], "SUBSTACK": [ 2, - "gd-stage-167" + "gd-stage-182" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-174": { + "gd-stage-189": { "opcode": "operator_gt", "next": null, - "parent": "gd-stage-173", + "parent": "gd-stage-188", "inputs": { "OPERAND1": [ 3, @@ -7723,14 +8082,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-175": { + "gd-stage-190": { "opcode": "procedures_definition", - "next": "gd-stage-177", + "next": "gd-stage-192", "parent": null, "inputs": { "custom_block": [ 1, - "gd-stage-176" + "gd-stage-191" ] }, "fields": {}, @@ -7739,10 +8098,10 @@ "x": 20, "y": 1070 }, - "gd-stage-176": { + "gd-stage-191": { "opcode": "procedures_prototype", "next": null, - "parent": "gd-stage-175", + "parent": "gd-stage-190", "inputs": {}, "fields": {}, "shadow": true, @@ -7757,10 +8116,10 @@ "warp": "true" } }, - "gd-stage-177": { + "gd-stage-192": { "opcode": "data_replaceitemoflist", - "next": "gd-stage-178", - "parent": "gd-stage-175", + "next": "gd-stage-193", + "parent": "gd-stage-190", "inputs": { "INDEX": [ 3, @@ -7791,10 +8150,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-178": { + "gd-stage-193": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-177", + "parent": "gd-stage-192", "inputs": {}, "fields": {}, "shadow": false, @@ -7807,14 +8166,14 @@ "warp": "true" } }, - "gd-stage-179": { + "gd-stage-194": { "opcode": "procedures_definition", - "next": "gd-stage-181", + "next": "gd-stage-196", "parent": null, "inputs": { "custom_block": [ 1, - "gd-stage-180" + "gd-stage-195" ] }, "fields": {}, @@ -7823,10 +8182,10 @@ "x": 20, "y": 1220 }, - "gd-stage-180": { + "gd-stage-195": { "opcode": "procedures_prototype", "next": null, - "parent": "gd-stage-179", + "parent": "gd-stage-194", "inputs": {}, "fields": {}, "shadow": true, @@ -7841,10 +8200,10 @@ "warp": "true" } }, - "gd-stage-181": { + "gd-stage-196": { "opcode": "data_setvariableto", - "next": "gd-stage-182", - "parent": "gd-stage-179", + "next": "gd-stage-197", + "parent": "gd-stage-194", "inputs": { "VALUE": [ 1, @@ -7863,10 +8222,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-182": { + "gd-stage-197": { "opcode": "data_setvariableto", - "next": "gd-stage-183", - "parent": "gd-stage-181", + "next": "gd-stage-198", + "parent": "gd-stage-196", "inputs": { "VALUE": [ 1, @@ -7885,10 +8244,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-183": { + "gd-stage-198": { "opcode": "control_repeat", "next": null, - "parent": "gd-stage-182", + "parent": "gd-stage-197", "inputs": { "TIMES": [ 1, @@ -7899,17 +8258,17 @@ ], "SUBSTACK": [ 2, - "gd-stage-191" + "gd-stage-206" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-184": { + "gd-stage-199": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-187", + "parent": "gd-stage-202", "inputs": { "OPERAND1": [ 3, @@ -7935,10 +8294,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-185": { + "gd-stage-200": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-186", + "parent": "gd-stage-201", "inputs": { "INDEX": [ 3, @@ -7962,14 +8321,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-186": { + "gd-stage-201": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-187", + "parent": "gd-stage-202", "inputs": { "OPERAND1": [ 2, - "gd-stage-185" + "gd-stage-200" ], "OPERAND2": [ 1, @@ -7983,28 +8342,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-187": { + "gd-stage-202": { "opcode": "operator_and", "next": null, - "parent": "gd-stage-191", + "parent": "gd-stage-206", "inputs": { "OPERAND1": [ 2, - "gd-stage-184" + "gd-stage-199" ], "OPERAND2": [ 2, - "gd-stage-186" + "gd-stage-201" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-188": { + "gd-stage-203": { "opcode": "data_replaceitemoflist", - "next": "gd-stage-189", - "parent": "gd-stage-191", + "next": "gd-stage-204", + "parent": "gd-stage-206", "inputs": { "INDEX": [ 3, @@ -8035,10 +8394,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-189": { + "gd-stage-204": { "opcode": "data_replaceitemoflist", - "next": "gd-stage-190", - "parent": "gd-stage-188", + "next": "gd-stage-205", + "parent": "gd-stage-203", "inputs": { "INDEX": [ 3, @@ -8069,10 +8428,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-190": { + "gd-stage-205": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-189", + "parent": "gd-stage-204", "inputs": { "VALUE": [ 3, @@ -8096,28 +8455,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-191": { + "gd-stage-206": { "opcode": "control_if", - "next": "gd-stage-192", - "parent": "gd-stage-183", + "next": "gd-stage-207", + "parent": "gd-stage-198", "inputs": { "CONDITION": [ 2, - "gd-stage-187" + "gd-stage-202" ], "SUBSTACK": [ 2, - "gd-stage-188" + "gd-stage-203" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-192": { + "gd-stage-207": { "opcode": "data_changevariableby", "next": null, - "parent": "gd-stage-191", + "parent": "gd-stage-206", "inputs": { "VALUE": [ 1, @@ -8136,9 +8495,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-193": { + "gd-stage-208": { "opcode": "event_whenflagclicked", - "next": "gd-stage-194", + "next": "gd-stage-209", "parent": null, "inputs": {}, "fields": {}, @@ -8147,10 +8506,10 @@ "x": 20, "y": 1370 }, - "gd-stage-194": { + "gd-stage-209": { "opcode": "data_setvariableto", - "next": "gd-stage-195", - "parent": "gd-stage-193", + "next": "gd-stage-210", + "parent": "gd-stage-208", "inputs": { "VALUE": [ 1, @@ -8169,10 +8528,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-195": { + "gd-stage-210": { "opcode": "data_setvariableto", - "next": "gd-stage-196", - "parent": "gd-stage-194", + "next": "gd-stage-211", + "parent": "gd-stage-209", "inputs": { "VALUE": [ 1, @@ -8191,10 +8550,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-196": { + "gd-stage-211": { "opcode": "data_setvariableto", - "next": "gd-stage-197", - "parent": "gd-stage-195", + "next": "gd-stage-212", + "parent": "gd-stage-210", "inputs": { "VALUE": [ 1, @@ -8213,10 +8572,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-197": { + "gd-stage-212": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-196", + "parent": "gd-stage-211", "inputs": { "director-destination": [ 1, @@ -8244,9 +8603,9 @@ "warp": "false" } }, - "gd-stage-198": { + "gd-stage-213": { "opcode": "event_whenkeypressed", - "next": "gd-stage-200", + "next": "gd-stage-215", "parent": null, "inputs": {}, "fields": { @@ -8260,10 +8619,10 @@ "x": 20, "y": 1520 }, - "gd-stage-199": { + "gd-stage-214": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-200", + "parent": "gd-stage-215", "inputs": { "director-destination": [ 1, @@ -8291,28 +8650,28 @@ "warp": "false" } }, - "gd-stage-200": { + "gd-stage-215": { "opcode": "control_if", "next": null, - "parent": "gd-stage-198", + "parent": "gd-stage-213", "inputs": { "CONDITION": [ 2, - "gd-stage-201" + "gd-stage-216" ], "SUBSTACK": [ 2, - "gd-stage-199" + "gd-stage-214" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-201": { + "gd-stage-216": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-200", + "parent": "gd-stage-215", "inputs": { "OPERAND1": [ 3, @@ -8338,9 +8697,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-202": { + "gd-stage-217": { "opcode": "event_whenkeypressed", - "next": "gd-stage-206", + "next": "gd-stage-221", "parent": null, "inputs": {}, "fields": { @@ -8354,10 +8713,10 @@ "x": 20, "y": 1670 }, - "gd-stage-203": { + "gd-stage-218": { "opcode": "data_changevariableby", - "next": "gd-stage-204", - "parent": "gd-stage-206", + "next": "gd-stage-219", + "parent": "gd-stage-221", "inputs": { "VALUE": [ 1, @@ -8376,10 +8735,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-204": { + "gd-stage-219": { "opcode": "event_broadcast", - "next": "gd-stage-205", - "parent": "gd-stage-203", + "next": "gd-stage-220", + "parent": "gd-stage-218", "inputs": { "BROADCAST_INPUT": [ 1, @@ -8394,10 +8753,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-205": { + "gd-stage-220": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-204", + "parent": "gd-stage-219", "inputs": { "director-destination": [ 1, @@ -8425,28 +8784,28 @@ "warp": "false" } }, - "gd-stage-206": { + "gd-stage-221": { "opcode": "control_if", "next": null, - "parent": "gd-stage-202", + "parent": "gd-stage-217", "inputs": { "CONDITION": [ 2, - "gd-stage-207" + "gd-stage-222" ], "SUBSTACK": [ 2, - "gd-stage-203" + "gd-stage-218" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-207": { + "gd-stage-222": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-206", + "parent": "gd-stage-221", "inputs": { "OPERAND1": [ 3, @@ -8472,9 +8831,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-208": { + "gd-stage-223": { "opcode": "event_whenkeypressed", - "next": "gd-stage-212", + "next": "gd-stage-227", "parent": null, "inputs": {}, "fields": { @@ -8488,10 +8847,10 @@ "x": 20, "y": 1820 }, - "gd-stage-209": { + "gd-stage-224": { "opcode": "data_setvariableto", - "next": "gd-stage-210", - "parent": "gd-stage-212", + "next": "gd-stage-225", + "parent": "gd-stage-227", "inputs": { "VALUE": [ 1, @@ -8510,10 +8869,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-210": { + "gd-stage-225": { "opcode": "event_broadcast", - "next": "gd-stage-211", - "parent": "gd-stage-209", + "next": "gd-stage-226", + "parent": "gd-stage-224", "inputs": { "BROADCAST_INPUT": [ 1, @@ -8528,10 +8887,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-211": { + "gd-stage-226": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-210", + "parent": "gd-stage-225", "inputs": { "director-destination": [ 1, @@ -8559,28 +8918,28 @@ "warp": "false" } }, - "gd-stage-212": { + "gd-stage-227": { "opcode": "control_if", "next": null, - "parent": "gd-stage-208", + "parent": "gd-stage-223", "inputs": { "CONDITION": [ 2, - "gd-stage-213" + "gd-stage-228" ], "SUBSTACK": [ 2, - "gd-stage-209" + "gd-stage-224" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-213": { + "gd-stage-228": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-212", + "parent": "gd-stage-227", "inputs": { "OPERAND1": [ 3, @@ -8606,9 +8965,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-214": { + "gd-stage-229": { "opcode": "event_whenkeypressed", - "next": "gd-stage-218", + "next": "gd-stage-233", "parent": null, "inputs": {}, "fields": { @@ -8622,10 +8981,10 @@ "x": 20, "y": 1970 }, - "gd-stage-215": { + "gd-stage-230": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-216", + "parent": "gd-stage-231", "inputs": { "INDEX": [ 1, @@ -8644,14 +9003,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-216": { + "gd-stage-231": { "opcode": "data_setvariableto", - "next": "gd-stage-217", - "parent": "gd-stage-218", + "next": "gd-stage-232", + "parent": "gd-stage-233", "inputs": { "VALUE": [ 3, - "gd-stage-215", + "gd-stage-230", [ 10, "" @@ -8667,10 +9026,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-217": { + "gd-stage-232": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-216", + "parent": "gd-stage-231", "inputs": {}, "fields": {}, "shadow": false, @@ -8683,28 +9042,28 @@ "warp": "true" } }, - "gd-stage-218": { + "gd-stage-233": { "opcode": "control_if", "next": null, - "parent": "gd-stage-214", + "parent": "gd-stage-229", "inputs": { "CONDITION": [ 2, - "gd-stage-219" + "gd-stage-234" ], "SUBSTACK": [ 2, - "gd-stage-216" + "gd-stage-231" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-219": { + "gd-stage-234": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-218", + "parent": "gd-stage-233", "inputs": { "OPERAND1": [ 3, @@ -8730,9 +9089,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-220": { + "gd-stage-235": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-222", + "next": "gd-stage-237", "parent": null, "inputs": {}, "fields": { @@ -8746,10 +9105,10 @@ "x": 20, "y": 2120 }, - "gd-stage-221": { + "gd-stage-236": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-222", + "parent": "gd-stage-237", "inputs": { "director-destination": [ 1, @@ -8777,46 +9136,46 @@ "warp": "false" } }, - "gd-stage-222": { + "gd-stage-237": { "opcode": "control_if", "next": null, - "parent": "gd-stage-220", + "parent": "gd-stage-235", "inputs": { "CONDITION": [ 2, - "gd-stage-223" + "gd-stage-238" ], "SUBSTACK": [ 2, - "gd-stage-221" + "gd-stage-236" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-223": { + "gd-stage-238": { "opcode": "operator_or", "next": null, - "parent": "gd-stage-222", + "parent": "gd-stage-237", "inputs": { "OPERAND1": [ 2, - "gd-stage-224" + "gd-stage-239" ], "OPERAND2": [ 2, - "gd-stage-225" + "gd-stage-240" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-224": { + "gd-stage-239": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-223", + "parent": "gd-stage-238", "inputs": { "OPERAND1": [ 3, @@ -8842,10 +9201,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-225": { + "gd-stage-240": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-223", + "parent": "gd-stage-238", "inputs": { "OPERAND1": [ 3, @@ -8871,9 +9230,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-226": { + "gd-stage-241": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-233", + "next": "gd-stage-248", "parent": null, "inputs": {}, "fields": { @@ -8887,32 +9246,32 @@ "x": 20, "y": 2270 }, - "gd-stage-227": { + "gd-stage-242": { "opcode": "control_if_else", "next": null, - "parent": "gd-stage-233", + "parent": "gd-stage-248", "inputs": { "CONDITION": [ 2, - "gd-stage-228" + "gd-stage-243" ], "SUBSTACK": [ 2, - "gd-stage-229" + "gd-stage-244" ], "SUBSTACK2": [ 2, - "gd-stage-231" + "gd-stage-246" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-228": { + "gd-stage-243": { "opcode": "operator_gt", "next": null, - "parent": "gd-stage-227", + "parent": "gd-stage-242", "inputs": { "OPERAND1": [ 3, @@ -8938,10 +9297,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-229": { + "gd-stage-244": { "opcode": "data_setvariableto", - "next": "gd-stage-230", - "parent": "gd-stage-227", + "next": "gd-stage-245", + "parent": "gd-stage-242", "inputs": { "VALUE": [ 1, @@ -8960,10 +9319,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-230": { + "gd-stage-245": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-229", + "parent": "gd-stage-244", "inputs": { "director-destination": [ 1, @@ -8991,10 +9350,10 @@ "warp": "false" } }, - "gd-stage-231": { + "gd-stage-246": { "opcode": "data_setvariableto", - "next": "gd-stage-232", - "parent": "gd-stage-227", + "next": "gd-stage-247", + "parent": "gd-stage-242", "inputs": { "VALUE": [ 1, @@ -9013,10 +9372,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-232": { + "gd-stage-247": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-231", + "parent": "gd-stage-246", "inputs": { "director-destination": [ 1, @@ -9044,28 +9403,28 @@ "warp": "false" } }, - "gd-stage-233": { + "gd-stage-248": { "opcode": "control_if", "next": null, - "parent": "gd-stage-226", + "parent": "gd-stage-241", "inputs": { "CONDITION": [ 2, - "gd-stage-234" + "gd-stage-249" ], "SUBSTACK": [ 2, - "gd-stage-227" + "gd-stage-242" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-234": { + "gd-stage-249": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-233", + "parent": "gd-stage-248", "inputs": { "OPERAND1": [ 3, @@ -9091,9 +9450,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-235": { + "gd-stage-250": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-240", + "next": "gd-stage-255", "parent": null, "inputs": {}, "fields": { @@ -9107,10 +9466,10 @@ "x": 20, "y": 2420 }, - "gd-stage-236": { + "gd-stage-251": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-237", + "parent": "gd-stage-252", "inputs": { "INDEX": [ 1, @@ -9129,10 +9488,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-237": { + "gd-stage-252": { "opcode": "operator_gt", "next": null, - "parent": "gd-stage-238", + "parent": "gd-stage-253", "inputs": { "OPERAND1": [ 3, @@ -9148,21 +9507,21 @@ ], "OPERAND2": [ 2, - "gd-stage-236" + "gd-stage-251" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-238": { + "gd-stage-253": { "opcode": "data_setvariableto", - "next": "gd-stage-239", - "parent": "gd-stage-240", + "next": "gd-stage-254", + "parent": "gd-stage-255", "inputs": { "VALUE": [ 3, - "gd-stage-237", + "gd-stage-252", [ 10, "" @@ -9178,10 +9537,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-239": { + "gd-stage-254": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-238", + "parent": "gd-stage-253", "inputs": { "director-destination": [ 1, @@ -9209,28 +9568,28 @@ "warp": "false" } }, - "gd-stage-240": { + "gd-stage-255": { "opcode": "control_if", "next": null, - "parent": "gd-stage-235", + "parent": "gd-stage-250", "inputs": { "CONDITION": [ 2, - "gd-stage-241" + "gd-stage-256" ], "SUBSTACK": [ 2, - "gd-stage-238" + "gd-stage-253" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-241": { + "gd-stage-256": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-240", + "parent": "gd-stage-255", "inputs": { "OPERAND1": [ 3, @@ -9256,9 +9615,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-242": { + "gd-stage-257": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-250", + "next": "gd-stage-265", "parent": null, "inputs": {}, "fields": { @@ -9272,10 +9631,10 @@ "x": 20, "y": 2570 }, - "gd-stage-243": { + "gd-stage-258": { "opcode": "sound_sounds_menu", "next": null, - "parent": "gd-stage-244", + "parent": "gd-stage-259", "inputs": {}, "fields": { "SOUND_MENU": [ @@ -9286,56 +9645,56 @@ "shadow": true, "topLevel": false }, - "gd-stage-244": { + "gd-stage-259": { "opcode": "sound_playuntildone", - "next": "gd-stage-245", - "parent": "gd-stage-250", + "next": "gd-stage-260", + "parent": "gd-stage-265", "inputs": { "SOUND_MENU": [ 1, - "gd-stage-243" + "gd-stage-258" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-245": { + "gd-stage-260": { "opcode": "control_repeat_until", "next": null, - "parent": "gd-stage-244", + "parent": "gd-stage-259", "inputs": { "CONDITION": [ 2, - "gd-stage-246" + "gd-stage-261" ], "SUBSTACK": [ 2, - "gd-stage-249" + "gd-stage-264" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-246": { + "gd-stage-261": { "opcode": "operator_not", "next": null, - "parent": "gd-stage-245", + "parent": "gd-stage-260", "inputs": { "OPERAND": [ 2, - "gd-stage-247" + "gd-stage-262" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-247": { + "gd-stage-262": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-246", + "parent": "gd-stage-261", "inputs": { "OPERAND1": [ 3, @@ -9361,10 +9720,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-248": { + "gd-stage-263": { "opcode": "sound_sounds_menu", "next": null, - "parent": "gd-stage-249", + "parent": "gd-stage-264", "inputs": {}, "fields": { "SOUND_MENU": [ @@ -9375,42 +9734,42 @@ "shadow": true, "topLevel": false }, - "gd-stage-249": { + "gd-stage-264": { "opcode": "sound_playuntildone", "next": null, - "parent": "gd-stage-245", + "parent": "gd-stage-260", "inputs": { "SOUND_MENU": [ 1, - "gd-stage-248" + "gd-stage-263" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-250": { + "gd-stage-265": { "opcode": "control_if", "next": null, - "parent": "gd-stage-242", + "parent": "gd-stage-257", "inputs": { "CONDITION": [ 2, - "gd-stage-251" + "gd-stage-266" ], "SUBSTACK": [ 2, - "gd-stage-244" + "gd-stage-259" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-251": { + "gd-stage-266": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-250", + "parent": "gd-stage-265", "inputs": { "OPERAND1": [ 3, @@ -9436,9 +9795,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-252": { + "gd-stage-267": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-258", + "next": "gd-stage-273", "parent": null, "inputs": {}, "fields": { @@ -9452,42 +9811,42 @@ "x": 20, "y": 2720 }, - "gd-stage-253": { + "gd-stage-268": { "opcode": "control_repeat_until", "next": null, - "parent": "gd-stage-258", + "parent": "gd-stage-273", "inputs": { "CONDITION": [ 2, - "gd-stage-254" + "gd-stage-269" ], "SUBSTACK": [ 2, - "gd-stage-256" + "gd-stage-271" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-254": { + "gd-stage-269": { "opcode": "operator_not", "next": null, - "parent": "gd-stage-253", + "parent": "gd-stage-268", "inputs": { "OPERAND": [ 2, - "gd-stage-255" + "gd-stage-270" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-255": { + "gd-stage-270": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-254", + "parent": "gd-stage-269", "inputs": { "OPERAND1": [ 3, @@ -9513,10 +9872,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-256": { + "gd-stage-271": { "opcode": "procedures_call", - "next": "gd-stage-257", - "parent": "gd-stage-253", + "next": "gd-stage-272", + "parent": "gd-stage-268", "inputs": {}, "fields": {}, "shadow": false, @@ -9529,10 +9888,10 @@ "warp": "true" } }, - "gd-stage-257": { + "gd-stage-272": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-256", + "parent": "gd-stage-271", "inputs": {}, "fields": {}, "shadow": false, @@ -9545,28 +9904,28 @@ "warp": "true" } }, - "gd-stage-258": { + "gd-stage-273": { "opcode": "control_if", "next": null, - "parent": "gd-stage-252", + "parent": "gd-stage-267", "inputs": { "CONDITION": [ 2, - "gd-stage-259" + "gd-stage-274" ], "SUBSTACK": [ 2, - "gd-stage-253" + "gd-stage-268" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-259": { + "gd-stage-274": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-258", + "parent": "gd-stage-273", "inputs": { "OPERAND1": [ 3, @@ -9592,9 +9951,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-260": { + "gd-stage-275": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-264", + "next": "gd-stage-279", "parent": null, "inputs": {}, "fields": { @@ -9608,28 +9967,28 @@ "x": 20, "y": 2870 }, - "gd-stage-261": { + "gd-stage-276": { "opcode": "control_if", "next": null, - "parent": "gd-stage-273", + "parent": "gd-stage-288", "inputs": { "CONDITION": [ 2, - "gd-stage-262" + "gd-stage-277" ], "SUBSTACK": [ 2, - "gd-stage-263" + "gd-stage-278" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-262": { + "gd-stage-277": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-261", + "parent": "gd-stage-276", "inputs": { "OPERAND1": [ 3, @@ -9655,10 +10014,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-263": { + "gd-stage-278": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-261", + "parent": "gd-stage-276", "inputs": { "VALUE": [ 1, @@ -9677,10 +10036,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-264": { + "gd-stage-279": { "opcode": "procedures_call", - "next": "gd-stage-273", - "parent": "gd-stage-260", + "next": "gd-stage-288", + "parent": "gd-stage-275", "inputs": {}, "fields": {}, "shadow": false, @@ -9693,10 +10052,10 @@ "warp": "true" } }, - "gd-stage-265": { + "gd-stage-280": { "opcode": "data_setvariableto", - "next": "gd-stage-266", - "parent": "gd-stage-273", + "next": "gd-stage-281", + "parent": "gd-stage-288", "inputs": { "VALUE": [ 1, @@ -9715,10 +10074,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-266": { + "gd-stage-281": { "opcode": "data_setvariableto", - "next": "gd-stage-267", - "parent": "gd-stage-265", + "next": "gd-stage-282", + "parent": "gd-stage-280", "inputs": { "VALUE": [ 1, @@ -9737,10 +10096,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-267": { + "gd-stage-282": { "opcode": "data_setvariableto", - "next": "gd-stage-268", - "parent": "gd-stage-266", + "next": "gd-stage-283", + "parent": "gd-stage-281", "inputs": { "VALUE": [ 1, @@ -9759,10 +10118,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-268": { + "gd-stage-283": { "opcode": "data_setvariableto", - "next": "gd-stage-270", - "parent": "gd-stage-267", + "next": "gd-stage-285", + "parent": "gd-stage-282", "inputs": { "VALUE": [ 1, @@ -9781,10 +10140,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-269": { + "gd-stage-284": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-270", + "parent": "gd-stage-285", "inputs": { "INDEX": [ 1, @@ -9803,14 +10162,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-270": { + "gd-stage-285": { "opcode": "data_setvariableto", - "next": "gd-stage-272", - "parent": "gd-stage-268", + "next": "gd-stage-287", + "parent": "gd-stage-283", "inputs": { "VALUE": [ 3, - "gd-stage-269", + "gd-stage-284", [ 10, "" @@ -9826,10 +10185,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-271": { + "gd-stage-286": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-272", + "parent": "gd-stage-287", "inputs": { "INDEX": [ 1, @@ -9848,14 +10207,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-272": { + "gd-stage-287": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-270", + "parent": "gd-stage-285", "inputs": { "VALUE": [ 3, - "gd-stage-271", + "gd-stage-286", [ 10, "" @@ -9871,46 +10230,46 @@ "shadow": false, "topLevel": false }, - "gd-stage-273": { + "gd-stage-288": { "opcode": "control_if", - "next": "gd-stage-261", - "parent": "gd-stage-264", + "next": "gd-stage-276", + "parent": "gd-stage-279", "inputs": { "CONDITION": [ 2, - "gd-stage-274" + "gd-stage-289" ], "SUBSTACK": [ 2, - "gd-stage-265" + "gd-stage-280" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-274": { + "gd-stage-289": { "opcode": "operator_or", "next": null, - "parent": "gd-stage-273", + "parent": "gd-stage-288", "inputs": { "OPERAND1": [ 2, - "gd-stage-275" + "gd-stage-290" ], "OPERAND2": [ 2, - "gd-stage-276" + "gd-stage-291" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-275": { + "gd-stage-290": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-274", + "parent": "gd-stage-289", "inputs": { "OPERAND1": [ 3, @@ -9936,10 +10295,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-276": { + "gd-stage-291": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-274", + "parent": "gd-stage-289", "inputs": { "OPERAND1": [ 3, @@ -9965,9 +10324,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-277": { + "gd-stage-292": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-286", + "next": "gd-stage-301", "parent": null, "inputs": {}, "fields": { @@ -9981,10 +10340,10 @@ "x": 20, "y": 3020 }, - "gd-stage-278": { + "gd-stage-293": { "opcode": "data_setvariableto", - "next": "gd-stage-279", - "parent": "gd-stage-286", + "next": "gd-stage-294", + "parent": "gd-stage-301", "inputs": { "VALUE": [ 1, @@ -10003,10 +10362,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-279": { + "gd-stage-294": { "opcode": "data_setvariableto", - "next": "gd-stage-280", - "parent": "gd-stage-278", + "next": "gd-stage-295", + "parent": "gd-stage-293", "inputs": { "VALUE": [ 1, @@ -10025,10 +10384,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-280": { + "gd-stage-295": { "opcode": "data_setvariableto", - "next": "gd-stage-282", - "parent": "gd-stage-279", + "next": "gd-stage-297", + "parent": "gd-stage-294", "inputs": { "VALUE": [ 1, @@ -10047,10 +10406,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-281": { + "gd-stage-296": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-282", + "parent": "gd-stage-297", "inputs": { "INDEX": [ 3, @@ -10074,14 +10433,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-282": { + "gd-stage-297": { "opcode": "data_setvariableto", - "next": "gd-stage-284", - "parent": "gd-stage-280", + "next": "gd-stage-299", + "parent": "gd-stage-295", "inputs": { "VALUE": [ 3, - "gd-stage-281", + "gd-stage-296", [ 10, "" @@ -10097,10 +10456,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-283": { + "gd-stage-298": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-284", + "parent": "gd-stage-299", "inputs": { "INDEX": [ 3, @@ -10124,14 +10483,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-284": { + "gd-stage-299": { "opcode": "data_setvariableto", - "next": "gd-stage-285", - "parent": "gd-stage-282", + "next": "gd-stage-300", + "parent": "gd-stage-297", "inputs": { "VALUE": [ 3, - "gd-stage-283", + "gd-stage-298", [ 10, "" @@ -10147,10 +10506,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-285": { + "gd-stage-300": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-284", + "parent": "gd-stage-299", "inputs": { "VALUE": [ 1, @@ -10169,46 +10528,46 @@ "shadow": false, "topLevel": false }, - "gd-stage-286": { + "gd-stage-301": { "opcode": "control_if", - "next": "gd-stage-290", - "parent": "gd-stage-277", + "next": "gd-stage-305", + "parent": "gd-stage-292", "inputs": { "CONDITION": [ 2, - "gd-stage-287" + "gd-stage-302" ], "SUBSTACK": [ 2, - "gd-stage-278" + "gd-stage-293" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-287": { + "gd-stage-302": { "opcode": "operator_or", "next": null, - "parent": "gd-stage-286", + "parent": "gd-stage-301", "inputs": { "OPERAND1": [ 2, - "gd-stage-288" + "gd-stage-303" ], "OPERAND2": [ 2, - "gd-stage-289" + "gd-stage-304" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-288": { + "gd-stage-303": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-287", + "parent": "gd-stage-302", "inputs": { "OPERAND1": [ 3, @@ -10234,10 +10593,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-289": { + "gd-stage-304": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-287", + "parent": "gd-stage-302", "inputs": { "OPERAND1": [ 3, @@ -10263,28 +10622,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-290": { + "gd-stage-305": { "opcode": "control_if", "next": null, - "parent": "gd-stage-286", + "parent": "gd-stage-301", "inputs": { "CONDITION": [ 2, - "gd-stage-291" + "gd-stage-306" ], "SUBSTACK": [ 2, - "gd-stage-299" + "gd-stage-314" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-291": { + "gd-stage-306": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-290", + "parent": "gd-stage-305", "inputs": { "OPERAND1": [ 3, @@ -10310,28 +10669,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-292": { + "gd-stage-307": { "opcode": "operator_and", "next": null, - "parent": "gd-stage-299", + "parent": "gd-stage-314", "inputs": { "OPERAND1": [ 2, - "gd-stage-293" + "gd-stage-308" ], "OPERAND2": [ 2, - "gd-stage-294" + "gd-stage-309" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-293": { + "gd-stage-308": { "opcode": "operator_gt", "next": null, - "parent": "gd-stage-292", + "parent": "gd-stage-307", "inputs": { "OPERAND1": [ 3, @@ -10357,10 +10716,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-294": { + "gd-stage-309": { "opcode": "operator_gt", "next": null, - "parent": "gd-stage-292", + "parent": "gd-stage-307", "inputs": { "OPERAND1": [ 1, @@ -10386,32 +10745,32 @@ "shadow": false, "topLevel": false }, - "gd-stage-295": { + "gd-stage-310": { "opcode": "control_if_else", "next": null, - "parent": "gd-stage-299", + "parent": "gd-stage-314", "inputs": { "CONDITION": [ 2, - "gd-stage-296" + "gd-stage-311" ], "SUBSTACK": [ 2, - "gd-stage-297" + "gd-stage-312" ], "SUBSTACK2": [ 2, - "gd-stage-298" + "gd-stage-313" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-296": { + "gd-stage-311": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-295", + "parent": "gd-stage-310", "inputs": { "OPERAND1": [ 3, @@ -10437,10 +10796,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-297": { + "gd-stage-312": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-295", + "parent": "gd-stage-310", "inputs": { "VALUE": [ 1, @@ -10459,10 +10818,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-298": { + "gd-stage-313": { "opcode": "data_changevariableby", "next": null, - "parent": "gd-stage-295", + "parent": "gd-stage-310", "inputs": { "VALUE": [ 1, @@ -10481,28 +10840,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-299": { + "gd-stage-314": { "opcode": "control_if", - "next": "gd-stage-300", - "parent": "gd-stage-290", + "next": "gd-stage-315", + "parent": "gd-stage-305", "inputs": { "CONDITION": [ 2, - "gd-stage-292" + "gd-stage-307" ], "SUBSTACK": [ 2, - "gd-stage-295" + "gd-stage-310" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-300": { + "gd-stage-315": { "opcode": "data_setvariableto", - "next": "gd-stage-301", - "parent": "gd-stage-299", + "next": "gd-stage-316", + "parent": "gd-stage-314", "inputs": { "VALUE": [ 1, @@ -10521,10 +10880,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-301": { + "gd-stage-316": { "opcode": "data_setvariableto", - "next": "gd-stage-303", - "parent": "gd-stage-300", + "next": "gd-stage-318", + "parent": "gd-stage-315", "inputs": { "VALUE": [ 1, @@ -10543,10 +10902,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-302": { + "gd-stage-317": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-303", + "parent": "gd-stage-318", "inputs": { "INDEX": [ 3, @@ -10570,14 +10929,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-303": { + "gd-stage-318": { "opcode": "data_setvariableto", - "next": "gd-stage-305", - "parent": "gd-stage-301", + "next": "gd-stage-320", + "parent": "gd-stage-316", "inputs": { "VALUE": [ 3, - "gd-stage-302", + "gd-stage-317", [ 10, "" @@ -10593,10 +10952,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-304": { + "gd-stage-319": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-305", + "parent": "gd-stage-320", "inputs": { "INDEX": [ 3, @@ -10620,14 +10979,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-305": { + "gd-stage-320": { "opcode": "data_setvariableto", - "next": "gd-stage-306", - "parent": "gd-stage-303", + "next": "gd-stage-321", + "parent": "gd-stage-318", "inputs": { "VALUE": [ 3, - "gd-stage-304", + "gd-stage-319", [ 10, "" @@ -10643,10 +11002,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-306": { + "gd-stage-321": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-305", + "parent": "gd-stage-320", "inputs": { "VALUE": [ 1, @@ -10665,9 +11024,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-307": { + "gd-stage-322": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-311", + "next": "gd-stage-326", "parent": null, "inputs": {}, "fields": { @@ -10681,10 +11040,10 @@ "x": 20, "y": 3170 }, - "gd-stage-308": { + "gd-stage-323": { "opcode": "data_setvariableto", - "next": "gd-stage-309", - "parent": "gd-stage-311", + "next": "gd-stage-324", + "parent": "gd-stage-326", "inputs": { "VALUE": [ 1, @@ -10703,10 +11062,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-309": { + "gd-stage-324": { "opcode": "data_setvariableto", - "next": "gd-stage-310", - "parent": "gd-stage-308", + "next": "gd-stage-325", + "parent": "gd-stage-323", "inputs": { "VALUE": [ 1, @@ -10725,10 +11084,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-310": { + "gd-stage-325": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-309", + "parent": "gd-stage-324", "inputs": { "VALUE": [ 1, @@ -10747,46 +11106,46 @@ "shadow": false, "topLevel": false }, - "gd-stage-311": { + "gd-stage-326": { "opcode": "control_if", "next": null, - "parent": "gd-stage-307", + "parent": "gd-stage-322", "inputs": { "CONDITION": [ 2, - "gd-stage-312" + "gd-stage-327" ], "SUBSTACK": [ 2, - "gd-stage-308" + "gd-stage-323" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-312": { + "gd-stage-327": { "opcode": "operator_or", "next": null, - "parent": "gd-stage-311", + "parent": "gd-stage-326", "inputs": { "OPERAND1": [ 2, - "gd-stage-313" + "gd-stage-328" ], "OPERAND2": [ 2, - "gd-stage-314" + "gd-stage-329" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-313": { + "gd-stage-328": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-312", + "parent": "gd-stage-327", "inputs": { "OPERAND1": [ 3, @@ -10812,10 +11171,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-314": { + "gd-stage-329": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-312", + "parent": "gd-stage-327", "inputs": { "OPERAND1": [ 3, diff --git a/src/xevious/runtime_identifiers.json b/src/xevious/runtime_identifiers.json index 5f0ecdd..744e67a 100644 --- a/src/xevious/runtime_identifiers.json +++ b/src/xevious/runtime_identifiers.json @@ -89,6 +89,11 @@ "name": "bullet cursor", "scope": "Stage" }, + "difficulty-ai-adjust": { + "kind": "variable", + "name": "ai adjust", + "scope": "Stage" + }, "difficulty-ai-level": { "kind": "variable", "name": "ai level", diff --git a/tests/test_scratch_project.py b/tests/test_scratch_project.py index 6e35c69..0ff4998 100644 --- a/tests/test_scratch_project.py +++ b/tests/test_scratch_project.py @@ -892,6 +892,8 @@ def test_game_director_has_one_stage_owned_transition_path(self) -> None: "qualified", # FORM-01 transient formation-lookup register (overwritten on every selection). "formation index", + # DIF-02 transient score re-tune addend (computed then added to the AI level). + "ai adjust", } # ECO economy state — Stage-written, HUD reads only. Held in its own category and # enforced Stage-only-write below (a HUD sprite writing `score` is the bug this guards). @@ -2467,12 +2469,22 @@ def break_g(p): break def break_decision(p): - b = find( - lambda b: b["opcode"] == "operator_gt" - and isinstance(b["inputs"].get("OPERAND1"), list) - and b["inputs"]["OPERAND1"][1][2:3] == [director.LIVES_ID] - )(p) - b["inputs"]["OPERAND1"][1][2] = director.SCORE_ID # decide from score, not craft + # Target the DEATH-decision `craft > threshold` specifically — the operator_gt that is the + # CONDITION of the control_if_else (as _ply02_failures identifies it), not any other craft + # comparison on the Stage (e.g. DIF-02's `craft > 0` re-tune guard). + s = next(t for t in p["targets"] if t["isStage"]) + blocks = s["blocks"] + decision = next( + b + for b in blocks.values() + if b["opcode"] == "control_if_else" + and isinstance(b["inputs"].get("CONDITION"), list) + and blocks.get(b["inputs"]["CONDITION"][1], {}).get("opcode") == "operator_gt" + and blocks[b["inputs"]["CONDITION"][1]]["inputs"].get("OPERAND1", [None, [None]])[1][2:3] + == [director.LIVES_ID] + ) + cond = blocks[decision["inputs"]["CONDITION"][1]] + cond["inputs"]["OPERAND1"][1][2] = director.SCORE_ID # decide from score, not craft cases = [ ("d-decrements-craft", break_d), @@ -4423,7 +4435,7 @@ def test_full_repository_verification(self) -> None: original_hash, ) self.assertEqual( - "89b9b90e8730d0b85a2f83b6fe612a86dc0be2e1ff21184e9ba43909412af57a", + "922a237830cbb6042942b24557e6fa6ac9b6920e0fb55f8798586d078d73fdeb", build_hash, ) diff --git a/tests/test_spec_docs.py b/tests/test_spec_docs.py index 53f80fc..c1c3f1c 100644 --- a/tests/test_spec_docs.py +++ b/tests/test_spec_docs.py @@ -621,6 +621,22 @@ def raise_once(ai): self.assertEqual(65, raise_once(127)) # 129 -> fold -> 65 self.assertLess(raise_once(127), director.AI_LEVEL_FOLD_THRESHOLD) + def test_score_retune_rule(self): + # DIF-02 score-adaptive re-tune (sub_2_fn_23 / avg_score_per_solvalou): the addend is the + # player's score in thousands divided by the craft in reserve, floored, capped at 16, and + # only when reserve > 0 (no divide-by-zero). Reserve is the live `craft` count (the reference + # divides by solvalou_number with no subtraction). + def retune(score, craft): + if craft <= 0: + return 0 + return min(16, (score // 1000) // craft) + + self.assertEqual(0, retune(500, 3), "score below 1000 adds nothing") + self.assertEqual(1, retune(3000, 3), "3k over 3 craft -> 1") + self.assertEqual(5, retune(20000, 4), "20k over 4 craft -> 5") + self.assertEqual(16, retune(200000, 3), "66 over 3 = 22, capped at 16") + self.assertEqual(0, retune(50000, 0), "zero craft is guarded, adds nothing") + def test_formation_index_in_domain_over_committed_schedules(self): # FORM-01 / DIF-01 range proof: walk the committed schedules in the accelerated 1..16 then # 7..16 loop order, tracking the AI level through raises (fold-back) and picking the formation diff --git a/tools/game_director.py b/tools/game_director.py index 0abfa76..c3f8877 100644 --- a/tools/game_director.py +++ b/tools/game_director.py @@ -408,6 +408,7 @@ def _load_terrain_columns() -> list[int]: FORMATION_COUNT_ID = "formation-count" FORMATION_TYPE_OFFSET_ID = "formation-type-offset" FORMATION_INDEX_ID = "formation-index" # transient lookup index (machinery) +AI_ADJUST_ID = "difficulty-ai-adjust" # DIF-02 transient score re-tune addend (machinery) SCHEDULE_ARG_ID = "area-schedule-arg" # 4th parallel schedule column (runtime scalar) DIFFICULTY_INCREMENT_ID = "difficulty-increment" # baked [2,0,6,16], indexed by DIP FORMATION_COUNT_TABLE_ID = "formation-count-table" # 160 entries, index -32..127 @@ -1478,6 +1479,43 @@ def arg_at_cursor() -> str: raise_branch = blocks.if_reporter( blocks.op_eq(handler_at_cursor(), text(RAISE_HANDLER)), raise_body ) + # DIF-02 score re-tune: add floor(floor(score / 1000) / craft), capped at 16, to the AI level — + # so a player scoring heavily with craft in reserve meets sharper pressure. Guarded on craft > 0 + # (no divide-by-zero). Unlike the raise, the reference does NOT fold this add back. + adjust_branch = blocks.if_reporter( + blocks.op_eq(handler_at_cursor(), text(ADJUST_HANDLER)), + [ + blocks.if_reporter( + blocks.op_gt(variable("craft", LIVES_ID), number(0)), + [ + blocks.set_var_expr( + "ai adjust", + AI_ADJUST_ID, + blocks.op_floor( + blocks.op_div( + blocks.op_floor( + blocks.op_div(variable("score", SCORE_ID), number(1000)) + ), + variable("craft", LIVES_ID), + ) + ), + ), + blocks.if_reporter( + blocks.op_gt(variable("ai adjust", AI_ADJUST_ID), number(16)), + [blocks.set_var("ai adjust", AI_ADJUST_ID, number(16))], + ), + blocks.set_var_expr( + "ai level", + AI_LEVEL_ID, + blocks.op_add( + variable("ai level", AI_LEVEL_ID), + variable("ai adjust", AI_ADJUST_ID), + ), + ), + ], + ) + ], + ) # FORM-01 set-formation: the record's signed offset IS the table index (no AI level added). set_branch = blocks.if_reporter( blocks.op_eq(handler_at_cursor(), text(SET_FORMATION_HANDLER)), @@ -1499,6 +1537,7 @@ def arg_at_cursor() -> str: loop, [ raise_branch, + adjust_branch, set_branch, reset_branch, blocks.change_var("schedule fired", SCHEDULE_FIRED_ID, 1), @@ -2861,6 +2900,7 @@ def expected_project(project: dict[str, Any]) -> dict[str, Any]: FORMATION_COUNT_ID, FORMATION_TYPE_OFFSET_ID, FORMATION_INDEX_ID, + AI_ADJUST_ID, } preserved_variables = { variable_id: value @@ -2926,6 +2966,8 @@ def expected_project(project: dict[str, Any]) -> dict[str, Any]: FORMATION_COUNT_ID: ["formation count", 0], FORMATION_TYPE_OFFSET_ID: ["formation type offset", 0], FORMATION_INDEX_ID: ["formation index", 0], + # DIF-02 transient score re-tune addend (machinery, like `formation index`). + AI_ADJUST_ID: ["ai adjust", 0], } owned_lists = { ALLOWED_ID, From e29f461808fb02185ffebed5afceaa648e940744 Mon Sep 17 00:00:00 2001 From: Shane Kidd <33380501+StarshipSuperjam@users.noreply.github.com> Date: Sat, 15 Aug 2026 13:49:00 -0700 Subject: [PATCH 4/5] Feature: per-family fire-permission masks (DIF-03) Wire the eight fire_mask_ handlers and ground_stop_firing_row into the schedule dispatch: each sets its Stage variable from the schedule arg column as its record fires. The eight branches + variables are generated from one family table (FIRE_MASK_FAMILIES) so a family cannot be half-wired; all reset to 0 on a world reset via difficulty_reset. Held as eight named variables (not one indexed list) because the slice-8 consumers are per-family sprites reading one mask each. The per-family FIRING that consumes these masks is the enemy slices' (8+). Verification: the mask bytes round-trip via the schedule arg golden; a live scratch-vm scenario (fire-permission-masks) confirms the masks are set to their scheduled values, with a biting negative on the logram branch. Record 022; catalog DIF-03 -> present. Also adds the roadmap closure-evidence markers for leaf #56 (DIF-01/02/03/FORM-01 model obligations) to the difficulty model-fixture class, per the dependency-aware roadmap contract merged (#36) while this slice was in flight. build_hash re-pinned; two builds byte-identical + round-trip; full suite + harness green. Co-Authored-By: Claude Opus 4.8 --- docs/MECHANICS_CATALOG.md | 2 +- docs/mechanics/022-fire-permission-masks.md | 15 + harness/lib/catalog.js | 36 + src/xevious/project.json | 2402 ++++++++++++++----- src/xevious/runtime_identifiers.json | 45 + tests/test_scratch_project.py | 16 +- tests/test_spec_docs.py | 14 + tools/game_director.py | 44 + 8 files changed, 2009 insertions(+), 565 deletions(-) create mode 100644 docs/mechanics/022-fire-permission-masks.md diff --git a/docs/MECHANICS_CATALOG.md b/docs/MECHANICS_CATALOG.md index 5954569..c9cbe82 100644 --- a/docs/MECHANICS_CATALOG.md +++ b/docs/MECHANICS_CATALOG.md @@ -51,7 +51,7 @@ document differ, the spec document wins. | AREA-04 | Transitions and 16-to-7 loop | present | AREA-03 | main: `main_gameplay_loop`; sub: `sub_fn_3__handle_next_area` | Areas advance 1–16 then continue at 7, with no win screen. The advance/wrap shipped in AREA-01; with all 16 schedules ingested the loop is data-complete and the accelerated trace confirms 1–16→7 with no win screen ([018](mechanics/018-area-transitions-and-loop.md)) — a data trace, runtime traversal on the operator playtest. | | DIF-01 | Difficulty setting | present | AREA-02 | sub: `difficulty_tbl`, `sub_2_fn_3__inc_enemy_AI_and_flying_enemies` | Each normal setting starts at its recorded pressure. The adaptive AI level accumulates live from the schedule's raise records and folds back below 0x80 ([019](mechanics/019-difficulty-ai-level.md)); foundation — the AI level is live/observable, its consumption as enemy pressure is slices 8+, and the cabinet DIP is a project-defined placeholder (increment +2). | | DIF-02 | Score-per-life adaptive AI | present | DIF-01, ECO-01 | sub: `sub_2_fn_23__adjust_AI_level_based_on_score`, `avg_score_per_solvalou` | Fixtures show ordered AI changes from score per craft. The adjust records re-tune the AI level by floor(floor(score/1000)/craft) capped at 16, reading the live score and craft ([021](mechanics/021-score-adaptive-ai-level.md)); foundation — the rule is live and fixture-proven, the visible "playing better = harder" difference needs enemies (slice 8+). | -| DIF-03 | Per-family fire frequency | missing | DIF-01, SYS-04 | sub: `sub_2_fn_8__fire_freq_mask_derota` through `sub_2_fn_22__fire_freq_mask_andor_genesis` | Family fire fixtures follow recorded masks. | +| DIF-03 | Per-family fire frequency | present | DIF-01, SYS-04 | sub: `sub_2_fn_8__fire_freq_mask_derota` through `sub_2_fn_22__fire_freq_mask_andor_genesis` | Family fire fixtures follow recorded masks. The area schedule sets the eight per-family fire-permission masks + the ground-stop-firing row live from the record bytes ([022](mechanics/022-fire-permission-masks.md)); foundation — the masks are set/observable, the firing that consumes them is slices 8+. | | FORM-01 | Normal flying formations | present | AREA-02, DIF-01 | sub: `flying_enemy_type_offset_tbl_normal`, `sub_2_fn_2__set_flying_enemies` | Fixtures preserve normal type, count, offsets, and order. The wave size + type-table offset are selected live — set-formation by the record offset, raise by the folded AI level, reset zeroes ([020](mechanics/020-normal-flying-formations.md)); foundation — selection is live/observable, spawning the wave is slice 8. | ## Flying enemies and projectiles diff --git a/docs/mechanics/022-fire-permission-masks.md b/docs/mechanics/022-fire-permission-masks.md new file mode 100644 index 0000000..bbbf67c --- /dev/null +++ b/docs/mechanics/022-fire-permission-masks.md @@ -0,0 +1,15 @@ +# Fire-permission masks — which enemy families may fire, and how often + +- Mechanic: DIF-03 (partial, foundation) — the area schedule sets one fire-permission mask byte per firing family, plus a ground-stop-firing row. A family's mask gates how often its members may fire; the per-family firing that consumes each mask arrives with the enemy slices (8+). +- Derived behavior: While an area scrolls, `fire_mask_` records set that family's mask byte for the eight firing families — Derota, Logram, Zoshi, Terrazi, Kapi, Boza Logram, Domogram, and Andor Genesis — and a `ground_stop_firing_row` record sets the row at which the ground families stop firing. Like the AI level and formation, these are per-player game state: they persist across death and respawn and reset for a new game. +- Reference provenance: `jotd666/xevious@71473685a8c7856c8401c8519276cd97a38d4183`; `src/xevious_sub.68k`: `sub_2_fn_8` through `sub_2_fn_22` (375–419) — the per-family mask setters and the ground-stop-firing row. Every mask value each area sets, with its trigger row, is the committed, hash-pinned data in [docs/spec/data/area-schedules.json](../spec/data/area-schedules.json); the behaviour is the settled [difficulty and formations](../spec/difficulty-and-formations.md) document, which delegates the firing that consumes each mask to the family documents. +- Transfer class: General behavior and numeric constant (derived per-family byte values; no source text or media copied). +- Scratch interpretation: The Stage owns eight `fire mask ` variables and `ground stop firing row`. Each `fire_mask_` branch of the schedule consume (`_consume_schedule`) sets that family's variable from the `schedule arg` column (the byte pre-decoded from the record's `mask` param, since Scratch cannot parse the JSON payload); the `ground_stop_firing_row` branch sets its row from the same column. The eight branches are generated from a single family table (`FIRE_MASK_FAMILIES`) so a family cannot be half-wired. The masks and the ground-stop row are zeroed on a world reset (cold-start / new-game) by the `difficulty_reset` receiver, alongside the AI level and formation. +- Scratch evidence: `FIRE_MASK_FAMILIES`, the eight mask branches and the ground-stop branch in `_consume_schedule`, the eight `fire mask ` Stage variables + `ground stop firing row`, and their zeroing in `difficulty_reset`, all in `tools/game_director.py`. The mask bytes round-trip from the schedule via the extended `schedule arg` golden in `tests/test_spec_docs.py` (`test_all_area_schedules_round_trip_from_json`). Dynamic check in the scratch-vm harness (`harness/lib/catalog.js` `fire-permission-masks`): real play sets `fire mask logram` to its scheduled value (255) and other family masks to non-zero, with a negative that breaks the logram branch so it never sets. The transition-path variable set (`tests/test_scratch_project.py`) categorizes the eight masks + ground-stop row as difficulty-director state and forbids sprite writes. +- Acceptance criteria: Each family's mask byte round-trips from `area-schedules.json` into the `schedule arg` column (engine, round-trip golden). In real play the masks are set to their scheduled values as the records fire (engine, scratch-vm harness). Operator: with a `fire mask *` watcher open, a family's mask takes its scheduled value as the area scrolls — an inspectable confirmation; no family fires from the mask yet. +- Fidelity status: DIF-03 is **partial** (foundation) — the mask setting is built, live, and observable, and the values are faithful to the schedule. What is deferred: the per-family *firing* that consumes each mask (how often a family may fire, and the ground families stopping at the ground-stop row) is specified in the family documents and arrives with the enemy slices (8+), so no enemy fires from a mask this slice. +- License status: The pinned reference states no reusable license; only the derived per-family mask values (committed, hash-pinned in `area-schedules.json`) and the setter behaviour are used, cited to the settled spec and the data file, and no reference source text or media was reproduced. +- Known deviations or uncertainty: The masks are held as eight separate named Stage variables rather than one indexed list. The tradeoff is deliberate: a single list would collapse the eight dispatch branches and reset statements, but the slice-8 consumers are per-family sprites that each read one named mask, so the separate-variable shape is the more consumable downstream one; recorded here rather than left implied. The `ground stop firing row` is stored but, like the masks, its consumption (the ground families ceasing fire at that row) is an enemy-slice behaviour, not built this slice. +- [x] No assembly or other source code was copied into the Scratch project. +- [x] No arcade ROM files were acquired, opened, extracted, or distributed. +- [x] Any transferred graphics or audio are recorded in `src/xevious/assets/provenance.json`. diff --git a/harness/lib/catalog.js b/harness/lib/catalog.js index 2ae5193..be8505c 100644 --- a/harness/lib/catalog.js +++ b/harness/lib/catalog.js @@ -345,6 +345,42 @@ export const SCENARIOS = [ negativeMutation: (p) => mutate.changeEqualsOperand(p, 'Stage', 'raise_ai_level_and_set_formation', '__never__'), }, + { + key: 'fire-permission-masks', + behavior: 'Area-schedule fire-mask records set the per-family fire-permission masks live', + playtestStep: 4, + async drive(vm) { + assert.ok(reachPlaying(vm), 'precondition: game reaches playing'); + // The schedule sets the fire masks from the record bytes as it scrolls. One headless pump + // covers many game ticks, so a specific transient value (logram is set to 255, then 31 within + // one pump) can be stepped over — assert the robust fact instead: the logram mask, and other + // families, are SEEN set to a non-zero scheduled value. (The FIRING that consumes them is the + // enemy slices'.) + let logramSet = false; + let otherMaskSet = false; + const others = [ + 'fire-mask-derota', + 'fire-mask-zoshi', + 'fire-mask-terrazi', + 'fire-mask-kapi', + 'fire-mask-boza-logram', + 'fire-mask-domogram', + ]; + for (let i = 0; i < 60; i += 1) { + step(vm, 1); + if (readVar(vm, 'fire-mask-logram') > 0) logramSet = true; + for (const id of others) if (readVar(vm, id) > 0) otherMaskSet = true; + } + return { logramSet, otherMaskSet }; + }, + assert(obs) { + assert.equal(obs.logramSet, true, 'the logram fire mask is set to a non-zero scheduled value'); + assert.equal(obs.otherMaskSet, true, 'other family fire masks are set live too'); + }, + // Break the logram mask branch (its handler == comparison never matches) so it is never set → + // the logramSet assertion fails. + negativeMutation: (p) => mutate.changeEqualsOperand(p, 'Stage', 'fire_mask_logram', '__never__'), + }, ]; // VM-cannot-observe behaviors that stay the operator playtest's job, named so "complete" diff --git a/src/xevious/project.json b/src/xevious/project.json index 7a6c228..b4d30fa 100644 --- a/src/xevious/project.json +++ b/src/xevious/project.json @@ -135,6 +135,42 @@ "difficulty-ai-adjust": [ "ai adjust", 0 + ], + "ground-stop-firing-row": [ + "ground stop firing row", + 0 + ], + "fire-mask-derota": [ + "fire mask derota", + 0 + ], + "fire-mask-logram": [ + "fire mask logram", + 0 + ], + "fire-mask-zoshi": [ + "fire mask zoshi", + 0 + ], + "fire-mask-terrazi": [ + "fire mask terrazi", + 0 + ], + "fire-mask-kapi": [ + "fire mask kapi", + 0 + ], + "fire-mask-boza-logram": [ + "fire mask boza logram", + 0 + ], + "fire-mask-domogram": [ + "fire mask domogram", + 0 + ], + "fire-mask-andor-genesis": [ + "fire mask andor genesis", + 0 ] }, "lists": { @@ -7392,7 +7428,7 @@ }, "gd-stage-157": { "opcode": "control_if", - "next": "gd-stage-158", + "next": "gd-stage-162", "parent": "gd-stage-152", "inputs": { "CONDITION": [ @@ -7409,95 +7445,88 @@ "topLevel": false }, "gd-stage-158": { - "opcode": "data_changevariableby", - "next": "gd-stage-159", - "parent": "gd-stage-157", + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-159", "inputs": { - "VALUE": [ - 1, + "INDEX": [ + 3, [ - 4, - 1 + 12, + "schedule cursor", + "area-schedule-cursor" + ], + [ + 10, + "" ] ] }, "fields": { - "VARIABLE": [ - "schedule fired", - "area-schedule-fired" + "LIST": [ + "schedule handler", + "area-schedule-handler" ] }, "shadow": false, "topLevel": false }, "gd-stage-159": { - "opcode": "data_changevariableby", + "opcode": "operator_equals", "next": null, - "parent": "gd-stage-158", + "parent": "gd-stage-162", "inputs": { - "VALUE": [ + "OPERAND1": [ + 2, + "gd-stage-158" + ], + "OPERAND2": [ 1, [ - 4, - 1 + 10, + "fire_mask_derota" ] ] }, - "fields": { - "VARIABLE": [ - "schedule cursor", - "area-schedule-cursor" - ] - }, + "fields": {}, "shadow": false, "topLevel": false }, "gd-stage-160": { - "opcode": "procedures_definition", - "next": "gd-stage-162", - "parent": null, + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-161", "inputs": { - "custom_block": [ - 1, - "gd-stage-161" + "INDEX": [ + 3, + [ + 12, + "schedule cursor", + "area-schedule-cursor" + ], + [ + 10, + "" + ] + ] + }, + "fields": { + "LIST": [ + "schedule arg", + "area-schedule-arg" ] }, - "fields": {}, "shadow": false, - "topLevel": true, - "x": 20, - "y": 770 + "topLevel": false }, "gd-stage-161": { - "opcode": "procedures_prototype", + "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-160", - "inputs": {}, - "fields": {}, - "shadow": true, - "topLevel": false, - "mutation": { - "tagName": "mutation", - "children": [], - "proccode": "score", - "argumentids": "[]", - "argumentnames": "[]", - "argumentdefaults": "[]", - "warp": "true" - } - }, - "gd-stage-162": { - "opcode": "data_changevariableby", - "next": "gd-stage-163", - "parent": "gd-stage-160", + "parent": "gd-stage-162", "inputs": { "VALUE": [ 3, - [ - 12, - "award value", - "eco-award-value" - ], + "gd-stage-160", [ 10, "" @@ -7506,53 +7535,72 @@ }, "fields": { "VARIABLE": [ - "score", - "eco-score" + "fire mask derota", + "fire-mask-derota" ] }, "shadow": false, "topLevel": false }, - "gd-stage-163": { + "gd-stage-162": { "opcode": "control_if", - "next": "gd-stage-166", - "parent": "gd-stage-162", + "next": "gd-stage-167", + "parent": "gd-stage-157", "inputs": { "CONDITION": [ 2, - "gd-stage-164" + "gd-stage-159" ], "SUBSTACK": [ 2, - "gd-stage-165" + "gd-stage-161" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-164": { - "opcode": "operator_gt", + "gd-stage-163": { + "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-163", + "parent": "gd-stage-164", "inputs": { - "OPERAND1": [ + "INDEX": [ 3, [ 12, - "score", - "eco-score" + "schedule cursor", + "area-schedule-cursor" ], [ 10, "" ] + ] + }, + "fields": { + "LIST": [ + "schedule handler", + "area-schedule-handler" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-164": { + "opcode": "operator_equals", + "next": null, + "parent": "gd-stage-167", + "inputs": { + "OPERAND1": [ + 2, + "gd-stage-163" ], "OPERAND2": [ 1, [ - 4, - 9999990 + 10, + "fire_mask_logram" ] ] }, @@ -7561,72 +7609,114 @@ "topLevel": false }, "gd-stage-165": { + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-166", + "inputs": { + "INDEX": [ + 3, + [ + 12, + "schedule cursor", + "area-schedule-cursor" + ], + [ + 10, + "" + ] + ] + }, + "fields": { + "LIST": [ + "schedule arg", + "area-schedule-arg" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-166": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-163", + "parent": "gd-stage-167", "inputs": { "VALUE": [ - 1, + 3, + "gd-stage-165", [ - 4, - 9999990 + 10, + "" ] ] }, "fields": { "VARIABLE": [ - "score", - "eco-score" + "fire mask logram", + "fire-mask-logram" ] }, "shadow": false, "topLevel": false }, - "gd-stage-166": { + "gd-stage-167": { "opcode": "control_if", - "next": "gd-stage-169", - "parent": "gd-stage-163", + "next": "gd-stage-172", + "parent": "gd-stage-162", "inputs": { "CONDITION": [ 2, - "gd-stage-167" + "gd-stage-164" ], "SUBSTACK": [ 2, - "gd-stage-168" + "gd-stage-166" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-167": { - "opcode": "operator_gt", + "gd-stage-168": { + "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-166", + "parent": "gd-stage-169", "inputs": { - "OPERAND1": [ + "INDEX": [ 3, [ 12, - "score", - "eco-score" + "schedule cursor", + "area-schedule-cursor" ], [ 10, "" ] + ] + }, + "fields": { + "LIST": [ + "schedule handler", + "area-schedule-handler" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-169": { + "opcode": "operator_equals", + "next": null, + "parent": "gd-stage-172", + "inputs": { + "OPERAND1": [ + 2, + "gd-stage-168" ], "OPERAND2": [ - 3, - [ - 12, - "high score", - "eco-high-score" - ], + 1, [ 10, - "" + "fire_mask_zoshi" ] ] }, @@ -7634,17 +7724,17 @@ "shadow": false, "topLevel": false }, - "gd-stage-168": { - "opcode": "data_setvariableto", + "gd-stage-170": { + "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-166", + "parent": "gd-stage-171", "inputs": { - "VALUE": [ + "INDEX": [ 3, [ 12, - "score", - "eco-score" + "schedule cursor", + "area-schedule-cursor" ], [ 10, @@ -7653,23 +7743,1013 @@ ] }, "fields": { - "VARIABLE": [ - "high score", - "eco-high-score" + "LIST": [ + "schedule arg", + "area-schedule-arg" ] }, "shadow": false, "topLevel": false }, - "gd-stage-169": { - "opcode": "procedures_call", + "gd-stage-171": { + "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-166", - "inputs": {}, - "fields": {}, - "shadow": false, - "topLevel": false, - "mutation": { + "parent": "gd-stage-172", + "inputs": { + "VALUE": [ + 3, + "gd-stage-170", + [ + 10, + "" + ] + ] + }, + "fields": { + "VARIABLE": [ + "fire mask zoshi", + "fire-mask-zoshi" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-172": { + "opcode": "control_if", + "next": "gd-stage-177", + "parent": "gd-stage-167", + "inputs": { + "CONDITION": [ + 2, + "gd-stage-169" + ], + "SUBSTACK": [ + 2, + "gd-stage-171" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-173": { + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-174", + "inputs": { + "INDEX": [ + 3, + [ + 12, + "schedule cursor", + "area-schedule-cursor" + ], + [ + 10, + "" + ] + ] + }, + "fields": { + "LIST": [ + "schedule handler", + "area-schedule-handler" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-174": { + "opcode": "operator_equals", + "next": null, + "parent": "gd-stage-177", + "inputs": { + "OPERAND1": [ + 2, + "gd-stage-173" + ], + "OPERAND2": [ + 1, + [ + 10, + "fire_mask_terrazi" + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-175": { + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-176", + "inputs": { + "INDEX": [ + 3, + [ + 12, + "schedule cursor", + "area-schedule-cursor" + ], + [ + 10, + "" + ] + ] + }, + "fields": { + "LIST": [ + "schedule arg", + "area-schedule-arg" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-176": { + "opcode": "data_setvariableto", + "next": null, + "parent": "gd-stage-177", + "inputs": { + "VALUE": [ + 3, + "gd-stage-175", + [ + 10, + "" + ] + ] + }, + "fields": { + "VARIABLE": [ + "fire mask terrazi", + "fire-mask-terrazi" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-177": { + "opcode": "control_if", + "next": "gd-stage-182", + "parent": "gd-stage-172", + "inputs": { + "CONDITION": [ + 2, + "gd-stage-174" + ], + "SUBSTACK": [ + 2, + "gd-stage-176" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-178": { + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-179", + "inputs": { + "INDEX": [ + 3, + [ + 12, + "schedule cursor", + "area-schedule-cursor" + ], + [ + 10, + "" + ] + ] + }, + "fields": { + "LIST": [ + "schedule handler", + "area-schedule-handler" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-179": { + "opcode": "operator_equals", + "next": null, + "parent": "gd-stage-182", + "inputs": { + "OPERAND1": [ + 2, + "gd-stage-178" + ], + "OPERAND2": [ + 1, + [ + 10, + "fire_mask_kapi" + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-180": { + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-181", + "inputs": { + "INDEX": [ + 3, + [ + 12, + "schedule cursor", + "area-schedule-cursor" + ], + [ + 10, + "" + ] + ] + }, + "fields": { + "LIST": [ + "schedule arg", + "area-schedule-arg" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-181": { + "opcode": "data_setvariableto", + "next": null, + "parent": "gd-stage-182", + "inputs": { + "VALUE": [ + 3, + "gd-stage-180", + [ + 10, + "" + ] + ] + }, + "fields": { + "VARIABLE": [ + "fire mask kapi", + "fire-mask-kapi" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-182": { + "opcode": "control_if", + "next": "gd-stage-187", + "parent": "gd-stage-177", + "inputs": { + "CONDITION": [ + 2, + "gd-stage-179" + ], + "SUBSTACK": [ + 2, + "gd-stage-181" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-183": { + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-184", + "inputs": { + "INDEX": [ + 3, + [ + 12, + "schedule cursor", + "area-schedule-cursor" + ], + [ + 10, + "" + ] + ] + }, + "fields": { + "LIST": [ + "schedule handler", + "area-schedule-handler" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-184": { + "opcode": "operator_equals", + "next": null, + "parent": "gd-stage-187", + "inputs": { + "OPERAND1": [ + 2, + "gd-stage-183" + ], + "OPERAND2": [ + 1, + [ + 10, + "fire_mask_boza_logram" + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-185": { + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-186", + "inputs": { + "INDEX": [ + 3, + [ + 12, + "schedule cursor", + "area-schedule-cursor" + ], + [ + 10, + "" + ] + ] + }, + "fields": { + "LIST": [ + "schedule arg", + "area-schedule-arg" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-186": { + "opcode": "data_setvariableto", + "next": null, + "parent": "gd-stage-187", + "inputs": { + "VALUE": [ + 3, + "gd-stage-185", + [ + 10, + "" + ] + ] + }, + "fields": { + "VARIABLE": [ + "fire mask boza logram", + "fire-mask-boza-logram" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-187": { + "opcode": "control_if", + "next": "gd-stage-192", + "parent": "gd-stage-182", + "inputs": { + "CONDITION": [ + 2, + "gd-stage-184" + ], + "SUBSTACK": [ + 2, + "gd-stage-186" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-188": { + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-189", + "inputs": { + "INDEX": [ + 3, + [ + 12, + "schedule cursor", + "area-schedule-cursor" + ], + [ + 10, + "" + ] + ] + }, + "fields": { + "LIST": [ + "schedule handler", + "area-schedule-handler" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-189": { + "opcode": "operator_equals", + "next": null, + "parent": "gd-stage-192", + "inputs": { + "OPERAND1": [ + 2, + "gd-stage-188" + ], + "OPERAND2": [ + 1, + [ + 10, + "fire_mask_domogram" + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-190": { + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-191", + "inputs": { + "INDEX": [ + 3, + [ + 12, + "schedule cursor", + "area-schedule-cursor" + ], + [ + 10, + "" + ] + ] + }, + "fields": { + "LIST": [ + "schedule arg", + "area-schedule-arg" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-191": { + "opcode": "data_setvariableto", + "next": null, + "parent": "gd-stage-192", + "inputs": { + "VALUE": [ + 3, + "gd-stage-190", + [ + 10, + "" + ] + ] + }, + "fields": { + "VARIABLE": [ + "fire mask domogram", + "fire-mask-domogram" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-192": { + "opcode": "control_if", + "next": "gd-stage-197", + "parent": "gd-stage-187", + "inputs": { + "CONDITION": [ + 2, + "gd-stage-189" + ], + "SUBSTACK": [ + 2, + "gd-stage-191" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-193": { + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-194", + "inputs": { + "INDEX": [ + 3, + [ + 12, + "schedule cursor", + "area-schedule-cursor" + ], + [ + 10, + "" + ] + ] + }, + "fields": { + "LIST": [ + "schedule handler", + "area-schedule-handler" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-194": { + "opcode": "operator_equals", + "next": null, + "parent": "gd-stage-197", + "inputs": { + "OPERAND1": [ + 2, + "gd-stage-193" + ], + "OPERAND2": [ + 1, + [ + 10, + "fire_mask_andor_genesis" + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-195": { + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-196", + "inputs": { + "INDEX": [ + 3, + [ + 12, + "schedule cursor", + "area-schedule-cursor" + ], + [ + 10, + "" + ] + ] + }, + "fields": { + "LIST": [ + "schedule arg", + "area-schedule-arg" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-196": { + "opcode": "data_setvariableto", + "next": null, + "parent": "gd-stage-197", + "inputs": { + "VALUE": [ + 3, + "gd-stage-195", + [ + 10, + "" + ] + ] + }, + "fields": { + "VARIABLE": [ + "fire mask andor genesis", + "fire-mask-andor-genesis" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-197": { + "opcode": "control_if", + "next": "gd-stage-202", + "parent": "gd-stage-192", + "inputs": { + "CONDITION": [ + 2, + "gd-stage-194" + ], + "SUBSTACK": [ + 2, + "gd-stage-196" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-198": { + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-199", + "inputs": { + "INDEX": [ + 3, + [ + 12, + "schedule cursor", + "area-schedule-cursor" + ], + [ + 10, + "" + ] + ] + }, + "fields": { + "LIST": [ + "schedule handler", + "area-schedule-handler" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-199": { + "opcode": "operator_equals", + "next": null, + "parent": "gd-stage-202", + "inputs": { + "OPERAND1": [ + 2, + "gd-stage-198" + ], + "OPERAND2": [ + 1, + [ + 10, + "ground_stop_firing_row" + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-200": { + "opcode": "data_itemoflist", + "next": null, + "parent": "gd-stage-201", + "inputs": { + "INDEX": [ + 3, + [ + 12, + "schedule cursor", + "area-schedule-cursor" + ], + [ + 10, + "" + ] + ] + }, + "fields": { + "LIST": [ + "schedule arg", + "area-schedule-arg" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-201": { + "opcode": "data_setvariableto", + "next": null, + "parent": "gd-stage-202", + "inputs": { + "VALUE": [ + 3, + "gd-stage-200", + [ + 10, + "" + ] + ] + }, + "fields": { + "VARIABLE": [ + "ground stop firing row", + "ground-stop-firing-row" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-202": { + "opcode": "control_if", + "next": "gd-stage-203", + "parent": "gd-stage-197", + "inputs": { + "CONDITION": [ + 2, + "gd-stage-199" + ], + "SUBSTACK": [ + 2, + "gd-stage-201" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-203": { + "opcode": "data_changevariableby", + "next": "gd-stage-204", + "parent": "gd-stage-202", + "inputs": { + "VALUE": [ + 1, + [ + 4, + 1 + ] + ] + }, + "fields": { + "VARIABLE": [ + "schedule fired", + "area-schedule-fired" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-204": { + "opcode": "data_changevariableby", + "next": null, + "parent": "gd-stage-203", + "inputs": { + "VALUE": [ + 1, + [ + 4, + 1 + ] + ] + }, + "fields": { + "VARIABLE": [ + "schedule cursor", + "area-schedule-cursor" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-205": { + "opcode": "procedures_definition", + "next": "gd-stage-207", + "parent": null, + "inputs": { + "custom_block": [ + 1, + "gd-stage-206" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": true, + "x": 20, + "y": 770 + }, + "gd-stage-206": { + "opcode": "procedures_prototype", + "next": null, + "parent": "gd-stage-205", + "inputs": {}, + "fields": {}, + "shadow": true, + "topLevel": false, + "mutation": { + "tagName": "mutation", + "children": [], + "proccode": "score", + "argumentids": "[]", + "argumentnames": "[]", + "argumentdefaults": "[]", + "warp": "true" + } + }, + "gd-stage-207": { + "opcode": "data_changevariableby", + "next": "gd-stage-208", + "parent": "gd-stage-205", + "inputs": { + "VALUE": [ + 3, + [ + 12, + "award value", + "eco-award-value" + ], + [ + 10, + "" + ] + ] + }, + "fields": { + "VARIABLE": [ + "score", + "eco-score" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-208": { + "opcode": "control_if", + "next": "gd-stage-211", + "parent": "gd-stage-207", + "inputs": { + "CONDITION": [ + 2, + "gd-stage-209" + ], + "SUBSTACK": [ + 2, + "gd-stage-210" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-209": { + "opcode": "operator_gt", + "next": null, + "parent": "gd-stage-208", + "inputs": { + "OPERAND1": [ + 3, + [ + 12, + "score", + "eco-score" + ], + [ + 10, + "" + ] + ], + "OPERAND2": [ + 1, + [ + 4, + 9999990 + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-210": { + "opcode": "data_setvariableto", + "next": null, + "parent": "gd-stage-208", + "inputs": { + "VALUE": [ + 1, + [ + 4, + 9999990 + ] + ] + }, + "fields": { + "VARIABLE": [ + "score", + "eco-score" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-211": { + "opcode": "control_if", + "next": "gd-stage-214", + "parent": "gd-stage-208", + "inputs": { + "CONDITION": [ + 2, + "gd-stage-212" + ], + "SUBSTACK": [ + 2, + "gd-stage-213" + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-212": { + "opcode": "operator_gt", + "next": null, + "parent": "gd-stage-211", + "inputs": { + "OPERAND1": [ + 3, + [ + 12, + "score", + "eco-score" + ], + [ + 10, + "" + ] + ], + "OPERAND2": [ + 3, + [ + 12, + "high score", + "eco-high-score" + ], + [ + 10, + "" + ] + ] + }, + "fields": {}, + "shadow": false, + "topLevel": false + }, + "gd-stage-213": { + "opcode": "data_setvariableto", + "next": null, + "parent": "gd-stage-211", + "inputs": { + "VALUE": [ + 3, + [ + 12, + "score", + "eco-score" + ], + [ + 10, + "" + ] + ] + }, + "fields": { + "VARIABLE": [ + "high score", + "eco-high-score" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-214": { + "opcode": "procedures_call", + "next": null, + "parent": "gd-stage-211", + "inputs": {}, + "fields": {}, + "shadow": false, + "topLevel": false, + "mutation": { "tagName": "mutation", "children": [], "proccode": "check bonus life", @@ -7677,14 +8757,14 @@ "warp": "true" } }, - "gd-stage-170": { + "gd-stage-215": { "opcode": "procedures_definition", - "next": "gd-stage-188", + "next": "gd-stage-233", "parent": null, "inputs": { "custom_block": [ 1, - "gd-stage-171" + "gd-stage-216" ] }, "fields": {}, @@ -7693,10 +8773,10 @@ "x": 20, "y": 920 }, - "gd-stage-171": { + "gd-stage-216": { "opcode": "procedures_prototype", "next": null, - "parent": "gd-stage-170", + "parent": "gd-stage-215", "inputs": {}, "fields": {}, "shadow": true, @@ -7711,10 +8791,10 @@ "warp": "true" } }, - "gd-stage-172": { + "gd-stage-217": { "opcode": "operator_lt", "next": null, - "parent": "gd-stage-173", + "parent": "gd-stage-218", "inputs": { "OPERAND1": [ 3, @@ -7745,24 +8825,24 @@ "shadow": false, "topLevel": false }, - "gd-stage-173": { + "gd-stage-218": { "opcode": "operator_not", "next": null, - "parent": "gd-stage-181", + "parent": "gd-stage-226", "inputs": { "OPERAND": [ 2, - "gd-stage-172" + "gd-stage-217" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-174": { + "gd-stage-219": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-175", + "parent": "gd-stage-220", "inputs": { "INDEX": [ 1, @@ -7781,10 +8861,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-175": { + "gd-stage-220": { "opcode": "operator_add", "next": null, - "parent": "gd-stage-176", + "parent": "gd-stage-221", "inputs": { "NUM1": [ 3, @@ -7800,21 +8880,21 @@ ], "NUM2": [ 2, - "gd-stage-174" + "gd-stage-219" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-176": { + "gd-stage-221": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-180", + "parent": "gd-stage-225", "inputs": { "VALUE": [ 3, - "gd-stage-175", + "gd-stage-220", [ 10, "" @@ -7830,10 +8910,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-177": { + "gd-stage-222": { "opcode": "data_changevariableby", - "next": "gd-stage-179", - "parent": "gd-stage-181", + "next": "gd-stage-224", + "parent": "gd-stage-226", "inputs": { "VALUE": [ 1, @@ -7852,10 +8932,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-178": { + "gd-stage-223": { "opcode": "sound_sounds_menu", "next": null, - "parent": "gd-stage-179", + "parent": "gd-stage-224", "inputs": {}, "fields": { "SOUND_MENU": [ @@ -7866,24 +8946,24 @@ "shadow": true, "topLevel": false }, - "gd-stage-179": { + "gd-stage-224": { "opcode": "sound_play", - "next": "gd-stage-180", - "parent": "gd-stage-177", + "next": "gd-stage-225", + "parent": "gd-stage-222", "inputs": { "SOUND_MENU": [ 1, - "gd-stage-178" + "gd-stage-223" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-180": { + "gd-stage-225": { "opcode": "event_broadcast", - "next": "gd-stage-176", - "parent": "gd-stage-179", + "next": "gd-stage-221", + "parent": "gd-stage-224", "inputs": { "BROADCAST_INPUT": [ 1, @@ -7898,50 +8978,50 @@ "shadow": false, "topLevel": false }, - "gd-stage-181": { + "gd-stage-226": { "opcode": "control_if", "next": null, - "parent": "gd-stage-182", + "parent": "gd-stage-227", "inputs": { "CONDITION": [ 2, - "gd-stage-173" + "gd-stage-218" ], "SUBSTACK": [ 2, - "gd-stage-177" + "gd-stage-222" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-182": { + "gd-stage-227": { "opcode": "control_if_else", "next": null, - "parent": "gd-stage-188", + "parent": "gd-stage-233", "inputs": { "CONDITION": [ 2, - "gd-stage-183" + "gd-stage-228" ], "SUBSTACK": [ 2, - "gd-stage-184" + "gd-stage-229" ], "SUBSTACK2": [ 2, - "gd-stage-181" + "gd-stage-226" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-183": { + "gd-stage-228": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-182", + "parent": "gd-stage-227", "inputs": { "OPERAND1": [ 3, @@ -7967,10 +9047,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-184": { + "gd-stage-229": { "opcode": "data_changevariableby", - "next": "gd-stage-186", - "parent": "gd-stage-182", + "next": "gd-stage-231", + "parent": "gd-stage-227", "inputs": { "VALUE": [ 1, @@ -7989,10 +9069,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-185": { + "gd-stage-230": { "opcode": "sound_sounds_menu", "next": null, - "parent": "gd-stage-186", + "parent": "gd-stage-231", "inputs": {}, "fields": { "SOUND_MENU": [ @@ -8003,24 +9083,24 @@ "shadow": true, "topLevel": false }, - "gd-stage-186": { + "gd-stage-231": { "opcode": "sound_play", - "next": "gd-stage-187", - "parent": "gd-stage-184", + "next": "gd-stage-232", + "parent": "gd-stage-229", "inputs": { "SOUND_MENU": [ 1, - "gd-stage-185" + "gd-stage-230" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-187": { + "gd-stage-232": { "opcode": "event_broadcast", "next": null, - "parent": "gd-stage-186", + "parent": "gd-stage-231", "inputs": { "BROADCAST_INPUT": [ 1, @@ -8035,28 +9115,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-188": { + "gd-stage-233": { "opcode": "control_if", "next": null, - "parent": "gd-stage-170", + "parent": "gd-stage-215", "inputs": { "CONDITION": [ 2, - "gd-stage-189" + "gd-stage-234" ], "SUBSTACK": [ 2, - "gd-stage-182" + "gd-stage-227" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-189": { + "gd-stage-234": { "opcode": "operator_gt", "next": null, - "parent": "gd-stage-188", + "parent": "gd-stage-233", "inputs": { "OPERAND1": [ 3, @@ -8082,14 +9162,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-190": { + "gd-stage-235": { "opcode": "procedures_definition", - "next": "gd-stage-192", + "next": "gd-stage-237", "parent": null, "inputs": { "custom_block": [ 1, - "gd-stage-191" + "gd-stage-236" ] }, "fields": {}, @@ -8098,10 +9178,10 @@ "x": 20, "y": 1070 }, - "gd-stage-191": { + "gd-stage-236": { "opcode": "procedures_prototype", "next": null, - "parent": "gd-stage-190", + "parent": "gd-stage-235", "inputs": {}, "fields": {}, "shadow": true, @@ -8116,10 +9196,10 @@ "warp": "true" } }, - "gd-stage-192": { + "gd-stage-237": { "opcode": "data_replaceitemoflist", - "next": "gd-stage-193", - "parent": "gd-stage-190", + "next": "gd-stage-238", + "parent": "gd-stage-235", "inputs": { "INDEX": [ 3, @@ -8150,10 +9230,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-193": { + "gd-stage-238": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-192", + "parent": "gd-stage-237", "inputs": {}, "fields": {}, "shadow": false, @@ -8166,14 +9246,14 @@ "warp": "true" } }, - "gd-stage-194": { + "gd-stage-239": { "opcode": "procedures_definition", - "next": "gd-stage-196", + "next": "gd-stage-241", "parent": null, "inputs": { "custom_block": [ 1, - "gd-stage-195" + "gd-stage-240" ] }, "fields": {}, @@ -8182,10 +9262,10 @@ "x": 20, "y": 1220 }, - "gd-stage-195": { + "gd-stage-240": { "opcode": "procedures_prototype", "next": null, - "parent": "gd-stage-194", + "parent": "gd-stage-239", "inputs": {}, "fields": {}, "shadow": true, @@ -8200,10 +9280,10 @@ "warp": "true" } }, - "gd-stage-196": { + "gd-stage-241": { "opcode": "data_setvariableto", - "next": "gd-stage-197", - "parent": "gd-stage-194", + "next": "gd-stage-242", + "parent": "gd-stage-239", "inputs": { "VALUE": [ 1, @@ -8222,10 +9302,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-197": { + "gd-stage-242": { "opcode": "data_setvariableto", - "next": "gd-stage-198", - "parent": "gd-stage-196", + "next": "gd-stage-243", + "parent": "gd-stage-241", "inputs": { "VALUE": [ 1, @@ -8244,10 +9324,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-198": { + "gd-stage-243": { "opcode": "control_repeat", "next": null, - "parent": "gd-stage-197", + "parent": "gd-stage-242", "inputs": { "TIMES": [ 1, @@ -8258,17 +9338,17 @@ ], "SUBSTACK": [ 2, - "gd-stage-206" + "gd-stage-251" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-199": { + "gd-stage-244": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-202", + "parent": "gd-stage-247", "inputs": { "OPERAND1": [ 3, @@ -8294,10 +9374,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-200": { + "gd-stage-245": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-201", + "parent": "gd-stage-246", "inputs": { "INDEX": [ 3, @@ -8321,14 +9401,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-201": { + "gd-stage-246": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-202", + "parent": "gd-stage-247", "inputs": { "OPERAND1": [ 2, - "gd-stage-200" + "gd-stage-245" ], "OPERAND2": [ 1, @@ -8342,28 +9422,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-202": { + "gd-stage-247": { "opcode": "operator_and", "next": null, - "parent": "gd-stage-206", + "parent": "gd-stage-251", "inputs": { "OPERAND1": [ 2, - "gd-stage-199" + "gd-stage-244" ], "OPERAND2": [ 2, - "gd-stage-201" + "gd-stage-246" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-203": { + "gd-stage-248": { "opcode": "data_replaceitemoflist", - "next": "gd-stage-204", - "parent": "gd-stage-206", + "next": "gd-stage-249", + "parent": "gd-stage-251", "inputs": { "INDEX": [ 3, @@ -8394,10 +9474,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-204": { + "gd-stage-249": { "opcode": "data_replaceitemoflist", - "next": "gd-stage-205", - "parent": "gd-stage-203", + "next": "gd-stage-250", + "parent": "gd-stage-248", "inputs": { "INDEX": [ 3, @@ -8428,10 +9508,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-205": { + "gd-stage-250": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-204", + "parent": "gd-stage-249", "inputs": { "VALUE": [ 3, @@ -8455,28 +9535,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-206": { + "gd-stage-251": { "opcode": "control_if", - "next": "gd-stage-207", - "parent": "gd-stage-198", + "next": "gd-stage-252", + "parent": "gd-stage-243", "inputs": { "CONDITION": [ 2, - "gd-stage-202" + "gd-stage-247" ], "SUBSTACK": [ 2, - "gd-stage-203" + "gd-stage-248" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-207": { + "gd-stage-252": { "opcode": "data_changevariableby", "next": null, - "parent": "gd-stage-206", + "parent": "gd-stage-251", "inputs": { "VALUE": [ 1, @@ -8495,9 +9575,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-208": { + "gd-stage-253": { "opcode": "event_whenflagclicked", - "next": "gd-stage-209", + "next": "gd-stage-254", "parent": null, "inputs": {}, "fields": {}, @@ -8506,10 +9586,10 @@ "x": 20, "y": 1370 }, - "gd-stage-209": { + "gd-stage-254": { "opcode": "data_setvariableto", - "next": "gd-stage-210", - "parent": "gd-stage-208", + "next": "gd-stage-255", + "parent": "gd-stage-253", "inputs": { "VALUE": [ 1, @@ -8528,10 +9608,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-210": { + "gd-stage-255": { "opcode": "data_setvariableto", - "next": "gd-stage-211", - "parent": "gd-stage-209", + "next": "gd-stage-256", + "parent": "gd-stage-254", "inputs": { "VALUE": [ 1, @@ -8550,10 +9630,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-211": { + "gd-stage-256": { "opcode": "data_setvariableto", - "next": "gd-stage-212", - "parent": "gd-stage-210", + "next": "gd-stage-257", + "parent": "gd-stage-255", "inputs": { "VALUE": [ 1, @@ -8572,10 +9652,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-212": { + "gd-stage-257": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-211", + "parent": "gd-stage-256", "inputs": { "director-destination": [ 1, @@ -8603,9 +9683,9 @@ "warp": "false" } }, - "gd-stage-213": { + "gd-stage-258": { "opcode": "event_whenkeypressed", - "next": "gd-stage-215", + "next": "gd-stage-260", "parent": null, "inputs": {}, "fields": { @@ -8619,10 +9699,10 @@ "x": 20, "y": 1520 }, - "gd-stage-214": { + "gd-stage-259": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-215", + "parent": "gd-stage-260", "inputs": { "director-destination": [ 1, @@ -8650,28 +9730,28 @@ "warp": "false" } }, - "gd-stage-215": { + "gd-stage-260": { "opcode": "control_if", "next": null, - "parent": "gd-stage-213", + "parent": "gd-stage-258", "inputs": { "CONDITION": [ 2, - "gd-stage-216" + "gd-stage-261" ], "SUBSTACK": [ 2, - "gd-stage-214" + "gd-stage-259" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-216": { + "gd-stage-261": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-215", + "parent": "gd-stage-260", "inputs": { "OPERAND1": [ 3, @@ -8697,9 +9777,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-217": { + "gd-stage-262": { "opcode": "event_whenkeypressed", - "next": "gd-stage-221", + "next": "gd-stage-266", "parent": null, "inputs": {}, "fields": { @@ -8713,10 +9793,10 @@ "x": 20, "y": 1670 }, - "gd-stage-218": { + "gd-stage-263": { "opcode": "data_changevariableby", - "next": "gd-stage-219", - "parent": "gd-stage-221", + "next": "gd-stage-264", + "parent": "gd-stage-266", "inputs": { "VALUE": [ 1, @@ -8735,10 +9815,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-219": { + "gd-stage-264": { "opcode": "event_broadcast", - "next": "gd-stage-220", - "parent": "gd-stage-218", + "next": "gd-stage-265", + "parent": "gd-stage-263", "inputs": { "BROADCAST_INPUT": [ 1, @@ -8753,10 +9833,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-220": { + "gd-stage-265": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-219", + "parent": "gd-stage-264", "inputs": { "director-destination": [ 1, @@ -8784,28 +9864,28 @@ "warp": "false" } }, - "gd-stage-221": { + "gd-stage-266": { "opcode": "control_if", "next": null, - "parent": "gd-stage-217", + "parent": "gd-stage-262", "inputs": { "CONDITION": [ 2, - "gd-stage-222" + "gd-stage-267" ], "SUBSTACK": [ 2, - "gd-stage-218" + "gd-stage-263" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-222": { + "gd-stage-267": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-221", + "parent": "gd-stage-266", "inputs": { "OPERAND1": [ 3, @@ -8831,9 +9911,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-223": { + "gd-stage-268": { "opcode": "event_whenkeypressed", - "next": "gd-stage-227", + "next": "gd-stage-272", "parent": null, "inputs": {}, "fields": { @@ -8847,10 +9927,10 @@ "x": 20, "y": 1820 }, - "gd-stage-224": { + "gd-stage-269": { "opcode": "data_setvariableto", - "next": "gd-stage-225", - "parent": "gd-stage-227", + "next": "gd-stage-270", + "parent": "gd-stage-272", "inputs": { "VALUE": [ 1, @@ -8869,10 +9949,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-225": { + "gd-stage-270": { "opcode": "event_broadcast", - "next": "gd-stage-226", - "parent": "gd-stage-224", + "next": "gd-stage-271", + "parent": "gd-stage-269", "inputs": { "BROADCAST_INPUT": [ 1, @@ -8887,10 +9967,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-226": { + "gd-stage-271": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-225", + "parent": "gd-stage-270", "inputs": { "director-destination": [ 1, @@ -8918,28 +9998,28 @@ "warp": "false" } }, - "gd-stage-227": { + "gd-stage-272": { "opcode": "control_if", "next": null, - "parent": "gd-stage-223", + "parent": "gd-stage-268", "inputs": { "CONDITION": [ 2, - "gd-stage-228" + "gd-stage-273" ], "SUBSTACK": [ 2, - "gd-stage-224" + "gd-stage-269" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-228": { + "gd-stage-273": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-227", + "parent": "gd-stage-272", "inputs": { "OPERAND1": [ 3, @@ -8965,9 +10045,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-229": { + "gd-stage-274": { "opcode": "event_whenkeypressed", - "next": "gd-stage-233", + "next": "gd-stage-278", "parent": null, "inputs": {}, "fields": { @@ -8981,10 +10061,10 @@ "x": 20, "y": 1970 }, - "gd-stage-230": { + "gd-stage-275": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-231", + "parent": "gd-stage-276", "inputs": { "INDEX": [ 1, @@ -9003,14 +10083,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-231": { + "gd-stage-276": { "opcode": "data_setvariableto", - "next": "gd-stage-232", - "parent": "gd-stage-233", + "next": "gd-stage-277", + "parent": "gd-stage-278", "inputs": { "VALUE": [ 3, - "gd-stage-230", + "gd-stage-275", [ 10, "" @@ -9026,10 +10106,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-232": { + "gd-stage-277": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-231", + "parent": "gd-stage-276", "inputs": {}, "fields": {}, "shadow": false, @@ -9042,28 +10122,28 @@ "warp": "true" } }, - "gd-stage-233": { + "gd-stage-278": { "opcode": "control_if", "next": null, - "parent": "gd-stage-229", + "parent": "gd-stage-274", "inputs": { "CONDITION": [ 2, - "gd-stage-234" + "gd-stage-279" ], "SUBSTACK": [ 2, - "gd-stage-231" + "gd-stage-276" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-234": { + "gd-stage-279": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-233", + "parent": "gd-stage-278", "inputs": { "OPERAND1": [ 3, @@ -9089,9 +10169,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-235": { + "gd-stage-280": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-237", + "next": "gd-stage-282", "parent": null, "inputs": {}, "fields": { @@ -9105,10 +10185,10 @@ "x": 20, "y": 2120 }, - "gd-stage-236": { + "gd-stage-281": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-237", + "parent": "gd-stage-282", "inputs": { "director-destination": [ 1, @@ -9136,46 +10216,46 @@ "warp": "false" } }, - "gd-stage-237": { + "gd-stage-282": { "opcode": "control_if", "next": null, - "parent": "gd-stage-235", + "parent": "gd-stage-280", "inputs": { "CONDITION": [ 2, - "gd-stage-238" + "gd-stage-283" ], "SUBSTACK": [ 2, - "gd-stage-236" + "gd-stage-281" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-238": { + "gd-stage-283": { "opcode": "operator_or", "next": null, - "parent": "gd-stage-237", + "parent": "gd-stage-282", "inputs": { "OPERAND1": [ 2, - "gd-stage-239" + "gd-stage-284" ], "OPERAND2": [ 2, - "gd-stage-240" + "gd-stage-285" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-239": { + "gd-stage-284": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-238", + "parent": "gd-stage-283", "inputs": { "OPERAND1": [ 3, @@ -9201,10 +10281,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-240": { + "gd-stage-285": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-238", + "parent": "gd-stage-283", "inputs": { "OPERAND1": [ 3, @@ -9230,9 +10310,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-241": { + "gd-stage-286": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-248", + "next": "gd-stage-293", "parent": null, "inputs": {}, "fields": { @@ -9246,32 +10326,32 @@ "x": 20, "y": 2270 }, - "gd-stage-242": { + "gd-stage-287": { "opcode": "control_if_else", "next": null, - "parent": "gd-stage-248", + "parent": "gd-stage-293", "inputs": { "CONDITION": [ 2, - "gd-stage-243" + "gd-stage-288" ], "SUBSTACK": [ 2, - "gd-stage-244" + "gd-stage-289" ], "SUBSTACK2": [ 2, - "gd-stage-246" + "gd-stage-291" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-243": { + "gd-stage-288": { "opcode": "operator_gt", "next": null, - "parent": "gd-stage-242", + "parent": "gd-stage-287", "inputs": { "OPERAND1": [ 3, @@ -9297,10 +10377,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-244": { + "gd-stage-289": { "opcode": "data_setvariableto", - "next": "gd-stage-245", - "parent": "gd-stage-242", + "next": "gd-stage-290", + "parent": "gd-stage-287", "inputs": { "VALUE": [ 1, @@ -9319,10 +10399,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-245": { + "gd-stage-290": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-244", + "parent": "gd-stage-289", "inputs": { "director-destination": [ 1, @@ -9350,10 +10430,10 @@ "warp": "false" } }, - "gd-stage-246": { + "gd-stage-291": { "opcode": "data_setvariableto", - "next": "gd-stage-247", - "parent": "gd-stage-242", + "next": "gd-stage-292", + "parent": "gd-stage-287", "inputs": { "VALUE": [ 1, @@ -9372,10 +10452,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-247": { + "gd-stage-292": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-246", + "parent": "gd-stage-291", "inputs": { "director-destination": [ 1, @@ -9403,28 +10483,28 @@ "warp": "false" } }, - "gd-stage-248": { + "gd-stage-293": { "opcode": "control_if", "next": null, - "parent": "gd-stage-241", + "parent": "gd-stage-286", "inputs": { "CONDITION": [ 2, - "gd-stage-249" + "gd-stage-294" ], "SUBSTACK": [ 2, - "gd-stage-242" + "gd-stage-287" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-249": { + "gd-stage-294": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-248", + "parent": "gd-stage-293", "inputs": { "OPERAND1": [ 3, @@ -9450,9 +10530,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-250": { + "gd-stage-295": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-255", + "next": "gd-stage-300", "parent": null, "inputs": {}, "fields": { @@ -9466,10 +10546,10 @@ "x": 20, "y": 2420 }, - "gd-stage-251": { + "gd-stage-296": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-252", + "parent": "gd-stage-297", "inputs": { "INDEX": [ 1, @@ -9488,10 +10568,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-252": { + "gd-stage-297": { "opcode": "operator_gt", "next": null, - "parent": "gd-stage-253", + "parent": "gd-stage-298", "inputs": { "OPERAND1": [ 3, @@ -9507,21 +10587,21 @@ ], "OPERAND2": [ 2, - "gd-stage-251" + "gd-stage-296" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-253": { + "gd-stage-298": { "opcode": "data_setvariableto", - "next": "gd-stage-254", - "parent": "gd-stage-255", + "next": "gd-stage-299", + "parent": "gd-stage-300", "inputs": { "VALUE": [ 3, - "gd-stage-252", + "gd-stage-297", [ 10, "" @@ -9537,10 +10617,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-254": { + "gd-stage-299": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-253", + "parent": "gd-stage-298", "inputs": { "director-destination": [ 1, @@ -9568,28 +10648,28 @@ "warp": "false" } }, - "gd-stage-255": { + "gd-stage-300": { "opcode": "control_if", "next": null, - "parent": "gd-stage-250", + "parent": "gd-stage-295", "inputs": { "CONDITION": [ 2, - "gd-stage-256" + "gd-stage-301" ], "SUBSTACK": [ 2, - "gd-stage-253" + "gd-stage-298" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-256": { + "gd-stage-301": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-255", + "parent": "gd-stage-300", "inputs": { "OPERAND1": [ 3, @@ -9615,9 +10695,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-257": { + "gd-stage-302": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-265", + "next": "gd-stage-310", "parent": null, "inputs": {}, "fields": { @@ -9631,10 +10711,10 @@ "x": 20, "y": 2570 }, - "gd-stage-258": { + "gd-stage-303": { "opcode": "sound_sounds_menu", "next": null, - "parent": "gd-stage-259", + "parent": "gd-stage-304", "inputs": {}, "fields": { "SOUND_MENU": [ @@ -9645,56 +10725,56 @@ "shadow": true, "topLevel": false }, - "gd-stage-259": { + "gd-stage-304": { "opcode": "sound_playuntildone", - "next": "gd-stage-260", - "parent": "gd-stage-265", + "next": "gd-stage-305", + "parent": "gd-stage-310", "inputs": { "SOUND_MENU": [ 1, - "gd-stage-258" + "gd-stage-303" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-260": { + "gd-stage-305": { "opcode": "control_repeat_until", "next": null, - "parent": "gd-stage-259", + "parent": "gd-stage-304", "inputs": { "CONDITION": [ 2, - "gd-stage-261" + "gd-stage-306" ], "SUBSTACK": [ 2, - "gd-stage-264" + "gd-stage-309" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-261": { + "gd-stage-306": { "opcode": "operator_not", "next": null, - "parent": "gd-stage-260", + "parent": "gd-stage-305", "inputs": { "OPERAND": [ 2, - "gd-stage-262" + "gd-stage-307" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-262": { + "gd-stage-307": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-261", + "parent": "gd-stage-306", "inputs": { "OPERAND1": [ 3, @@ -9720,10 +10800,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-263": { + "gd-stage-308": { "opcode": "sound_sounds_menu", "next": null, - "parent": "gd-stage-264", + "parent": "gd-stage-309", "inputs": {}, "fields": { "SOUND_MENU": [ @@ -9734,42 +10814,42 @@ "shadow": true, "topLevel": false }, - "gd-stage-264": { + "gd-stage-309": { "opcode": "sound_playuntildone", "next": null, - "parent": "gd-stage-260", + "parent": "gd-stage-305", "inputs": { "SOUND_MENU": [ 1, - "gd-stage-263" + "gd-stage-308" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-265": { + "gd-stage-310": { "opcode": "control_if", "next": null, - "parent": "gd-stage-257", + "parent": "gd-stage-302", "inputs": { "CONDITION": [ 2, - "gd-stage-266" + "gd-stage-311" ], "SUBSTACK": [ 2, - "gd-stage-259" + "gd-stage-304" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-266": { + "gd-stage-311": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-265", + "parent": "gd-stage-310", "inputs": { "OPERAND1": [ 3, @@ -9795,9 +10875,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-267": { + "gd-stage-312": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-273", + "next": "gd-stage-318", "parent": null, "inputs": {}, "fields": { @@ -9811,42 +10891,42 @@ "x": 20, "y": 2720 }, - "gd-stage-268": { + "gd-stage-313": { "opcode": "control_repeat_until", "next": null, - "parent": "gd-stage-273", + "parent": "gd-stage-318", "inputs": { "CONDITION": [ 2, - "gd-stage-269" + "gd-stage-314" ], "SUBSTACK": [ 2, - "gd-stage-271" + "gd-stage-316" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-269": { + "gd-stage-314": { "opcode": "operator_not", "next": null, - "parent": "gd-stage-268", + "parent": "gd-stage-313", "inputs": { "OPERAND": [ 2, - "gd-stage-270" + "gd-stage-315" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-270": { + "gd-stage-315": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-269", + "parent": "gd-stage-314", "inputs": { "OPERAND1": [ 3, @@ -9872,10 +10952,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-271": { + "gd-stage-316": { "opcode": "procedures_call", - "next": "gd-stage-272", - "parent": "gd-stage-268", + "next": "gd-stage-317", + "parent": "gd-stage-313", "inputs": {}, "fields": {}, "shadow": false, @@ -9888,10 +10968,10 @@ "warp": "true" } }, - "gd-stage-272": { + "gd-stage-317": { "opcode": "procedures_call", "next": null, - "parent": "gd-stage-271", + "parent": "gd-stage-316", "inputs": {}, "fields": {}, "shadow": false, @@ -9904,28 +10984,28 @@ "warp": "true" } }, - "gd-stage-273": { + "gd-stage-318": { "opcode": "control_if", "next": null, - "parent": "gd-stage-267", + "parent": "gd-stage-312", "inputs": { "CONDITION": [ 2, - "gd-stage-274" + "gd-stage-319" ], "SUBSTACK": [ 2, - "gd-stage-268" + "gd-stage-313" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-274": { + "gd-stage-319": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-273", + "parent": "gd-stage-318", "inputs": { "OPERAND1": [ 3, @@ -9951,9 +11031,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-275": { + "gd-stage-320": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-279", + "next": "gd-stage-324", "parent": null, "inputs": {}, "fields": { @@ -9967,28 +11047,28 @@ "x": 20, "y": 2870 }, - "gd-stage-276": { + "gd-stage-321": { "opcode": "control_if", "next": null, - "parent": "gd-stage-288", + "parent": "gd-stage-333", "inputs": { "CONDITION": [ 2, - "gd-stage-277" + "gd-stage-322" ], "SUBSTACK": [ 2, - "gd-stage-278" + "gd-stage-323" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-277": { + "gd-stage-322": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-276", + "parent": "gd-stage-321", "inputs": { "OPERAND1": [ 3, @@ -10014,10 +11094,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-278": { + "gd-stage-323": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-276", + "parent": "gd-stage-321", "inputs": { "VALUE": [ 1, @@ -10036,10 +11116,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-279": { + "gd-stage-324": { "opcode": "procedures_call", - "next": "gd-stage-288", - "parent": "gd-stage-275", + "next": "gd-stage-333", + "parent": "gd-stage-320", "inputs": {}, "fields": {}, "shadow": false, @@ -10052,10 +11132,10 @@ "warp": "true" } }, - "gd-stage-280": { + "gd-stage-325": { "opcode": "data_setvariableto", - "next": "gd-stage-281", - "parent": "gd-stage-288", + "next": "gd-stage-326", + "parent": "gd-stage-333", "inputs": { "VALUE": [ 1, @@ -10074,10 +11154,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-281": { + "gd-stage-326": { "opcode": "data_setvariableto", - "next": "gd-stage-282", - "parent": "gd-stage-280", + "next": "gd-stage-327", + "parent": "gd-stage-325", "inputs": { "VALUE": [ 1, @@ -10096,10 +11176,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-282": { + "gd-stage-327": { "opcode": "data_setvariableto", - "next": "gd-stage-283", - "parent": "gd-stage-281", + "next": "gd-stage-328", + "parent": "gd-stage-326", "inputs": { "VALUE": [ 1, @@ -10118,10 +11198,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-283": { + "gd-stage-328": { "opcode": "data_setvariableto", - "next": "gd-stage-285", - "parent": "gd-stage-282", + "next": "gd-stage-330", + "parent": "gd-stage-327", "inputs": { "VALUE": [ 1, @@ -10140,10 +11220,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-284": { + "gd-stage-329": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-285", + "parent": "gd-stage-330", "inputs": { "INDEX": [ 1, @@ -10162,14 +11242,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-285": { + "gd-stage-330": { "opcode": "data_setvariableto", - "next": "gd-stage-287", - "parent": "gd-stage-283", + "next": "gd-stage-332", + "parent": "gd-stage-328", "inputs": { "VALUE": [ 3, - "gd-stage-284", + "gd-stage-329", [ 10, "" @@ -10185,10 +11265,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-286": { + "gd-stage-331": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-287", + "parent": "gd-stage-332", "inputs": { "INDEX": [ 1, @@ -10207,14 +11287,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-287": { + "gd-stage-332": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-285", + "parent": "gd-stage-330", "inputs": { "VALUE": [ 3, - "gd-stage-286", + "gd-stage-331", [ 10, "" @@ -10230,46 +11310,46 @@ "shadow": false, "topLevel": false }, - "gd-stage-288": { + "gd-stage-333": { "opcode": "control_if", - "next": "gd-stage-276", - "parent": "gd-stage-279", + "next": "gd-stage-321", + "parent": "gd-stage-324", "inputs": { "CONDITION": [ 2, - "gd-stage-289" + "gd-stage-334" ], "SUBSTACK": [ 2, - "gd-stage-280" + "gd-stage-325" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-289": { + "gd-stage-334": { "opcode": "operator_or", "next": null, - "parent": "gd-stage-288", + "parent": "gd-stage-333", "inputs": { "OPERAND1": [ 2, - "gd-stage-290" + "gd-stage-335" ], "OPERAND2": [ 2, - "gd-stage-291" + "gd-stage-336" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-290": { + "gd-stage-335": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-289", + "parent": "gd-stage-334", "inputs": { "OPERAND1": [ 3, @@ -10295,10 +11375,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-291": { + "gd-stage-336": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-289", + "parent": "gd-stage-334", "inputs": { "OPERAND1": [ 3, @@ -10324,9 +11404,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-292": { + "gd-stage-337": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-301", + "next": "gd-stage-346", "parent": null, "inputs": {}, "fields": { @@ -10340,10 +11420,10 @@ "x": 20, "y": 3020 }, - "gd-stage-293": { + "gd-stage-338": { "opcode": "data_setvariableto", - "next": "gd-stage-294", - "parent": "gd-stage-301", + "next": "gd-stage-339", + "parent": "gd-stage-346", "inputs": { "VALUE": [ 1, @@ -10362,10 +11442,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-294": { + "gd-stage-339": { "opcode": "data_setvariableto", - "next": "gd-stage-295", - "parent": "gd-stage-293", + "next": "gd-stage-340", + "parent": "gd-stage-338", "inputs": { "VALUE": [ 1, @@ -10384,10 +11464,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-295": { + "gd-stage-340": { "opcode": "data_setvariableto", - "next": "gd-stage-297", - "parent": "gd-stage-294", + "next": "gd-stage-342", + "parent": "gd-stage-339", "inputs": { "VALUE": [ 1, @@ -10406,10 +11486,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-296": { + "gd-stage-341": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-297", + "parent": "gd-stage-342", "inputs": { "INDEX": [ 3, @@ -10433,14 +11513,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-297": { + "gd-stage-342": { "opcode": "data_setvariableto", - "next": "gd-stage-299", - "parent": "gd-stage-295", + "next": "gd-stage-344", + "parent": "gd-stage-340", "inputs": { "VALUE": [ 3, - "gd-stage-296", + "gd-stage-341", [ 10, "" @@ -10456,10 +11536,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-298": { + "gd-stage-343": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-299", + "parent": "gd-stage-344", "inputs": { "INDEX": [ 3, @@ -10483,14 +11563,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-299": { + "gd-stage-344": { "opcode": "data_setvariableto", - "next": "gd-stage-300", - "parent": "gd-stage-297", + "next": "gd-stage-345", + "parent": "gd-stage-342", "inputs": { "VALUE": [ 3, - "gd-stage-298", + "gd-stage-343", [ 10, "" @@ -10506,10 +11586,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-300": { + "gd-stage-345": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-299", + "parent": "gd-stage-344", "inputs": { "VALUE": [ 1, @@ -10528,46 +11608,46 @@ "shadow": false, "topLevel": false }, - "gd-stage-301": { + "gd-stage-346": { "opcode": "control_if", - "next": "gd-stage-305", - "parent": "gd-stage-292", + "next": "gd-stage-350", + "parent": "gd-stage-337", "inputs": { "CONDITION": [ 2, - "gd-stage-302" + "gd-stage-347" ], "SUBSTACK": [ 2, - "gd-stage-293" + "gd-stage-338" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-302": { + "gd-stage-347": { "opcode": "operator_or", "next": null, - "parent": "gd-stage-301", + "parent": "gd-stage-346", "inputs": { "OPERAND1": [ 2, - "gd-stage-303" + "gd-stage-348" ], "OPERAND2": [ 2, - "gd-stage-304" + "gd-stage-349" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-303": { + "gd-stage-348": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-302", + "parent": "gd-stage-347", "inputs": { "OPERAND1": [ 3, @@ -10593,10 +11673,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-304": { + "gd-stage-349": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-302", + "parent": "gd-stage-347", "inputs": { "OPERAND1": [ 3, @@ -10622,28 +11702,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-305": { + "gd-stage-350": { "opcode": "control_if", "next": null, - "parent": "gd-stage-301", + "parent": "gd-stage-346", "inputs": { "CONDITION": [ 2, - "gd-stage-306" + "gd-stage-351" ], "SUBSTACK": [ 2, - "gd-stage-314" + "gd-stage-359" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-306": { + "gd-stage-351": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-305", + "parent": "gd-stage-350", "inputs": { "OPERAND1": [ 3, @@ -10669,28 +11749,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-307": { + "gd-stage-352": { "opcode": "operator_and", "next": null, - "parent": "gd-stage-314", + "parent": "gd-stage-359", "inputs": { "OPERAND1": [ 2, - "gd-stage-308" + "gd-stage-353" ], "OPERAND2": [ 2, - "gd-stage-309" + "gd-stage-354" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-308": { + "gd-stage-353": { "opcode": "operator_gt", "next": null, - "parent": "gd-stage-307", + "parent": "gd-stage-352", "inputs": { "OPERAND1": [ 3, @@ -10716,10 +11796,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-309": { + "gd-stage-354": { "opcode": "operator_gt", "next": null, - "parent": "gd-stage-307", + "parent": "gd-stage-352", "inputs": { "OPERAND1": [ 1, @@ -10745,32 +11825,32 @@ "shadow": false, "topLevel": false }, - "gd-stage-310": { + "gd-stage-355": { "opcode": "control_if_else", "next": null, - "parent": "gd-stage-314", + "parent": "gd-stage-359", "inputs": { "CONDITION": [ 2, - "gd-stage-311" + "gd-stage-356" ], "SUBSTACK": [ 2, - "gd-stage-312" + "gd-stage-357" ], "SUBSTACK2": [ 2, - "gd-stage-313" + "gd-stage-358" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-311": { + "gd-stage-356": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-310", + "parent": "gd-stage-355", "inputs": { "OPERAND1": [ 3, @@ -10796,10 +11876,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-312": { + "gd-stage-357": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-310", + "parent": "gd-stage-355", "inputs": { "VALUE": [ 1, @@ -10818,10 +11898,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-313": { + "gd-stage-358": { "opcode": "data_changevariableby", "next": null, - "parent": "gd-stage-310", + "parent": "gd-stage-355", "inputs": { "VALUE": [ 1, @@ -10840,28 +11920,28 @@ "shadow": false, "topLevel": false }, - "gd-stage-314": { + "gd-stage-359": { "opcode": "control_if", - "next": "gd-stage-315", - "parent": "gd-stage-305", + "next": "gd-stage-360", + "parent": "gd-stage-350", "inputs": { "CONDITION": [ 2, - "gd-stage-307" + "gd-stage-352" ], "SUBSTACK": [ 2, - "gd-stage-310" + "gd-stage-355" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-315": { + "gd-stage-360": { "opcode": "data_setvariableto", - "next": "gd-stage-316", - "parent": "gd-stage-314", + "next": "gd-stage-361", + "parent": "gd-stage-359", "inputs": { "VALUE": [ 1, @@ -10880,10 +11960,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-316": { + "gd-stage-361": { "opcode": "data_setvariableto", - "next": "gd-stage-318", - "parent": "gd-stage-315", + "next": "gd-stage-363", + "parent": "gd-stage-360", "inputs": { "VALUE": [ 1, @@ -10902,10 +11982,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-317": { + "gd-stage-362": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-318", + "parent": "gd-stage-363", "inputs": { "INDEX": [ 3, @@ -10929,14 +12009,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-318": { + "gd-stage-363": { "opcode": "data_setvariableto", - "next": "gd-stage-320", - "parent": "gd-stage-316", + "next": "gd-stage-365", + "parent": "gd-stage-361", "inputs": { "VALUE": [ 3, - "gd-stage-317", + "gd-stage-362", [ 10, "" @@ -10952,10 +12032,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-319": { + "gd-stage-364": { "opcode": "data_itemoflist", "next": null, - "parent": "gd-stage-320", + "parent": "gd-stage-365", "inputs": { "INDEX": [ 3, @@ -10979,14 +12059,14 @@ "shadow": false, "topLevel": false }, - "gd-stage-320": { + "gd-stage-365": { "opcode": "data_setvariableto", - "next": "gd-stage-321", - "parent": "gd-stage-318", + "next": "gd-stage-366", + "parent": "gd-stage-363", "inputs": { "VALUE": [ 3, - "gd-stage-319", + "gd-stage-364", [ 10, "" @@ -11002,10 +12082,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-321": { + "gd-stage-366": { "opcode": "data_setvariableto", "next": null, - "parent": "gd-stage-320", + "parent": "gd-stage-365", "inputs": { "VALUE": [ 1, @@ -11024,9 +12104,9 @@ "shadow": false, "topLevel": false }, - "gd-stage-322": { + "gd-stage-367": { "opcode": "event_whenbroadcastreceived", - "next": "gd-stage-326", + "next": "gd-stage-380", "parent": null, "inputs": {}, "fields": { @@ -11040,10 +12120,10 @@ "x": 20, "y": 3170 }, - "gd-stage-323": { + "gd-stage-368": { "opcode": "data_setvariableto", - "next": "gd-stage-324", - "parent": "gd-stage-326", + "next": "gd-stage-369", + "parent": "gd-stage-380", "inputs": { "VALUE": [ 1, @@ -11062,10 +12142,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-324": { + "gd-stage-369": { "opcode": "data_setvariableto", - "next": "gd-stage-325", - "parent": "gd-stage-323", + "next": "gd-stage-370", + "parent": "gd-stage-368", "inputs": { "VALUE": [ 1, @@ -11084,10 +12164,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-325": { + "gd-stage-370": { "opcode": "data_setvariableto", - "next": null, - "parent": "gd-stage-324", + "next": "gd-stage-371", + "parent": "gd-stage-369", "inputs": { "VALUE": [ 1, @@ -11106,46 +12186,244 @@ "shadow": false, "topLevel": false }, - "gd-stage-326": { + "gd-stage-371": { + "opcode": "data_setvariableto", + "next": "gd-stage-372", + "parent": "gd-stage-370", + "inputs": { + "VALUE": [ + 1, + [ + 4, + 0 + ] + ] + }, + "fields": { + "VARIABLE": [ + "ground stop firing row", + "ground-stop-firing-row" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-372": { + "opcode": "data_setvariableto", + "next": "gd-stage-373", + "parent": "gd-stage-371", + "inputs": { + "VALUE": [ + 1, + [ + 4, + 0 + ] + ] + }, + "fields": { + "VARIABLE": [ + "fire mask derota", + "fire-mask-derota" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-373": { + "opcode": "data_setvariableto", + "next": "gd-stage-374", + "parent": "gd-stage-372", + "inputs": { + "VALUE": [ + 1, + [ + 4, + 0 + ] + ] + }, + "fields": { + "VARIABLE": [ + "fire mask logram", + "fire-mask-logram" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-374": { + "opcode": "data_setvariableto", + "next": "gd-stage-375", + "parent": "gd-stage-373", + "inputs": { + "VALUE": [ + 1, + [ + 4, + 0 + ] + ] + }, + "fields": { + "VARIABLE": [ + "fire mask zoshi", + "fire-mask-zoshi" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-375": { + "opcode": "data_setvariableto", + "next": "gd-stage-376", + "parent": "gd-stage-374", + "inputs": { + "VALUE": [ + 1, + [ + 4, + 0 + ] + ] + }, + "fields": { + "VARIABLE": [ + "fire mask terrazi", + "fire-mask-terrazi" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-376": { + "opcode": "data_setvariableto", + "next": "gd-stage-377", + "parent": "gd-stage-375", + "inputs": { + "VALUE": [ + 1, + [ + 4, + 0 + ] + ] + }, + "fields": { + "VARIABLE": [ + "fire mask kapi", + "fire-mask-kapi" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-377": { + "opcode": "data_setvariableto", + "next": "gd-stage-378", + "parent": "gd-stage-376", + "inputs": { + "VALUE": [ + 1, + [ + 4, + 0 + ] + ] + }, + "fields": { + "VARIABLE": [ + "fire mask boza logram", + "fire-mask-boza-logram" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-378": { + "opcode": "data_setvariableto", + "next": "gd-stage-379", + "parent": "gd-stage-377", + "inputs": { + "VALUE": [ + 1, + [ + 4, + 0 + ] + ] + }, + "fields": { + "VARIABLE": [ + "fire mask domogram", + "fire-mask-domogram" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-379": { + "opcode": "data_setvariableto", + "next": null, + "parent": "gd-stage-378", + "inputs": { + "VALUE": [ + 1, + [ + 4, + 0 + ] + ] + }, + "fields": { + "VARIABLE": [ + "fire mask andor genesis", + "fire-mask-andor-genesis" + ] + }, + "shadow": false, + "topLevel": false + }, + "gd-stage-380": { "opcode": "control_if", "next": null, - "parent": "gd-stage-322", + "parent": "gd-stage-367", "inputs": { "CONDITION": [ 2, - "gd-stage-327" + "gd-stage-381" ], "SUBSTACK": [ 2, - "gd-stage-323" + "gd-stage-368" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-327": { + "gd-stage-381": { "opcode": "operator_or", "next": null, - "parent": "gd-stage-326", + "parent": "gd-stage-380", "inputs": { "OPERAND1": [ 2, - "gd-stage-328" + "gd-stage-382" ], "OPERAND2": [ 2, - "gd-stage-329" + "gd-stage-383" ] }, "fields": {}, "shadow": false, "topLevel": false }, - "gd-stage-328": { + "gd-stage-382": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-327", + "parent": "gd-stage-381", "inputs": { "OPERAND1": [ 3, @@ -11171,10 +12449,10 @@ "shadow": false, "topLevel": false }, - "gd-stage-329": { + "gd-stage-383": { "opcode": "operator_equals", "next": null, - "parent": "gd-stage-327", + "parent": "gd-stage-381", "inputs": { "OPERAND1": [ 3, diff --git a/src/xevious/runtime_identifiers.json b/src/xevious/runtime_identifiers.json index 744e67a..4c282e9 100644 --- a/src/xevious/runtime_identifiers.json +++ b/src/xevious/runtime_identifiers.json @@ -169,6 +169,46 @@ "name": "value table", "scope": "Stage" }, + "fire-mask-andor-genesis": { + "kind": "variable", + "name": "fire mask andor genesis", + "scope": "Stage" + }, + "fire-mask-boza-logram": { + "kind": "variable", + "name": "fire mask boza logram", + "scope": "Stage" + }, + "fire-mask-derota": { + "kind": "variable", + "name": "fire mask derota", + "scope": "Stage" + }, + "fire-mask-domogram": { + "kind": "variable", + "name": "fire mask domogram", + "scope": "Stage" + }, + "fire-mask-kapi": { + "kind": "variable", + "name": "fire mask kapi", + "scope": "Stage" + }, + "fire-mask-logram": { + "kind": "variable", + "name": "fire mask logram", + "scope": "Stage" + }, + "fire-mask-terrazi": { + "kind": "variable", + "name": "fire mask terrazi", + "scope": "Stage" + }, + "fire-mask-zoshi": { + "kind": "variable", + "name": "fire mask zoshi", + "scope": "Stage" + }, "formation-count": { "kind": "variable", "name": "formation count", @@ -219,6 +259,11 @@ "name": "game state", "scope": "Stage" }, + "ground-stop-firing-row": { + "kind": "variable", + "name": "ground stop firing row", + "scope": "Stage" + }, "hit-slot": { "kind": "variable", "name": "hit slot", diff --git a/tests/test_scratch_project.py b/tests/test_scratch_project.py index 0ff4998..67e385e 100644 --- a/tests/test_scratch_project.py +++ b/tests/test_scratch_project.py @@ -923,6 +923,16 @@ def test_game_director_has_one_stage_owned_transition_path(self) -> None: "ai level", "formation count", "formation type offset", + # DIF-03 per-family fire-permission masks + the ground-stop-firing row. + "ground stop firing row", + "fire mask derota", + "fire mask logram", + "fire mask zoshi", + "fire mask terrazi", + "fire mask kapi", + "fire mask boza logram", + "fire mask domogram", + "fire mask andor genesis", } self.assertTrue(director_state_names.isdisjoint(machinery_names)) self.assertTrue(economy_names.isdisjoint(machinery_names | director_state_names)) @@ -1047,10 +1057,12 @@ def _proccode(definition: dict) -> str: director.TERRAIN_COLUMN_ID, director.SCHEDULE_CURSOR_ID, director.SCHEDULE_FIRED_ID, - # DIF-01/FORM-01 difficulty-director state: Stage-only-written. + # DIF-01/FORM-01/DIF-03 difficulty-director state: Stage-only-written. director.AI_LEVEL_ID, director.FORMATION_COUNT_ID, director.FORMATION_TYPE_OFFSET_ID, + director.GROUND_STOP_FIRING_ROW_ID, + *(mask_id for _suffix, _name, mask_id in director.FIRE_MASK_FAMILIES), } # Read-only reference tables: ingested, hash-pinned authority data no sprite may # mutate (the mutable slot lists are deliberately excluded — allocators write those). @@ -4435,7 +4447,7 @@ def test_full_repository_verification(self) -> None: original_hash, ) self.assertEqual( - "922a237830cbb6042942b24557e6fa6ac9b6920e0fb55f8798586d078d73fdeb", + "dfd51edefb985b98550c76b7bc33f62902a3093355dba02684cd873c6ba02db3", build_hash, ) diff --git a/tests/test_spec_docs.py b/tests/test_spec_docs.py index c1c3f1c..04d74b8 100644 --- a/tests/test_spec_docs.py +++ b/tests/test_spec_docs.py @@ -567,6 +567,20 @@ class DifficultyAndFormations(unittest.TestCase): rather than laundering itself; only the build's DIP-index and numeric constants come from the generator.""" + # Roadmap closure evidence for leaf #56 (difficulty.models-live-state). Each obligation has a + # success path (a positive fixture below / the baked-table & round-trip goldens) and a failure + # path (a biting negative). The success fixtures live in this class; the failure negatives are the + # scratch-vm harness scenarios (`difficulty-and-formations`, `fire-permission-masks`, each with a + # negativeMutation that reddens) and the structural `break_missing_dispatch` negative. + # roadmap-evidence: DIF-01 success (test_ai_level_fold_back, test_baked_tables_match_committed_data) + # roadmap-evidence: DIF-01 failure (harness difficulty-and-formations negative breaks the raise dispatch) + # roadmap-evidence: DIF-02 success (test_score_retune_rule) + # roadmap-evidence: DIF-02 failure (test_score_retune_rule's cap/guard cases; break_missing_dispatch) + # roadmap-evidence: DIF-03 success (test_all_area_schedules_round_trip_from_json arg column, baked masks) + # roadmap-evidence: DIF-03 failure (harness fire-permission-masks negative breaks the logram branch) + # roadmap-evidence: FORM-01 success (test_formation_lookup_reproduces_committed_table, in-domain proof) + # roadmap-evidence: FORM-01 failure (harness difficulty-and-formations negative; the two-sided guard) + def _stage_lists(self): project = json.loads(PROJECT_JSON.read_text()) stage = next(t for t in project["targets"] if t["isStage"]) diff --git a/tools/game_director.py b/tools/game_director.py index c3f8877..be00062 100644 --- a/tools/game_director.py +++ b/tools/game_director.py @@ -423,6 +423,22 @@ def _load_terrain_columns() -> list[int]: FIRE_MASK_PREFIX = "fire_mask_" GROUND_STOP_FIRING_HANDLER = "ground_stop_firing_row" +# DIF-03 per-family fire-permission masks. Area schedules set one mask byte per firing family; the +# byte gates how often that family may fire, and the per-family firing that consumes each mask is the +# enemy slices' (8+). Each family is (handler suffix, Stage display name, Stage id). The handler is +# FIRE_MASK_PREFIX + suffix. +FIRE_MASK_FAMILIES = [ + ("derota", "fire mask derota", "fire-mask-derota"), + ("logram", "fire mask logram", "fire-mask-logram"), + ("zoshi", "fire mask zoshi", "fire-mask-zoshi"), + ("terrazi", "fire mask terrazi", "fire-mask-terrazi"), + ("kapi", "fire mask kapi", "fire-mask-kapi"), + ("boza_logram", "fire mask boza logram", "fire-mask-boza-logram"), + ("domogram", "fire mask domogram", "fire-mask-domogram"), + ("andor_genesis", "fire mask andor genesis", "fire-mask-andor-genesis"), +] +GROUND_STOP_FIRING_ROW_ID = "ground-stop-firing-row" + # Project-defined cabinet difficulty DIP index (four-marker placeholder; the spec records # no arcade power-on default, like RNG_COLD_START_SEED). Index 0 selects increment +2 — # the LOWEST setting that still PROGRESSES (index 1 = +0 would make every raise inert and @@ -1529,6 +1545,20 @@ def arg_at_cursor() -> str: blocks.set_var("formation type offset", FORMATION_TYPE_OFFSET_ID, number(0)), ], ) + # DIF-03 fire-permission masks: each family's `fire_mask_` record sets that family's mask + # byte from the schedule arg; the `ground_stop_firing_row` record sets the ground-stop row. The + # per-family firing that CONSUMES these lands with the enemy slices (8+). + mask_branches = [ + blocks.if_reporter( + blocks.op_eq(handler_at_cursor(), text(FIRE_MASK_PREFIX + suffix)), + [blocks.set_var_expr(name, mask_id, arg_at_cursor())], + ) + for suffix, name, mask_id in FIRE_MASK_FAMILIES + ] + ground_stop_branch = blocks.if_reporter( + blocks.op_eq(handler_at_cursor(), text(GROUND_STOP_FIRING_HANDLER)), + [blocks.set_var_expr("ground stop firing row", GROUND_STOP_FIRING_ROW_ID, arg_at_cursor())], + ) # ENGINE-TODO: the spawn / boss handler dispatch (add_ground_object, add_domogram_with_path, # add_object, *bacura*, andor_genesis_*, sheonite_*) lands with the enemy slices (8+); the # score-adaptive AI re-tune and the fire-permission masks arrive in the later commits of this @@ -1540,6 +1570,8 @@ def arg_at_cursor() -> str: adjust_branch, set_branch, reset_branch, + *mask_branches, + ground_stop_branch, blocks.change_var("schedule fired", SCHEDULE_FIRED_ID, 1), blocks.change_var("schedule cursor", SCHEDULE_CURSOR_ID, 1), ], @@ -1961,6 +1993,11 @@ def stage_blocks() -> dict[str, dict[str, Any]]: blocks.set_var("ai level", AI_LEVEL_ID, number(0)), blocks.set_var("formation count", FORMATION_COUNT_ID, number(0)), blocks.set_var("formation type offset", FORMATION_TYPE_OFFSET_ID, number(0)), + blocks.set_var("ground stop firing row", GROUND_STOP_FIRING_ROW_ID, number(0)), + *( + blocks.set_var(name, mask_id, number(0)) + for _suffix, name, mask_id in FIRE_MASK_FAMILIES + ), ], ) ], @@ -2901,6 +2938,8 @@ def expected_project(project: dict[str, Any]) -> dict[str, Any]: FORMATION_TYPE_OFFSET_ID, FORMATION_INDEX_ID, AI_ADJUST_ID, + GROUND_STOP_FIRING_ROW_ID, + *(mask_id for _suffix, _name, mask_id in FIRE_MASK_FAMILIES), } preserved_variables = { variable_id: value @@ -2968,6 +3007,11 @@ def expected_project(project: dict[str, Any]) -> dict[str, Any]: FORMATION_INDEX_ID: ["formation index", 0], # DIF-02 transient score re-tune addend (machinery, like `formation index`). AI_ADJUST_ID: ["ai adjust", 0], + # DIF-03 per-family fire-permission masks + the ground-stop-firing row (difficulty-director + # state, Stage-written, sprite-read, write-forbidden). Set by the schedule; consumed by the + # enemy slices (8+). All reset to 0 on a world reset, alongside the AI level and formation. + GROUND_STOP_FIRING_ROW_ID: ["ground stop firing row", 0], + **{mask_id: [name, 0] for _suffix, name, mask_id in FIRE_MASK_FAMILIES}, } owned_lists = { ALLOWED_ID, From e8d284f6729ece17e590813688b4b8802e3d069c Mon Sep 17 00:00:00 2001 From: Shane Kidd <33380501+StarshipSuperjam@users.noreply.github.com> Date: Sat, 15 Aug 2026 14:14:34 -0700 Subject: [PATCH 5/5] Address pre-submission review + regenerate the settled-criteria matrix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Post-review fixes (no block-graph change — build hash unchanged, dfd51ede): - Prove, don't assert, the formation-domain guard: the range fixture now models DIF-02's un-folded score adjust at its worst-case +16 over many loop cycles, so the "guard is dead" claim holds under the slice's FULL live dynamics, not just raises/sets (flagged by three review passes). Record 021 tightened to match. - Cover all nine DIF-03 targets live: the harness fire-permission-masks scenario now reaches area 4 and asserts fire_mask_andor_genesis and ground_stop_firing_row are set (previously unexercised). - Correct stale "later commit" comments in game_director.py and record 020 — DIF-02/DIF-03 ship in this same PR, not later. - Add the DIF-03 fire-mask / ground-stop watcher to the playtest checklist. - Align MECHANICS_CATALOG DIF-01/02/03/FORM-01 to "partial" (foundation). - Regenerate .engine/product-spec-matrix.json (the derived settled-acceptance record) after the locked spec's formation acceptance-criterion was corrected — the engine's settled-criteria check requires it to match the spec. Co-Authored-By: Claude Opus 4.8 --- .engine/product-spec-matrix.json | 4 +-- docs/MECHANICS_CATALOG.md | 8 ++--- docs/PLAYTEST_CHECKLIST.md | 6 +++- .../mechanics/020-normal-flying-formations.md | 2 +- docs/mechanics/021-score-adaptive-ai-level.md | 2 +- harness/lib/catalog.js | 17 +++++++---- tests/test_spec_docs.py | 29 +++++++++++++------ tools/game_director.py | 11 +++---- 8 files changed, 51 insertions(+), 28 deletions(-) diff --git a/.engine/product-spec-matrix.json b/.engine/product-spec-matrix.json index 15bdf4b..bbbdb95 100644 --- a/.engine/product-spec-matrix.json +++ b/.engine/product-spec-matrix.json @@ -145,8 +145,8 @@ "who": "engine" }, { - "criterion": "A model fixture over the committed data reproduces formation lookups (AI level + offset, fold-back at 0x80); the build's in-game selection is confirmed in play (a runtime-harness candidate once the enemy/formation slice ships)", - "digest": "sha256:14db719434b37cf2a448988587ad3c46e62454fed6ec6598e493f08d42ae59a4", + "criterion": "A model fixture over the committed data reproduces formation lookups (set-formation indexed by the record offset; raise indexed by the folded AI level; fold-back at 0x80); the build's in-game selection is confirmed in play (a runtime-harness candidate once the enemy/formation slice ships)", + "digest": "sha256:2dcfd47438dea90e3bb21b17beb5d5618a8327d46adcd30d79bd8b2ab511b3dc", "doc": "docs/spec/difficulty-and-formations.md", "how_verified": "Python fixture over the committed tables; operator play for the in-game half", "position": 2, diff --git a/docs/MECHANICS_CATALOG.md b/docs/MECHANICS_CATALOG.md index c9cbe82..0fbec1e 100644 --- a/docs/MECHANICS_CATALOG.md +++ b/docs/MECHANICS_CATALOG.md @@ -49,10 +49,10 @@ document differ, the spec document wins. | AREA-02 | Area object scheduler | partial | AREA-01, SYS-02 | sub: `sub_fn_2__handle_objects`, `obj_fn_tbl`, `area_object_tbl_tbl_normal` | Normal events spawn in recorded order and position. The ordered schedule consume, a lossless slice-6-ready representation of one fixture area (area 1) with a materialized sentinel, and the `schedule fired` observable are built ([016](mechanics/016-area-scheduler.md)); foundation-only — the per-record dispatch is an empty seam (handlers arrive slices 8+) and all 16 tables + the full trace are slice 6. | | AREA-03 | All 16 normal area tables | present | AREA-02 | sub: `area_1_obj_tbl_normal` through `area_16_obj_tbl_normal` | An accelerated trace consumes every normal table without unknown or Super objects. All 16 normal schedules are ingested into the flattened columns with per-area offsets and the accelerated 1–16→7 data trace passes ([017](mechanics/017-all-area-schedules.md)); the trace/round-trip prove the data, the built per-area consume rests on the offset golden + operator playtest. | | AREA-04 | Transitions and 16-to-7 loop | present | AREA-03 | main: `main_gameplay_loop`; sub: `sub_fn_3__handle_next_area` | Areas advance 1–16 then continue at 7, with no win screen. The advance/wrap shipped in AREA-01; with all 16 schedules ingested the loop is data-complete and the accelerated trace confirms 1–16→7 with no win screen ([018](mechanics/018-area-transitions-and-loop.md)) — a data trace, runtime traversal on the operator playtest. | -| DIF-01 | Difficulty setting | present | AREA-02 | sub: `difficulty_tbl`, `sub_2_fn_3__inc_enemy_AI_and_flying_enemies` | Each normal setting starts at its recorded pressure. The adaptive AI level accumulates live from the schedule's raise records and folds back below 0x80 ([019](mechanics/019-difficulty-ai-level.md)); foundation — the AI level is live/observable, its consumption as enemy pressure is slices 8+, and the cabinet DIP is a project-defined placeholder (increment +2). | -| DIF-02 | Score-per-life adaptive AI | present | DIF-01, ECO-01 | sub: `sub_2_fn_23__adjust_AI_level_based_on_score`, `avg_score_per_solvalou` | Fixtures show ordered AI changes from score per craft. The adjust records re-tune the AI level by floor(floor(score/1000)/craft) capped at 16, reading the live score and craft ([021](mechanics/021-score-adaptive-ai-level.md)); foundation — the rule is live and fixture-proven, the visible "playing better = harder" difference needs enemies (slice 8+). | -| DIF-03 | Per-family fire frequency | present | DIF-01, SYS-04 | sub: `sub_2_fn_8__fire_freq_mask_derota` through `sub_2_fn_22__fire_freq_mask_andor_genesis` | Family fire fixtures follow recorded masks. The area schedule sets the eight per-family fire-permission masks + the ground-stop-firing row live from the record bytes ([022](mechanics/022-fire-permission-masks.md)); foundation — the masks are set/observable, the firing that consumes them is slices 8+. | -| FORM-01 | Normal flying formations | present | AREA-02, DIF-01 | sub: `flying_enemy_type_offset_tbl_normal`, `sub_2_fn_2__set_flying_enemies` | Fixtures preserve normal type, count, offsets, and order. The wave size + type-table offset are selected live — set-formation by the record offset, raise by the folded AI level, reset zeroes ([020](mechanics/020-normal-flying-formations.md)); foundation — selection is live/observable, spawning the wave is slice 8. | +| DIF-01 | Difficulty setting | partial | AREA-02 | sub: `difficulty_tbl`, `sub_2_fn_3__inc_enemy_AI_and_flying_enemies` | Each normal setting starts at its recorded pressure. The adaptive AI level accumulates live from the schedule's raise records and folds back below 0x80 ([019](mechanics/019-difficulty-ai-level.md)); foundation — the AI level is live/observable, its consumption as enemy pressure is slices 8+, and the cabinet DIP is a project-defined placeholder (increment +2). | +| DIF-02 | Score-per-life adaptive AI | partial | DIF-01, ECO-01 | sub: `sub_2_fn_23__adjust_AI_level_based_on_score`, `avg_score_per_solvalou` | Fixtures show ordered AI changes from score per craft. The adjust records re-tune the AI level by floor(floor(score/1000)/craft) capped at 16, reading the live score and craft ([021](mechanics/021-score-adaptive-ai-level.md)); foundation — the rule is live and fixture-proven, the visible "playing better = harder" difference needs enemies (slice 8+). | +| DIF-03 | Per-family fire frequency | partial | DIF-01, SYS-04 | sub: `sub_2_fn_8__fire_freq_mask_derota` through `sub_2_fn_22__fire_freq_mask_andor_genesis` | Family fire fixtures follow recorded masks. The area schedule sets the eight per-family fire-permission masks + the ground-stop-firing row live from the record bytes ([022](mechanics/022-fire-permission-masks.md)); foundation — the masks are set/observable, the firing that consumes them is slices 8+. | +| FORM-01 | Normal flying formations | partial | AREA-02, DIF-01 | sub: `flying_enemy_type_offset_tbl_normal`, `sub_2_fn_2__set_flying_enemies` | Fixtures preserve normal type, count, offsets, and order. The wave size + type-table offset are selected live — set-formation by the record offset, raise by the folded AI level, reset zeroes ([020](mechanics/020-normal-flying-formations.md)); foundation — selection is live/observable, spawning the wave is slice 8. | ## Flying enemies and projectiles diff --git a/docs/PLAYTEST_CHECKLIST.md b/docs/PLAYTEST_CHECKLIST.md index 69e5842..fb48899 100644 --- a/docs/PLAYTEST_CHECKLIST.md +++ b/docs/PLAYTEST_CHECKLIST.md @@ -65,7 +65,11 @@ so area position is read from the `area progress`/`area number` variable watcher placeholder, not fidelity:** the cabinet difficulty is a project-chosen default (increment +2), so how *fast* the level climbs is not meaningful yet — only that it climbs, folds, and drives a valid formation is. No enemies spawn from the formation this slice, so this is a watcher check, not an on-screen one; the - exact table correctness is the build-time model fixture's, not the eye's. + exact table correctness is the build-time model fixture's, not the eye's. **You can also tick a + `fire mask *` watcher** (e.g. `fire mask logram`) and **`ground stop firing row`** (DIF-03): each takes + its scheduled byte value as the area scrolls (logram, for instance, is set near the top of area 1) and + resets to 0 on a new game. As with the masks above, no family *fires* from these yet — that is slice 8 — + so this only confirms the schedule sets them. 5. **Repeated deaths and the near-end checkpoint.** Die several times in a row (today: press D; once killers exist, die to a bullet, an enemy, and a Bacura): the full death presentation and sound complete uncut, the craft respawns immediately vulnerable, and nothing from the previous life diff --git a/docs/mechanics/020-normal-flying-formations.md b/docs/mechanics/020-normal-flying-formations.md index 9122706..ee569d9 100644 --- a/docs/mechanics/020-normal-flying-formations.md +++ b/docs/mechanics/020-normal-flying-formations.md @@ -9,7 +9,7 @@ - Acceptance criteria: The baked count/type-offset lists equal a re-derivation from `formations.json` (engine, golden). The selection reproduces every committed entry across the −32..127 domain (engine, model fixture). Over the real committed schedules the selection index never leaves the table's domain (engine, range fixture). In real play a formation is selected whose recorded wave size is 1–6 (engine, scratch-vm harness). Operator: with the `formation count` / `formation type offset` watchers open, they change as set-formation and raise records fire and zero on a reset — an inspectable confirmation; no enemies spawn from the selection yet. - Fidelity status: FORM-01 is **partial** (foundation) — the formation *selection* (both index paths, the reset, and the guarded table read) is built, live, and observable, and matches the reference. What is deferred: *spawning* the selected wave — the slice-8 flying-enemy vertical slice reads `formation count` / `formation type offset` (and the type table in [aerial enemies](../spec/aerial-enemies.md)) to place enemies — so no enemies appear from the formation this slice. - License status: The pinned reference states no reusable license; only derived behavior and the committed, hash-pinned `formations.json` table are used, cited to the settled spec and the data file, and no reference source text or media was reproduced. -- Known deviations or uncertainty: The locked spec previously described the set-formation index as "that offset plus the current AI level"; the reference adds no AI level on that path (it is the offset alone), and the AI level is the index only for the raise path — the spec prose was corrected to match its own cited reference in this pull request, with no data change. The two-sided formation guard leaves the prior formation on an out-of-domain index rather than fabricating a value; the range fixture proves it is never reached under this slice's raise/set dynamics — the score-adaptive term (DIF-02, a later commit of this slice) is the only thing that could in principle drive the index out of domain, and will be recorded there. +- Known deviations or uncertainty: The locked spec previously described the set-formation index as "that offset plus the current AI level"; the reference adds no AI level on that path (it is the offset alone), and the AI level is the index only for the raise path — the spec prose was corrected to match its own cited reference in this pull request, with no data change. The two-sided formation guard leaves the prior formation on an out-of-domain index rather than fabricating a value; the range fixture proves it is never reached under this slice's FULL dynamics — raises, set-formation, and [DIF-02](021-score-adaptive-ai-level.md)'s un-folded score adjust at its worst-case cap — so the guard is a defensive dead branch (DIF-02 is built in this same pull request; its interaction is recorded in 021). - [x] No assembly or other source code was copied into the Scratch project. - [x] No arcade ROM files were acquired, opened, extracted, or distributed. - [x] Any transferred graphics or audio are recorded in `src/xevious/assets/provenance.json`. diff --git a/docs/mechanics/021-score-adaptive-ai-level.md b/docs/mechanics/021-score-adaptive-ai-level.md index a98286b..c25fb2b 100644 --- a/docs/mechanics/021-score-adaptive-ai-level.md +++ b/docs/mechanics/021-score-adaptive-ai-level.md @@ -9,7 +9,7 @@ - Acceptance criteria: A model fixture implementing the documented rule reproduces the re-tune (score per reserve craft, floored, capped at 16, guarded at zero) — engine, Python fixture. The build's in-game re-tune is confirmed in play (the spec defers this: "playing better produces visibly harder waves" needs the enemy slices to be observable) — operator, deferred. - Fidelity status: DIF-02 is **partial** (foundation) — the re-tune is built and runs live (it fires on adjust records reading the live score and craft), and the rule is reference-faithful. What is deferred, per the spec's own acceptance table: the operator-visible *difference* ("playing better = harder waves") needs the enemy waves the AI level scales, which arrive with the enemy slices (8+). - License status: The pinned reference states no reusable license; only the derived re-tune rule is used, cited to the settled spec, and no reference source text or media was reproduced. -- Known deviations or uncertainty: Reserve is mapped to the live `craft` count with no subtraction, matching the reference's `solvalou_number`; whether that count includes the craft currently in play (a possible off-by-one against a strict "in reserve" reading) is a residual uncertainty recorded here rather than silently chosen. The adjust does **not** fold back (per the reference), so it can push the AI level above 0x80 transiently; the next raise folds it, and because the raise's re-select uses the *post-fold* level and a set-formation uses its own offset, the formation index stays in the table's domain (the two-sided formation guard in [FORM-01](020-normal-flying-formations.md) is the backstop). In normal play the level stays well below the byte wrap because raises fold it, so no explicit mod-256 is applied — recorded rather than left implied. The generated adjust's live execution rests on the model rule plus the structural dispatch check and the operator playtest: the Python block interpreter executes only `set`/`if` (not the `repeat until` consume), and the scratch-vm harness observes the AI level but cannot isolate an adjust from the raises in the same run — matching the spec's deferral of DIF-02's in-game half. +- Known deviations or uncertainty: Reserve is mapped to the live `craft` count with no subtraction, matching the reference's `solvalou_number`; whether that count includes the craft currently in play (a possible off-by-one against a strict "in reserve" reading) is a residual uncertainty recorded here rather than silently chosen. The adjust does **not** fold back (per the reference), so it can push the AI level above 0x80 transiently; because the raise's re-select uses the *post-fold* level and a set-formation uses its own offset, the formation index stays in the table's domain. This is not left to inspection: `test_formation_index_in_domain_over_committed_schedules` now walks the real schedule with the adjust forced to its worst-case +16 and proves every selection index stays in −32..127. The margin holds because the committed schedule interleaves few consecutive adjusts between raises, so the raise's single −0x40 fold always recovers a < 0x80 index; a future schedule or DIP change that broke that margin reddens that fixture (the two-sided formation guard in [FORM-01](020-normal-flying-formations.md) is the fail-safe backstop). In normal play the level stays well below the byte wrap because raises fold it, so no explicit mod-256 is applied — recorded rather than left implied. The generated adjust's live execution rests on the model rule plus the structural dispatch check and the operator playtest: the Python block interpreter executes only `set`/`if` (not the `repeat until` consume), and the scratch-vm harness observes the AI level but cannot isolate an adjust from the raises in the same run — matching the spec's deferral of DIF-02's in-game half. - [x] No assembly or other source code was copied into the Scratch project. - [x] No arcade ROM files were acquired, opened, extracted, or distributed. - [x] Any transferred graphics or audio are recorded in `src/xevious/assets/provenance.json`. diff --git a/harness/lib/catalog.js b/harness/lib/catalog.js index be8505c..99311e9 100644 --- a/harness/lib/catalog.js +++ b/harness/lib/catalog.js @@ -353,11 +353,14 @@ export const SCENARIOS = [ assert.ok(reachPlaying(vm), 'precondition: game reaches playing'); // The schedule sets the fire masks from the record bytes as it scrolls. One headless pump // covers many game ticks, so a specific transient value (logram is set to 255, then 31 within - // one pump) can be stepped over — assert the robust fact instead: the logram mask, and other - // families, are SEEN set to a non-zero scheduled value. (The FIRING that consumes them is the - // enemy slices'.) + // one pump) can be stepped over — assert the robust fact instead: each family mask, the + // ground-stop-firing row, and Andor Genesis (first scheduled in area 4) are SEEN set to a + // non-zero scheduled value. (The FIRING that consumes them is the enemy slices'.) The window is + // long enough to cross into area 4 so all nine DIF-03 targets are actually exercised. let logramSet = false; let otherMaskSet = false; + let andorSet = false; + let groundStopSet = false; const others = [ 'fire-mask-derota', 'fire-mask-zoshi', @@ -366,16 +369,20 @@ export const SCENARIOS = [ 'fire-mask-boza-logram', 'fire-mask-domogram', ]; - for (let i = 0; i < 60; i += 1) { + for (let i = 0; i < 130; i += 1) { step(vm, 1); if (readVar(vm, 'fire-mask-logram') > 0) logramSet = true; + if (readVar(vm, 'fire-mask-andor-genesis') > 0) andorSet = true; + if (readVar(vm, 'ground-stop-firing-row') > 0) groundStopSet = true; for (const id of others) if (readVar(vm, id) > 0) otherMaskSet = true; } - return { logramSet, otherMaskSet }; + return { logramSet, otherMaskSet, andorSet, groundStopSet }; }, assert(obs) { assert.equal(obs.logramSet, true, 'the logram fire mask is set to a non-zero scheduled value'); assert.equal(obs.otherMaskSet, true, 'other family fire masks are set live too'); + assert.equal(obs.andorSet, true, 'the Andor Genesis fire mask is set live (area 4)'); + assert.equal(obs.groundStopSet, true, 'the ground-stop-firing row is set live'); }, // Break the logram mask branch (its handler == comparison never matches) so it is never set → // the logramSet assertion fails. diff --git a/tests/test_spec_docs.py b/tests/test_spec_docs.py index 04d74b8..40beb6d 100644 --- a/tests/test_spec_docs.py +++ b/tests/test_spec_docs.py @@ -652,22 +652,28 @@ def retune(score, craft): self.assertEqual(0, retune(50000, 0), "zero craft is guarded, adds nothing") def test_formation_index_in_domain_over_committed_schedules(self): - # FORM-01 / DIF-01 range proof: walk the committed schedules in the accelerated 1..16 then - # 7..16 loop order, tracking the AI level through raises (fold-back) and picking the formation - # index exactly as the emitted dispatch does — set-formation: the record offset; raise: the - # folded AI level. Assert EVERY index lands in the table's -32..127 domain, so the generator's - # two-sided guard is a proven-dead defensive branch under this slice's dynamics, and that BOTH - # selection paths are actually exercised. (DIF-02's score term, a later commit, is the only - # thing that could push the index out of domain; that is recorded with DIF-02.) + # FORM-01 / DIF-01 / DIF-02 range proof: walk the committed schedules in the accelerated + # 1..16 then 7..16 loop order, tracking the AI level through EVERY handler that moves it — the + # raise (with fold-back) AND DIF-02's score adjust forced to its worst case (+16, un-folded, + # per the reference) — and pick the formation index exactly as the emitted dispatch does: + # set-formation uses the record offset; the raise uses the folded AI level (adjust selects no + # formation). Assert EVERY selection index lands in the table's -32..127 domain, so the + # generator's two-sided guard is a proven-dead defensive branch under this slice's FULL live + # dynamics (not just raises/sets), and that all three AI-moving/selecting paths are exercised. + # The margin is real, not accidental: consecutive adjusts between raises are few, so the raise's + # single -0x40 fold always recovers a < 0x80 index; if a future schedule or DIP change broke + # that, THIS fixture reddens rather than the guard silently freezing the formation. + DIF02_MAX_ADDEND = 16 # the score-per-craft re-tune is capped at 16 (docs/spec) areas = {a["area"]: a["records"] for a in json.loads((DATA / "area-schedules.json").read_text())["areas"]} inc = json.loads((DATA / "difficulty.json").read_text())["difficulty_tbl"]["values"][ director.DIFFICULTY_DIP_INDEX ] lo = director.FORMATION_MIN_INDEX hi = director.FORMATION_MIN_INDEX + director.FORMATION_TABLE_LEN - 1 - order = list(range(1, 17)) + list(range(7, 17)) * 6 # a few loop cycles for steady state + # Many loop cycles so any slow AI-level drift (adjust outrunning the folds) would surface. + order = list(range(1, 17)) + list(range(7, 17)) * 20 ai = 0 - raises = sets = 0 + raises = sets = adjusts = 0 for area in order: for record in areas[area]: handler = record["handler"] @@ -677,6 +683,10 @@ def test_formation_index_in_domain_over_committed_schedules(self): ai -= director.AI_LEVEL_FOLD_SUBTRACT index = ai raises += 1 + elif handler == "adjust_ai_level_from_score": + ai += DIF02_MAX_ADDEND # worst case; the reference does NOT fold this add + adjusts += 1 + continue # adjust re-tunes the level but selects no formation elif handler == "set_flying_formation": index = record["params"]["formation_offset"] sets += 1 @@ -685,6 +695,7 @@ def test_formation_index_in_domain_over_committed_schedules(self): self.assertTrue(lo <= index <= hi, f"formation index {index} out of domain (area {area})") self.assertGreater(raises, 0, "the raise re-select path must be exercised") self.assertGreater(sets, 0, "the set-formation path must be exercised") + self.assertGreater(adjusts, 0, "the DIF-02 adjust contribution must be exercised") if __name__ == "__main__": diff --git a/tools/game_director.py b/tools/game_director.py index be00062..e1e0b98 100644 --- a/tools/game_director.py +++ b/tools/game_director.py @@ -1403,8 +1403,9 @@ def _select_formation(blocks: Blocks, index_value: Any) -> list[str]: # the assignment is GUARDED on BOTH bounds: an out-of-domain index leaves the prior formation # unchanged (no faithful ROM-adjacent value exists to fabricate). The build-time fixture in # tests/test_spec_docs.py proves the real committed schedules never leave the domain under this - # slice's dynamics, so the guard is defensive; DIF-02's score term (a later commit) is where an - # index could in principle exceed it, recorded there. + # slice's full dynamics (raises, set-formation, AND DIF-02's un-folded score adjust at its + # worst-case cap), so the guard is a defensive dead branch; a future schedule/DIP change that + # broke that margin would redden that fixture, not fail silently here. if isinstance(index_value, str): set_index = blocks.set_var_expr("formation index", FORMATION_INDEX_ID, index_value) else: @@ -1560,9 +1561,9 @@ def arg_at_cursor() -> str: [blocks.set_var_expr("ground stop firing row", GROUND_STOP_FIRING_ROW_ID, arg_at_cursor())], ) # ENGINE-TODO: the spawn / boss handler dispatch (add_ground_object, add_domogram_with_path, - # add_object, *bacura*, andor_genesis_*, sheonite_*) lands with the enemy slices (8+); the - # score-adaptive AI re-tune and the fire-permission masks arrive in the later commits of this - # slice. Unhandled records still advance the cursor and count the fire, with no behaviour. + # add_object, *bacura*, andor_genesis_*, sheonite_*) lands with the enemy slices (8+). The + # DIF/FORM handlers (raise, adjust, set/reset formation, the 8 fire masks, ground-stop) are all + # wired above; the still-unhandled spawn/boss records advance the cursor and count the fire only. blocks.substack( loop, [