Files
goon-game/docs/LEVEL_SOLUTION_GRAPHS.md
T

40 KiB
Raw Blame History

Графы решений уровней 1–18

Документ фиксирует авторский маршрут каждого уровня текущего vertical slice. Он получен из LevelCatalog, моделей LevelDefinition и фактической логики GameView, затем проверен device-level ботами через production-команды движения и прыжка. targetDeaths ниже — целевое число жертв для результата уровня, но оно не доказывает минимальность решения.

На 19 августа 2026 года intended route всех уровней 1–18 автоматически выполнен по три раза подряд без retry masking. Device-тесты управляют production GameView через те же флаги, что и touch-контролы. Для уровня 8 отдельно проверено восстановление после истечения таймера на дальней стороне PIT.

Семантика, общая для графов

  • PRESSURE активен, пока с его box пересекается достаточная масса живого игрока и/или тел (requiredMass). Сигнал не защёлкивается.
  • TOGGLE меняет значение сигнала только на фронте контакта; повторный вход переключает его обратно.
  • TIMED запускает таймер только на фронте контакта; удержание на переключателе не перезапускает истёкший таймер.
  • Door.requiredSignals использует AND-семантику: дверь открыта, только когда активны все указанные сигналы.
  • Управляемая движущаяся платформа накапливает motionTime только при активном controlId; при потере сигнала она замирает в текущей фазе GameMath.pingPong.
  • SPIKES оставляет закреплённое тело над шипами; SAW передаёт телу impulseX/impulseY; FREEZER создаёт неподвижный блок 104×104; ELECTRIC оставляет закреплённое проводящее тело внутри опасности; CRUSHER создаёт низкое CRUSHED-тело; FIRE оставляет твёрдое BURNED-тело без pressure mass; PIT тела не оставляет.
  • Тела являются твёрдыми опорами для игрока. Смерть сохраняет тела и состояния уровня, respawn возвращает нового игрока в spawnX/spawnY; restart очищает состояние.
  • Пересечение живого игрока с goal переводит сцену в COMPLETE.

Уровень 1 — The Volunteer

Статус: доказан ботом, 3/3 последовательных прохождения без смертей. Ожидаемые смерти: 0 (targetDeaths=0). Источник: LevelCatalog.level1(); уступы (640,760,230) и (1060,690,250); goal=(1690,770,86,110).

Solution graph 1

Goal расположен справа от двух перекрывающих путь уступов
→ разогнаться вправо и запрыгнуть на уступ x=640..870
→ сохранить движение и перепрыгнуть на более высокий уступ x=1060..1310
→ спуститься на сплошной floor(0,1920)
→ пересечь goal x=1690..1776
→ COMPLETE без смерти

Механика и сигналы: только движение, прыжок и статические Platform; сигналов и дверей нет.

Bot checkpoints: playerX>640 при playerY≤660 → playerX>1060 при playerY≤590 → playerX>1310 → completed=true, deaths=0.

Softlock/неопределённость: intended route и окна двух прыжков воспроизводимо подтверждены. Альтернативный проход под/мимо уступов отдельно не проверялся.

Уровень 2 — A Useful End

Статус: доказан ботом, 3/3 последовательных прохождения с тремя телами. Ожидаемые смерти: 3 (targetDeaths=3). Источник: LevelCatalog.level2(); SPIKES=(610,850,260,30); статичный уступ (1180,740,240); goal=(1830,770,86,110).

Solution graph 2

Spike lane x=610..870 перекрывает наземный маршрут
→ первый доброволец погибает на ближнем краю SPIKES
→ закреплённое тело становится первой твёрдой опорой
→ следующие добровольцы продвигаются прыжками и оставляют ещё два тела
→ цепочка из трёх тел образует предусмотренный путь через lane
→ следующий доброволец пересекает тела, возвращается на floor
→ проходит уступ x=1180..1420 и достигает goal
→ COMPLETE с целевыми тремя смертями

Механика и сигналы: SPIKES закрепляет каждое тело на hazard.box.y-corpse.height; двери и сигналы отсутствуют.

Bot checkpoints: после каждой предусмотренной жертвы deaths/corpseCount=1/1, 2/2, 3/3; затем живой игрок playerX>870; финально completed=true, deaths=3.

Softlock/неопределённость: intended route с тремя телами воспроизводимо подтверждён. Отдельная попытка прямого zero-death прохода не подтвердила sequence break, но не является исчерпывающим negative-тестом; минимальность трёх смертей остаётся открытым follow-up.

Уровень 3 — Dead Weight

Статус: доказан ботом, 3/3 последовательных прохождения с одной жертвой. Ожидаемые смерти: 1 (targetDeaths=1). Источник: LevelCatalog.level3(); SAW=(565,760,92,92), impulse (0,-150); PRESSURE=(540,860,150,20), signalId="gate"; дверь (1110,570,78,310) требует "gate".

Solution graph 3

Door закрывает путь к goal
→ для Door требуется активный signal "gate"
→ PRESSURE удерживает "gate" только при постоянной массе
→ первый доброволец входит в SAW над зоной плиты
→ тело с нулевым horizontal impulse оседает на PRESSURE
→ "gate" становится active и Door открывается
→ respawn следующего добровольца
→ перепрыгнуть SAW/тело, пройти открытую Door
→ пересечь goal и получить COMPLETE

Механика и сигналы: checkpoint цепочки — corpseCount=1 → switchContact(PRESSURE)=true → signalActive("gate")=true → doorOpen=true.

Bot checkpoints: deaths=1, corpseCount=1; после respawn playerAlive=true; требуется расширить snapshot состоянием "gate" либо использовать allDoorsOpen=true; затем playerX>1188 и completed=true.

Softlock/неопределённость: доставка тела на плиту, удержание двери и последующий проход подтверждены в трёх последовательных запусках. Альтернативные точки контакта с SAW отдельно не перебирались.

Уровень 4 — The Long Lift

Статус: доказан ботом, 3/3 последовательных прохождения без смертей. Ожидаемые смерти: 0 (targetDeaths=0). Источник: LevelCatalog.level4(); TOGGLE=(520,820,72,60), signalId="lift"; moving platform (1040,790,260,34), travel (0,-390), period 5.2, controlId="lift"; PIT=(1500,880,320,200); верхний уступ (1660,500,540); goal=(1960,390,86,110).

Solution graph 4

Goal находится на верхней галерее за PIT
→ обычный прыжок с floor не даёт требуемой высоты
→ один раз войти в TOGGLE и включить signal "lift"
→ активный "lift" запускает вертикальный цикл moving platform
→ запрыгнуть на platform x=1040..1300 и подняться
→ в верхней фазе прыгнуть вправо через край PIT на ledge x=1660..2200
→ пройти по галерее до goal
→ COMPLETE без смерти

Механика и сигналы: фронт контакта TOGGLE → toggleSignals["lift"]=true → растёт motionTime платформы → travelY*pingPong поднимает её максимум на 390.

Bot checkpoints: signal "lift"=true; координата платформы уменьшается от y=790; игрок получает supportIndex движущейся платформы; затем playerX≥1660, playerY≤400; финально completed=true, deaths=0. Для этого snapshot нужно расширить сигналами, supportIndex и состоянием платформы.

Softlock/неопределённость: lift→gallery прыжок подтверждён в трёх последовательных запусках. Повторный контакт с TOGGLE по-прежнему выключает сигнал и может заморозить платформу; это предусмотренное состояние, доступное для restart.

Уровень 5 — Express Delivery

Статус: доказан LevelFivePlaythroughTest, 3/3 последовательных прохождения. Ожидаемые смерти: 1 (targetDeaths=1); acceptance-тест требует ровно одну. Источник: LevelCatalog.level5(); SAW=(570,760,96,96), impulse (500,-700); уступ (850,800,330); PRESSURE=(930,780,160,20), signalId="gate"; дверь (1390,560,82,320) требует "gate"; goal=(2080,770,86,110).

Solution graph 5

Door закрывает путь к goal
→ для Door требуется signal "gate"
→ удалённую PRESSURE нужно удерживать постоянной массой
→ первый доброволец идёт вправо в SAW
→ SAW убивает и запускает тело impulse (500,-700)
→ тело приземляется на уступе/плите x=930..1090
→ PRESSURE активирует "gate", Door открывается
→ следующий доброволец respawn-ится
→ прыжками пересекает SAW и зону доставленного тела
→ проходит открытую Door и достигает goal
→ COMPLETE

Механика и сигналы: SAW создаёт динамическое тело → контакт тела с PRESSURE → signalActive("gate")=true → allDoorsOpen=true.

Bot checkpoints: реализованы в LevelPlaytestBot.proveLevelFive: первая смерть; corpseCount≥1; allDoorsOpen=true; прыжок после playerX≥390, дополнительный прыжок после playerX≥750; затем completed=true. Тест проверяет completed, смерть, сохранённое тело и факт открытия двери.

Softlock/неопределённость: основной маршрут воспроизводимо подтверждён тремя последовательными запусками. Альтернативные решения и физическая стабильность на нескольких frame rates этим тестом не покрыты.

Уровень 6 — Cold Comfort

Статус: доказан ботом, 3/3 последовательных прохождения с frozen stepping stone. Ожидаемые смерти: 1 (targetDeaths=1). Источник: LevelCatalog.level6(); FREEZER=(690,776,100,104); floor заканчивается на x=1120; уступы (810,590,520) и (1430,610,570); goal=(1880,500,86,110).

Solution graph 6

Высокий уступ x=810..1330 недоступен с уровня floor обычным прыжком
→ первый доброволец входит в FREEZER
→ смерть создаёт неподвижный frozen corpse block 104×104 у x=688
→ следующий доброволец respawn-ится
→ запрыгивает на frozen block как на промежуточную ступень
→ с блока прыгает на высокий уступ x=810..1330
→ пересекает разрыв до уступа x=1430..2000
→ достигает goal на втором уступе
→ COMPLETE с одной смертью

Механика и сигналы: FREEZER принудительно ставит frozen=true, размеры 104×104, позицию (source.x-2, 880-height); тело не обновляется физикой и остаётся твёрдой ступенью. Сигналов нет.

Bot checkpoints: deaths=1, corpseCount=1; после respawn игрок стоит на блоке около playerY=676; затем на первом уступе playerY=490, playerX≥810; на втором playerY=510, playerX≥1430; финально completed=true.

Softlock/неопределённость: первоначальная зона FREEZER перекрывала игрока, стоящего на блоке, на 26 px и делала intended route невозможным. Высота зоны минимально исправлена до 104; floor runner всё ещё погибает, а оба прыжка подтверждены тремя запусками.

Уровень 7 — Live Wire

Статус: доказан ботом, 3/3 последовательных прохождения с conductive corpse. Ожидаемые смерти: 1 (targetDeaths=1). Источник: LevelCatalog.level7(); ELECTRIC=(650,780,110,100), relayId="power"; дверь (1130,560,84,320) требует "power"; goal=(1930,770,86,110).

Solution graph 7

Door закрывает путь к goal
→ Door требует signal "power"
→ "power" активен только от conductive corpse внутри ELECTRIC relay
→ первый доброволец входит в ELECTRIC
→ смерть оставляет закреплённое проводящее тело внутри hazard.box
→ relay "power" становится active и Door открывается
→ следующий доброволец respawn-ится
→ перепрыгивает ELECTRIC/тело и проходит открытую Door
→ достигает goal
→ COMPLETE с одной смертью

Механика и сигналы: ELECTRIC выставляет conductive=true, центрирует тело внутри hazard и закрепляет его; signalActive("power") требует пересечения этого тела с relay hazard.

Bot checkpoints: deaths=1, corpseCount=1; allDoorsOpen=true после появления conductive corpse; после respawn playerX>1214; финально completed=true, deaths=1. Для прямой проверки механики snapshot должен отдельно сообщать conductive state или активный "power".

Softlock/неопределённость: relay-сигнал и прыжок через совмещённые hazard/body подтверждены тремя запусками ровно с одной смертью.

Уровень 8 — Borrowed Time

Статус: intended route и восстановление после истечения таймера доказаны production-input ботом, по три раза подряд. Ожидаемые смерти: 0 (targetDeaths=0). Источник: LevelCatalog.level8(); основной TIMED=(560,810,90,70), signalId="clock", duration 8.0; recovery relay TIMED=(1600,650,90,70), duration 3.5; moving platform (910,770,320,34), travel (380,0), period 4.0, controlId="clock"; PIT=(1040,880,470,200); дверь (1770,560,82,320) требует "clock"; goal=(2220,600,86,110).

Solution graph 8

PIT разрывает floor, а Door закрывает дальнейший путь
→ войти в TIMED и запустить signal "clock" на 8.0 s
→ "clock" одновременно запускает horizontal moving platform и открывает Door
→ без задержки добежать до края floor x=1040
→ прыгнуть на moving platform и пересечь PIT
→ сойти на правый floor x≥1510
→ пройти Door x=1770..1852 до истечения "clock"
→ запрыгнуть на ledge x=1980..2450
→ пересечь goal и получить COMPLETE без смерти

Ветка восстановления после пересечения PIT:
→ дождаться истечения "clock" на правом floor x≥1510
→ Door закрывается и подтверждает прежнюю trap-state
→ намеренно прыгнуть в высокий recovery relay x=1600, y=650
→ повторно запустить "clock" на 3.5 s
→ пройти Door и достичь goal без смерти/restart

Механика и сигналы: фронт контакта основного TIMED → timedSignals["clock"]=8.0 → движение платформы по travelX=380 и открытие Door; высокий relay выставляет тот же сигнал на 3.5 s. Обычный бег проходит под relay, поэтому original route не активирует восстановление автоматически. Android 16 при задержках между решениями выявил узкое окно посадки: launch floor продлён до x=1040, а платформа расширена влево до x=910 при сохранении прежнего правого края x=1230, дальнего края PIT x=1510, travel, period и recovery relay.

Bot checkpoints: основной timer активен; первый прыжок подтверждает playerOnMovingPlatform=true, второй доставляет игрока на дальний floor. Перед движением к relay явно подтверждены playerX≥1510, playerY≥779 и всё ещё открытая Door. Intended route проходит Door на первом таймере. Recovery route ждёт allDoorsOpen=false справа от PIT, прыжком получает allDoorsOpen=true, проходит Door и завершает уровень. Оба маршрута финально дают completed=true, deaths=0; каждый выполнен три раза подряд на Android 16. Дополнительный intended run с 96 ms задержки на каждое решение также завершён без смерти. Дальний край платформы намеренно не расширен, чтобы она не могла унести ожидающего игрока обратно над PIT.

Softlock/неопределённость: прежний blocker устранён: после истечения "clock" справа от PIT высокий relay гарантирует restart-free повторное открытие двери. Relay не помогает слева от PIT и не отменяет timed-platform crossing. Оба пути проверены без прямой мутации состояния, teleport, auto-complete или restart.

Уровень 9 — Two Good Reasons

Статус: доказан ботом, 3/3 последовательных прохождения с AND из двух тел. Ожидаемые смерти: 2 (targetDeaths=2). Источник: LevelCatalog.level9(); SPIKES=(520,850,130,30); PRESSURE=(510,842,160,38), signalId="weight"; ELECTRIC=(910,780,110,100), relayId="power"; дверь (1510,540,86,340) требует "weight" и "power"; goal=(2310,770,86,110).

Solution graph 9

Final Door использует AND из "weight" и "power"
→ первый доброволец погибает на SPIKES внутри зоны PRESSURE
→ закреплённое spike-тело удерживает signal "weight"
→ следующий доброволец пересекает spike-тело и погибает в ELECTRIC
→ закреплённое conductive body удерживает relay signal "power"
→ "weight" AND "power" одновременно active
→ Door открывается
→ третий доброволец respawn-ится
→ перепрыгивает обе опасности, проходит открытую Door
→ достигает goal и получает COMPLETE

Механика и сигналы: spike corpse → switchContact(PRESSURE) → "weight"; conductive corpse в relay → "power"; doorOpen проверяет оба requiredSignals.

Bot checkpoints: после первой смерти deaths/corpses=1/1, "weight"=true, Door ещё closed; после второй 2/2, "power"=true, allDoorsOpen=true; после respawn playerX>1596; финально completed=true, deaths=2. Snapshot нужно расширить поимёнными сигналами, чтобы доказать AND, а не только открытие двери.

Softlock/неопределённость: первая смерть стабильно удерживает "weight", но дверь остаётся закрытой; вторая активирует "power" и открывает AND-door. Цепочка подтверждена тремя запусками ровно с двумя телами.

Уровень 10 — The Last Procession

Статус: mastery-маршрут доказан production-input ботом: 3/3 последовательных прохождения и ограниченный стресс финального перехода 96 ms без ретраев. Ожидаемые и доказанные смерти: 3 (targetDeaths=3). Источник: LevelCatalog.level10(); SAW=(520,760,96,96), impulse (700,-240); PRESSURE=(860,860,160,20), signalId="lift"; FREEZER=(1110,776,100,104); ELECTRIC=(1510,780,110,100), relayId="power"; moving platform (1800,790,290,34), travel (0,-410), period 10.0, controlId="lift"; стартовый floor заканчивается на x=1940; PIT=(1940,880,200,200); дверь (2310,310,82,570) требует "power"; верхний уступ (2420,440,680); goal=(2880,330,86,110).

Solution graph 10

Goal расположен на верхнем уступе за PIT и закрытой высокой Door
→ первый доброволец входит в SAW
→ impulse (700,-240) доставляет тело на PRESSURE x=860..1020
→ тело оседает и фиксируется на PRESSURE, удерживает signal "lift" и запускает vertical moving platform
→ следующий доброволец погибает в FREEZER
→ frozen corpse становится стабильной ступенью для повторного прохода этой зоны
→ следующий доброволец погибает в ELECTRIC
→ conductive corpse удерживает relay signal "power" и открывает Door
→ четвёртый доброволец respawn-ится и пересекает сохранённые тела/опасности
→ садится на активную platform у x=1800..2090
→ поднимается над PIT и в верхней фазе прыгает вправо через открытую Door
→ приземляется на ledge x=2420..3100
→ достигает goal и получает COMPLETE с тремя смертями

Механика и сигналы: launched saw corpse при контакте с PRESSURE обнуляет скорость и закрепляется внутри плиты → "lift" → vertical platform; frozen corpse → твёрдая ступень; conductive corpse → "power" → Door open; platform и Door используют независимые постоянные сигналы от сохранённых тел.

Bot checkpoints: после SAW deaths=1, "lift"=true, platform y<790; после FREEZER deaths=2 и наличие frozen corpse; после ELECTRIC deaths=3, "power"=true, allDoorsOpen=true; перед посадкой первая moving platform должна вернуться к y≥780, затем snapshot подтверждает playerOnMovingPlatform=true; в верхней фазе playerY≤280; после прыжка playerX≥2420, playerY≤340; финально completed=true.

Softlock/неопределённость: исправлены два независимых blocker-состояния: saw-тело больше не соскальзывает с плиты после доставки, а перекрытие floor/lift увеличено до 140 px при сохранении 200 px PIT и обязательного вертикального подъёма. Период lift увеличен до 10.0 s, чтобы нижняя фаза была читаемой при задержанном вводе. Бот теперь явно приземляется на frozen corpse и прыгает с него; доставка saw-тела, три сохранённых тела, посадка, подъём и lift→ledge прыжок подтверждены тремя запусками и стресс-сценарием. Возможная альтернативная двухсмертная трасса не считается blocker, пока intended three-body route остаётся стабильным.

Уровень 11 — The Brass Breather

Статус: доказан production-input ботом, 3/3 изолированно и 3/3 в общей hazard-матрице. Ожидаемые и доказанные смерти: 1.

CRUSHER перекрывает единственный проход
→ первый доброволец входит в активный пресс и оставляет тело
→ следующий доброволец подходит к безопасной границе
→ наблюдает закрытие и следующий переход пресса в REST
→ прыгает через сохранённое тело и проходит пресс в полном окне отдыха
→ достигает goal с одной смертью

Контракт: cycleSeconds=4, activeSeconds=2.5; collision активен только в CRUSH-фазе. Bot snapshot наблюдает firstHazardActive, не использует sleeps, restart или прямую мутацию состояния.

Уровень 12 — Blue Funeral

Статус: доказан production-input ботом, 3/3 изолированно и 3/3 в общей hazard-матрице. Ожидаемые и доказанные смерти: 1.

FIRE перекрывает floor
→ первый доброволец демонстрирует смертельность синего огня
→ после respawn игрок подходит к рассчитанной точке x≈535
→ отдельным takeoff подтверждает airborne state
→ пересекает весь flame box до приземления
→ достигает goal, тело остаётся в уровне

Контракт: постоянный FIRE=(700,790,120,90) с отдельными visual/audio IDs. Маршрут запрещает вторую смерть на approach, takeoff и clear checkpoints.

Уровень 13 — Crossfire Clock

Статус: доказан production-input ботом, 3/3 изолированно и 3/3 в общей hazard-матрице. Ожидаемые и доказанные смерти: 1.

PROJECTILE каждые 3 s проходит справа налево
→ первый доброволец погибает и показывает линию снаряда
→ после respawn игрок останавливается у x≈600
→ ждёт наблюдаемое окно projectile x=850..930 и прыгает через первый проход
→ останавливается за линией и ждёт следующий цикл x=1350..1450
→ вторым прыжком проходит возвращённый снаряд
→ добегает за spawn снаряда и достигает goal без новых смертей

Контракт: runtime вычисляет текущий box из speedX=-400 и сбрасывает его на исходную позицию по cycleSeconds=3. Оба прыжка привязаны к snapshot координате, а не к wall-clock.

Уровень 14 — Steam Charge

Статус: доказан production-input ботом, 3/3 изолированно и 3/3 в общей hazard-матрице. Ожидаемые и доказанные смерти: 1; дверь обязана открыться.

Door требует signal "blast-gate" от удалённой PRESSURE
→ первый доброволец входит в активный EXPLOSION
→ impulse (550,-500) доставляет тело на PRESSURE x=980..1160
→ тело закрепляется на плите и открывает Door
→ следующий доброволец наблюдает новый BLAST и следующую REST-фазу
→ проходит inactive explosion
→ перепрыгивает сохранённое тело на плите
→ проходит открытую Door и достигает goal

Контракт: EXPLOSION использует data-driven цикл 4/2 s; inactive-фаза отличается визуально (REST) и не убивает. Device RED с impulseX=1400 доказал перелёт тела за плиту; минимальное authored значение 550 стабильно помещает тело в firstCorpseX=980, после чего allDoorsOpen=true.

Уровень 15 — Pressed Into Service

Статус: доказан production-input ботом, 3/3 последовательных прохождения. Ожидаемые и доказанные смерти: 1; сохранённое тело обязано иметь состояние CRUSHED, размер 140×24 и оставаться твёрдой опорой.

Верхний ledge начинается на высоте y=720 и недоступен прыжком с floor
→ первый доброволец входит в активный CRUSHER
→ пресс превращает тело в низкую закреплённую плиту 140×24
→ следующий доброволец наблюдает новый активный цикл и ждёт REST
→ проходит безопасный пресс и приземляется на crushed body
→ отдельным прыжком использует 24 px ступень для достижения ledge
→ проходит по верхней платформе к goal
→ COMPLETE ровно с одной смертью и одним crushed body

Контракт: CRUSHED композиционно сохраняется в CorpseManager, уменьшает коллайдер и не удаляет физическую опору. Save version 3 сохраняет флаг; v1/v2 мигрируют его в false. Snapshot отдельно публикует state, размеры и pressure capability, а Canvas добавляет текстовую метку CRUSHED помимо цвета.

Уровень 16 — Ashen Counterweight

Статус: доказан production-input ботом, 3/3 последовательных прохождения. Ожидаемые и доказанные смерти: 1; сохранённое тело обязано иметь состояние BURNED, оставаться твёрдым и не активировать PRESSURE.

Moving bridge над PIT управляется signal "burn-weight"
→ первый доброволец пересекает PRESSURE и погибает в FIRE над плитой
→ burned body остаётся на плите как твёрдый объект
→ burned body не даёт pressure mass: signal остаётся inactive
→ мост остаётся в нижней фазе у y≈840 вместо подъёма
→ следующий доброволец перепрыгивает FIRE и burned body
→ садится на неподвижный мост и пересекает PIT
→ достигает goal на правом floor
→ COMPLETE ровно с одной смертью и одним burned body

Контракт: BURNED сохраняет коллайдер, но activatesPressure=false; это проверяется одновременно состоянием тела, неактивным firstMovingPlatformPowered и нижней координатой моста. Save version 3 сохраняет флаг; Canvas добавляет текстовую метку BURNED, поэтому состояние не кодируется только цветом.

Уровень 17 — The Whole Weight

Статус: доказан production-input ботом, 3/3 последовательных прохождения. Ожидаемые и доказанные смерти: 0; дверь обязана удерживаться только физическими объектами после отпускания player input.

Door требует signal "weight-gate" с requiredMass=9
→ на PRESSURE уже стоят Box(1), Rock(2), Ball(1) и IceBlock(2): сумма 6
→ Counterweight(3) находится слева от плиты, поэтому Door закрыта
→ игрок подходит и толкает Counterweight вправо
→ при x≥920 Counterweight пересекает plate x=1000..1650
→ общий IWeightedObject resolver получает массу 6+3=9 и открывает Door
→ игрок отпускает input; объект продолжает удерживать сигнал без player mass
→ игрок двумя отдельными прыжками пересекает Counterweight и ряд объектов
→ проходит открытую Door и достигает goal
→ COMPLETE без смерти и без создания тел

Контракт: Player, CorpseManager.Body и PhysicalObjectState реализуют один IWeightedObject; plate агрегирует только геометрически пересекающуюся активную массу, не проверяя тип. Все пять authored типов имеют type/box/mass в JSON, детерминированный runtime, non-color type+weight label, SVG/TSV preview и save-v4 состояние. V1–v3 active sessions мигрируют с пустым runtime-object list.

Bot checkpoints: каталог публикует пять objects и Counterweight mass 3; до push allDoorsOpen=false; после push firstPhysicalObjectX≥920 и Door open; после release Door остаётся open; затем два отдельных jump edge и completed=true.

Уровень 18 — Threefold Proof

Статус: доказан production-input ботом, 3/3 последовательных прохождения. Ожидаемые и доказанные смерти: 0; обязательный challenge-route получает casualty, time и collectible stars.

LevelID="foundations.threefold-proof", WorldID="foundations"
→ игрок проходит безопасный teaching floor без смертей
→ у x≈650 начинает прыжок к cache=(850,650,58,58)
→ пересекает cache: collectibleFound=true, cache исчезает только для этой попытки
→ продолжает вправо и достигает goal x=2000..2086
→ COMPLETE с deaths=0 и time≤30 s
→ ChallengeResult выдаёт casualty/time/collectible = true, stars=3
→ ProgressStore сохраняет лучшие критерии по стабильному LevelID
→ три последовательных restart-free прохождения воспроизводят 3/3 stars

Контракт: collectible является опциональным world-space объектом и сохраняется в active session v5. Restart сбрасывает состояние текущей попытки; завершённый collectible challenge накапливается в progress v3 независимо от лучших casualty и time runs. Legacy levels без collectible получают третью звезду за core completion.

Bot checkpoints: deaths=0; после прыжка collectibleFound=true и collectibleVisible=false; затем completed=true; CompletionResult.stars=3, bestStars=3; новый ProgressStore после трёх запусков возвращает 3 звезды для foundations.threefold-proof.

Проверки, следующие из графов

  1. Сохранять полный integrated device-regression: intended route принятых уровней по три раза и отдельный recovery route уровня 8.
  2. Отдельно проверить предполагаемый sequence break уровня 2 и необязательность FREEZER на уровне 10.
  3. Добавить параметризованные проверки restart из ключевых промежуточных состояний.
  4. Повторить bot matrix на дополнительных frame rates и поддерживаемых версиях Android.
  5. Провести ручные сессии этапа 2 и скорректировать подсказки/допуски без ослабления механик.