- после авто-паузы стабильного поля уровень сразу открывает EDIT_P1 (без клика «Дорисовать»)
- кнопка «Заново» в панели действий перезапускает уровень через диалог подтверждения
- Описание на стартовом экране сведено к первому предложению
- «Кампания» и «Игра на двоих» — в одинаковом нейтральном стиле
- «Продолжить партию» выделена акцентной кнопкой
- Меню стало сплэшем: краткое описание, тема, кнопки «Продолжить»/«Кампания»/«Игра на двоих»
- Новое состояние TWO_SETUP (экран #setup): своя справка и настройки поля (размер/torus/бюджет)
- У кампании своя сворачиваемая справка #aboutCampaign, стиль справок вынесен в .help
- Тесты адаптированы под новый поток + раздел 37n (сплэш/двухэкранность/reload)
Вместо прежнего обмена id4 и id10 — вставка: «Издалека» (id4) стоит на
10-м месте, а id5..id10 сдвинуты на позицию вверх (индексы 3..8).
Порядок: 1,2,3,5,6,7,8,9,10,4,11..100.
- Меняется только порядок записей: данные уровней (имя, размер, зона,
бюджет, клетки) не тронуты, «Издалека» как была.
- Единственный «блип» размеров теперь на индексе 9; тест монотонности
усилен (исключается только он), добавлен кейс «порядок вставки».
- 464/464, паритет step 273/273 сохранён.
- Добавлены стойкие (ванна, лодка, кораблик, каравай, пожиратель, пруд),
осцилляторы (маяк, часы, пентадекатлон), долгожители (жёлудь, Diehard,
громовая птица); у записей появилось поле group.
- #optPattern сгруппирован в optgroup по PATTERN_GROUPS
(Стойкие/Осцилляторы/Корабли/Долгожители/Ружья).
- Тесты: patternCells новых фигур, поведение (периоды/рост/гибель),
группировка и наличие всех id; обновлены доки и комментарии.
У 96 сгенерированных уровней полная зона заменена на «центр»: теперь
зона рисования никогда не покрывает всю доску, остаётся 7 типов
(половина, центр, углы, полосы, прямоугольник). Полная зона — только
у ручных «Разминка» и «Рой».
- Правка точечная: изменены зоны 12 уровней, клетки врага и порядок
уровней не тронуты («Издалека» без изменений).
- Генератор: kind «всё поле» перенаправлен в центр без сдвига PRNG;
--check теперь запрещает полную зону у сгенерированных.
- Тесты: вместо «зоны разнообразны» — три проверки (нет полной зоны у
сгенерированных; полная только у ручных; все 7 типов присутствуют).
- 424/424, паритет step 273/273 сохранён.
Расширили кампанию с 14 до 100 уровней: 4 ручных + 96 сгенерированных
(id 5..100). Размер карты растёт с ~60 до 300×300, бюджет и число фигур —
вместе с размером.
- Данные уровней переведены с ASCII-сеток enemy на компактный формат
cells: [[x,y],...] (иначе 96 уровней до 300×300 раздували память и
старт); enemyFromCells удалён, buildCampaignField строит поле из cells.
- Зоны рисования разнообразны: всё поле, половина, углы, центр, узкие
полосы, произвольные прямоугольники; у части уровней враг вне зоны.
- Уровень «Издалека» перенесён на 10-е место (данные без изменений).
- Список из 100 уровней — прокручиваемый; syncLevelList не работает вне
экрана выбора.
- tools/gen-campaign-levels.mjs обновлён под 96 уровней и формат cells
(seeded PRNG, без Math.random, --check).
- Тесты обновлены под 100 уровней (422/422), паритет 273/273 сохранён.
- #speedRow с #speed1..#speed8, активная подсвечена; setSpeed(m) вместо cycleSpeed
- speedMult теперь 1/2/4/8 (транзиентный); документация и тесты обновлены
Было 3 почти одинаковых уровня. Теперь первый — «Разминка» (блок),
второй — «Каравай», плюс «Рой» (много фигур) и «Издалека» (враг вне
зоны рисования игрока), и 10 сгенерированных уровней.
- Фигуры врага: блок, улей, мигалка, жаба, каравай, пульсар, ружьё
Госпера; есть уровни с врагом вне зоны игрока.
- tools/gen-campaign-levels.mjs — детерминированный генератор (seeded
PRNG, без Math.random); вывод вшит в CAMPAIGN_LEVELS статически, в
рантайме ничего не генерируется.
- Решаемость намеренно не гарантируется: уровни с ружьём почти
непроходимы — это задумка, а не дефект.
- Тесты обновлены под 14 уровней (416/416): инварианты вместо жёстких
значений, проверка набора фигур, врага вне зоны, детерминизма
генератора и отсутствия дрейфа между генератором и вшитым блоком.
- Ядро step не тронуто; паритет 273/273 сохранён.
Новый режим (кнопка «Кампания» → экран уровней): на поле заранее
расставлены стабильные фигуры врага (цвет 2), игрок (цвет 1) должен
полностью убрать цвет врага только перекраской в симуляции. У каждого
уровня своя прямоугольная зона рисования и свой бюджет клеток.
- FSM переиспользует PLACE_P1/RUNNING/PAUSED/EDIT_P1/GAME_OVER, добавлено
только LEVEL_SELECT; режим различается флагами campaign/levelIndex.
- Зона игрока — прямоугольник zoneRect, новый предикат inZoneAt;
inZone/zoneSplit не менялись (контракт тестов).
- Клетки врага нельзя стирать/перекрашивать (в paintTool пропускаются
во всех ветках без траты бюджета); вымирание игрока не проигрыш.
- Победа = 0 клеток врага (reason='win'), поражение = бюджет исчерпан и
враг жив на авто-паузе (reason='defeat').
- Прогресс с разблокировкой уровней в localStorage (аддитивные поля
сейва, SAVE_VERSION без изменений); выход в меню откладывает уровень
в suspended.
- Настройки меню (menuFieldW/H/Wrap/Budget) отделены от активной игры —
размер/бюджет уровня не утекают в обычную партию.
- Тесты: +76 кейсов кампании (408/408), паритет step сохранён 273/273.
Co-authored-by: opencode <noreply@opencode.ai>
- глобалы stampRot (0..3) и wheelAccum, хелперы rotate90/stampCells;
- обработчик wheel на canvas ({passive:false}): только в фазах рисования при
активном штампе, deltaY копится до порога WHEEL_ROT_STEP (мышь — один поворот
на щелчок, тачпад — контролируемо), deltaMode нормализуется к пикселям;
- paintTool и ghost-превью используют stampCells (поворот влияет и на
постановку, и на превью), stampRot/wheelAccum сбрасываются при смене
паттерна/инструмента;
- тесты (325/325): stampCells 0..3 и возврат формы, wheel вниз/вверх/круг,
инертность без штампа и вне рисования, накопление мелких дельт, постановка
повёрнутой фигуры, сброс поворота; доки.
- таблица PATTERNS (ASCII-формы) + patternCells/findPattern, глобал stamp
(транзиентный, как speedMult — в сейв не пишется);
- ветка stamp в paintTool: якорь левый верхний угол, зона/бюджет как у краски,
кламп по доске, обрезка по половине; одно нажатие = одна постановка;
- дропдаун #optPattern в тулбаре (подсветка .active, disabled вне рисования,
selectTool сбрасывает штамп); ghost-превью с показом вылета за зону;
- тесты (312/312): разбор форм, постановка, зона/бюджет/кламп/Сброс, корректность
фигур на симуляции, проводка DOM/ввода, транзиентность; доки.
checkEnd() больше не смотрит на бюджет: после каждого шага симуляции
исчезнувший цвет проигрывает немедленно (бюджет финал не отодвигает).
Обновлены тесты (фикстуры с обоими цветами, новый кейс финала при
непустом бюджете) и документация.
Симуляция сама встаёт на паузу, когда поле перестало меняться (фиксированная
точка или короткий цикл: хеш поколения повторяется в окне STABLE_WINDOW=32).
Признак fieldStable открывает дорисовку (EDIT_P1/EDIT_P2) только на «застывшем»
поле; на живом (глайдеры/рост/хаос) кнопки скрыты, партию завершают вручную.
fieldStable сохраняется в сейве (stable) и в отложенной партии (suspended).
- CSS-переменные структурных цветов UI + :root[data-theme=light]
- CANVAS_THEME (dark/light) и applyTheme/setTheme; draw читает цвета зон из COLORS
- селект #optTheme в меню; syncDom отражает тему
- поле theme аддитивно в сейв v2 (старые сейвы → dark)
- тесты темы + стабильные глобалы; AGENTS/README актуализированы
- кнопки «В меню»/«Завершить» перекрашены; 5% подсветка территорий в RUNNING/PAUSED
- Первичная передача: после расстановки P2 новое состояние HANDOFF_P2_START
(кнопки «Начать симуляцию» и «Вернуться к игроку 1»). handoffBack() ведёт
P2→P1 с сохранением расстановки соперника (правая половина снова скрыта);
«Готов» из PLACE_P2 больше не стартует симуляцию сразу.
- Снимок начала хода PLACE_* чистится по зоне игрока (enterPlace/clearZone), чтобы
«Сброс»/ластик откатывали только расстановку текущего игрока и корректно
возвращали бюджет, не трогая чужую половину.
- «Завершить партию» (#btnEnd/#btnEndPause) теперь открывает #confirm
(confirmAction='end'), ставит симуляцию на паузу; «Отмена» возвращает RUNNING,
подтверждение → GAME_OVER/manual. Единый confirmAction='new'|'end' поверх
#btnConfirmOk/#btnConfirmCancel: партию нельзя потерять одним кликом.
- Финальный reason='manual' выставляется через requestEndGame→confirmProceed.
- Тесты 253/253, паритет step==clean 273/273 (+torus 273/273), check: OK.
- checkEnd(): вымирание объявляется только когда исчезнувший цвет уже не вернуть
(у игрока без клеток остаток бюджета = 0); иначе партия продолжается до ручного финала.
- Кнопки «В меню»/⚙️ откладывают партию в suspended; в меню — «Продолжить партию»,
«Играть»/«Реванш» при suspended спрашивают подтверждение (#confirm). suspended
переживает reload (аддитивное поле сейва v2, без слома миграции).
- Дорисовка: отдельные «Дорисовать красным»/«Дорисовать зелёным» и «Старт симуляции»
в PAUSED; убрана форс-цепочка EDIT_P1→EDIT_P2; состояния HANDOFF_E1_E2/HANDOFF_E2_RUN
удалены; commitTurn() из EDIT_* → PAUSED.
- Первичная передача: кнопка «Вернуться к игроку 1» (handoffBack → PLACE_P1) с
сохранением снимка начала хода P1.
- Тесты 234/234, паритет step==clean 273/273 (+torus 273/273), check: OK.
- AGENTS.md как конфиг проекта: стек (один index.html, vanilla JS, Canvas 2D + DOM),
структура, правила игры (B3/S23, большинство из 3), FSM и правила скрытия,
инструменты/настройки, команды проверки, тестовая инфраструктура и покрытие,
подводные камни, 'где крутить', стабильные глобалы.
- README.md: описание игры, управление, запуск, тесты.
- .gitignore/.ignore: deepwork-состояние git-local + доступ для поиска.
- Ревью-гейт 1 (Oracle): PASS; закрыты M1/M2 и мелкие замечания.