Files
andrey 3061247ce5 Паттерны и кампания: 8 новых фигур, 3 showcase-уровня, факты в README
- PATTERNS: авианосец, длинная лодка, каноэ, MWSS, HWSS, Loafer, кролики, ружьё Симкина (22 → 30)
- CAMPAIGN_LEVELS: ручные «Флотилия»/«Погоня»/«Кролики» после «Издалека» (100 → 103)
- README: раздел «Интересные факты» и список ресурсов
- tests: счётчики и проверки новых фигур/уровней синхронизированы
2026-10-13 15:06:52 +03:00

23 KiB
Raw Permalink Blame History

Life — территориальная борьба

Браузерная hot-seat игра-переосмысление Conway's Game of Life: двое игроков по очереди расставляют свои живые клетки, а дальше доска живёт по правилам Конвея — и чей цвет захватит поле, тот и победил. Один HTML-файл, без зависимостей: открой в браузере и играй.

Интересные факты

Наша игра — вариант классического автомата: у Конвея клетки одного цвета, бесконечное поле и «игра для нуля игроков», а у нас — территориальная борьба двух цветов, конечное поле, бюджет клеток и наследование цвета большинством. Вот несколько фактов о самой классике.

  • Джон Хортон Конвей придумал игру в 1970 году как упрощение самовоспроизводящейся машины фон Неймана (1940-е). Публика сделала её знаменитой после колонки Мартина Гарднера в Scientific American (октябрь 1970).
  • Это игра для нуля игроков: вся эволюция полностью задаётся начальной расстановкой. Автомат — B3/S23, окрестность Мура (8 соседей), состояния одновременны (тик).
  • Конвей объявил приз $50 тому, кто найдёт пример неограниченного роста. В ноябре 1970 приз взяла команда MIT во главе с Биллом Госпером — так появилось ружьё Госпера (первое ружьё, 36 клеток, период 30).
  • Игра тьюринг-полна: в 2002 году Пол Чапмен построил в ней универсальную регистровую машину (268 096 клеток). Всё, что вычислимо алгоритмически, вычислимо и в Life.
  • Life омнипериодична: существуют осцилляторы любого периода. Последним, в июле 2023, был найден период 41.
  • Алгоритм HashLife (Госпер, 1984) хранит подпаттерны в хеш-таблице и перескакивает тысячи поколений — им посчитано 6-октиллионное поколение машины Тьюринга Ренделла менее чем за 30 секунд.
  • Garden of Eden — конфигурации без «родителя» — существуют по теореме Мура–Майхилла с самого рождения игры. «Проблема уникального отца» (1972) была решена лишь в 2022 (пример из 306 клеток).
  • Конвей подбирал правила так, чтобы не было простого доказательства неограниченного роста, но такие растущие конфигурации всё же существовали, а простые «семена» долго и непредсказуемо развивались.

Ресурсы

  • LifeWiki — главная энциклопедия игры: https://conwaylife.com/wiki (может требовать обхода Cloudflare; страницы доступны через https://web.archive.org).
  • Catagolue — перепись «естественно возникающих» паттернов, краудсорсинг-поиск: https://catagolue.hatsya.com.
  • Life Lexicon (Stephen Silver) — словарь терминов: https://conwaylife.com/ref/lexicon/lex.htm.
  • OEIS — числовые последовательности (стойкие фигуры A019473, плотные A055397 и др.): https://oeis.org.
  • MathWorld — обзор с правилами и ссылками: https://mathworld.wolfram.com/GameofLife.html.
  • Golly — эталонный симулятор с HashLife: https://sourceforge.net/projects/golly/.
  • ibiblio — скан оригинальной статьи Гарднера 1970 года и коллекция паттернов: https://www.ibiblio.org/lifepatterns/.
  • Rosetta Code — реализации Life на десятках языков: https://rosettacode.org/wiki/Conway%27s_Game_of_Life.

Как играть

Игра на одном экране, игроки ходят по очереди, передавая устройство друг другу. На стартовом экране — краткое описание игры, выбор темы и две равноправные кнопки режимов: «Кампания» и «Игра на двоих» (а над ними выделенная «Продолжить партию», если есть отложенная). Нажав «Игра на двоих», вы попадаете на экран с настройками поля (размер, «замкнутая карта», бюджет) и справкой «Как играть»; партия стартует по кнопке «Начать». Сначала первый игрок расставляет свои клетки, затем устройство переходит второму — он расставляет вслепую, не видя расстановку соперника. Если первый игрок хочет что-то поправить, на экране передачи есть кнопка «Вернуться к игроку 1». После этого включается симуляция: живые клетки выживают при 2–3 живых соседях, а в пустой клетке рождается новая ровно при 3 соседях — и цвет новорождённой наследуется от большинства из своих соседей-родителей.

Каждый игрок может ставить клетки только в своей половине поля (первый — в левой, второй — в правой), а неактивная половина затемняется, чтобы было видно зону. На всю партию у каждого игрока есть бюджет клеток — счётчик остатка виден в HUD. Бюджет тратится на каждую новую поставленную клетку, ластик возвращает потраченное, а симуляция бюджет не расходует.

Когда поле перестало меняться — симуляция сама встаёт на паузу (и в HUD появляется метка «поле стабильно»), после чего каждый игрок может дорисовать клетки (уже видя всё поле): на паузе есть отдельные кнопки «Дорисовать красным» и «Дорисовать зелёным» (в любом порядке) и «Старт симуляции». Дорисовка доступна только на «застывшем» поле — это либо неподвижная структура, либо короткий цикл (например, мигалка). Если поле продолжает меняться (глайдеры, рост, хаос), дорисовки нет — такую партию можно только завершить вручную. Партия заканчивается при вымирании — как только у игрока не осталось ни одной клетки его цвета на доске (бюджет его уже не спасает), — тупиком по бюджету (поле стабильно, а отстающему игроку нечем ходить: его бюджет исчерпан, и ни поставить, ни стереть он не может; при равном счёте — когда бюджет кончился у обоих) либо ручным завершением кнопкой «Завершить партию» (с подтверждением, чтобы не завершить случайно). Победитель — у кого на доске больше живых клеток своего цвета.

Правила: окрестность Мура (8 соседей), классический автомат B3/S23. По умолчанию границы жёсткие (без заворота краёв); на экране «Игра на двоих» можно включить опцию «Замкнутая карта (torus)» — тогда соседи за краем берутся с противоположной стороны.

Кампания

В меню есть кнопка «Кампания» — это режим-испытание с отдельным экраном выбора уровня (справка «Как играть» — в сворачиваемом блоке на том же экране). На уровне заранее расставлены стабильные фигуры врага (зелёные клетки); вы играете красными и должны уничтожить все клетки врага (добиться нуля зелёных). Враг сам не ходит — поле живёт обычной детерминированной симуляцией Конвея, поэтому врага уничтожают, подводя его фигуры под смерть/перерождение по правилам B3/S23.

  • Зона рисования на уровне — прямоугольник (может быть меньше поля или совпадать с ним); неактивная область затемняется, как и половины в обычной партии.
  • Бюджет клеток — свой на каждый уровень, виден в HUD; при нуле остатка метка краснеет.
  • Врага нельзя трогать напрямую: краска и штамп не перезаписывают зелёные клетки (и не тратят за них бюджет), ластик их не стирает и бюджет не возвращает.
  • Вымирание игрока — не проигрыш: даже если красных клеток не осталось, можно продолжать, пока есть бюджет.
  • Победа — на доске не осталось клеток врага. Поражение — бюджет исчерпан, а враг ещё жив (фиксируется, когда поле стабилизировалось и симуляция сама встала на паузу).
  • HUD показывает «Уровень N/T» и остаток бюджета; обычный счёт скрыт.
  • Прогресс (сколько уровней открыто) сохраняется, победа открывает следующий. Всего 103 уровня: ручные («Разминка» — блок, «Каравай», «Рой» — много фигур, «Издалека» — враг вне зоны игрока, а сразу за ним showcase-уровни «Флотилия»/«Погоня»/«Кролики» с новыми фигурами), остальные 96 расставлены генератором tools/gen-campaign-levels.mjs (детерминированно, фиксированный seed) и вшиты в index.html статически. Размер поля у сгенерированных уровней постепенно растёт до 300×300; у ручных вставок (в т.ч. «Издалека» и showcase) размер свой. Зоны рисования разнообразны (половина, центр, углы, узкие полосы, произвольный прямоугольник); зона на всё поле есть только у ручных «Разминки» и «Роя» — у сгенерированных её нет. Список уровней прокручивается. Решаемость уровней намеренно не проверяется: среди них есть заведомо почти непроходимые (например с ружьём Госпера) — это задумка.
  • Когда поле уровня стабилизировалось, игра сама открывает фазу дорисовки — жать «Дорисовать» не нужно: дорисуйте свои клетки и нажмите «Готов» — симуляция запустится сразу (цикл «нарисовал → побежало»). Кнопка «Заново» в панели действий перезапускает уровень в любой момент (с подтверждением).
  • Уровень можно отложить в меню (кнопка «В меню»/⚙️ посреди уровня) и вернуться к нему кнопкой «Продолжить партию»; из финала — «Следующий уровень», «К уровням» или «Заново».
  • Настройки уровня (размер поля, бюджет) действуют только внутри уровня и не меняют ваши настройки из меню: обычная партия после кампании стартует с прежним размером и бюджетом.

Управление

  • Инструменты: карандаш 1×1, кисть 3×3, ластик 1×1, ластик 4×4. Правая кнопка мыши — ластик: удерживайте её, чтобы стирать, не переключая инструмент (если активен ластик, ПКМ сохраняет его размер, иначе стирает 1×1).
  • Готовые паттерны (штампы): дропдаун «Паттерн» в тулбаре, сгруппированный по категориям — Стойкие (блок, улей, ванна, лодка, кораблик, каравай, пожиратель, пруд, авианосец, длинная лодка, каноэ), Осцилляторы (мигалка, жаба, маяк, часы, пульсар, пентадекатлон), Корабли (глайдер, LWSS, MWSS, HWSS, Loafer), Долгожители (R-пентамино, жёлудь, Diehard, громовая птица, кролики) и Ружья (ружьё Госпера, ружьё Симкина). Выберите фигуру и кликните: она встанет целиком, левый верхний угол — в точке клика. Клетки вне вашей половины не ставятся (в превью они подсвечены серым), бюджет тратится только за поставленные. Одно нажатие — одна постановка (перетаскивание фигуру не повторяет); ПКМ по-прежнему стирает. Поворот фигуры на 90° — кнопкой «↻» в тулбаре (видна при выбранном паттерне) или колесом мыши над доской. Выбор паттерна и его поворот не сохраняются между сессиями.
  • Режим «постановка по отпусканию» (для сенсорных экранов): кнопка «👆 тап» в тулбаре. Когда режим включён, нажатие/касание только подсвечивает будущее место, а клетка (или фигура) ставится в момент отпускания — палец не закрывает точку постановки, а перетаскивание не рисует линию. Ластик и ПКМ работают так же — по отпусканию. Режим не сохраняется между сессиями и не сбрасывается при новой партии.
  • Поле: 40 / 60 / 80 / 100 / 120 / 150 / 200 / 250 / 300 клеток в стороне (по умолчанию 60×60) плюс прямоугольные 60×100 и 100×60; размер выбирается дропдауном на экране «Игра на двоих»; правила партии открываются там же по кнопке «Как играть».
  • Бюджет клеток на партию (по умолчанию 100): комбобокс на экране «Игра на двоих» — можно выбрать пресет из списка (100/250/500) или ввести любое своё число.
  • «Замкнутая карта (torus)» — опция на экране «Игра на двоих» (по умолчанию выключена, границы жёсткие).
  • Тема оформления — селект в стартовом меню: «Тёмная» (по умолчанию) или «Светлая». Выбор сохраняется и применяется после перезагрузки.
  • Зоны рисования: первый игрок ставит клетки только в левой половине, второй — только в правой.
  • Скорость симуляции задаётся константой STEPS_PER_SEC (~8 шагов/сек) в коде index.html. Во время симуляции в панели действий есть ряд из четырёх кнопок 1× / 2× / 4× / 8× — клик выбирает множитель скорости (выбранная кнопка подсвечена); множитель не сохраняется и сбрасывается при новой партии.
  • Клавиатура: пробел ставит и снимает паузу во время симуляции (как у медиаплеера) — то же, что кнопки «Пауза»/«Старт симуляции». В меню, фазах расстановки/дорисовки, при передаче устройства, в финале и при открытом диалоге подтверждения пробел ничего не делает; в поле ввода (бюджет) работает как обычный пробел.
  • «Сброс» сбрасывает только текущий ход — возвращает поле и бюджет к началу фазы рисования.

Сохранение и резюм партии

Игра сама сохраняет прогресс в localStorage браузера (ключ life-save-v1) — без сервера и аккаунтов. Сохраняются:

  • настройки: размер поля, активный инструмент, скорость симуляции, опция «Замкнутая карта», тема оформления, бюджет клеток;
  • текущая партия: состояние (чей ход / симуляция / пауза / передача устройства), поле целиком и счёт;
  • кампания: прогресс (сколько уровней открыто) и незавершённый уровень кампании (с полем врага и зоной рисования) — он резюмится так же, как обычная партия.

Поэтому после перезагрузки страницы незавершённая партия продолжается с того же места (включая фазу расстановки и идущую симуляцию). Если партия завершена или сейва нет — игра открывается в меню. Если сохранённые данные битые или устаревшего формата, игра просто стартует в меню, не падая. Кнопка «В меню» (и ⚙️) не теряет партию: она откладывает её, и в меню появляется кнопка «Продолжить партию» для возврата. Кнопка «Игра на двоих» (а также «Реванш») при наличии незавершённой партии сначала спрашивает подтверждение, чтобы случайно её не потерять.

⚠️ localStorage привязан к origin, поэтому сейв/резюм не переносятся между file:// и http://localhost:8000 — для проверки резюма используйте один и тот же способ открытия.

Запуск

Просто открой index.html в браузере (десктоп или телефон) — игра работает с file://. Для локальной разработки:

python3 -m http.server 8000
# → http://localhost:8000

Тесты

Сначала проверка синтаксиса JS, встроенного в index.html:

node tools/check.mjs

Затем headless-суита на puppeteer-core в Chromium (нужен установленный Chromium; путь при необходимости правится переменной CHROMIUM):

cd tests
npm install
npm test

Ждать все PASS и exit 0. Суита также включает проверки персистентности/резюма, миграции сейва, resize и проводки DOM-кнопок.

Отдельно — паритет с прототипом (harness в tools/old-ref/, опционально): сборка g++ и дифтест, подробности в tools/old-ref/README.md.

Структура

index.html       # вся игра: HTML + CSS + один <script>
tests/           # headless-тесты (puppeteer-core): test.js, parity-fixture.json, package.json
tools/check.mjs  # проверка синтаксиса JS из index.html
tools/gen-campaign-levels.mjs # генератор 96 уровней кампании (seeded PRNG, без Math.random)
tools/old-ref/   # harness паритета с прототипом (C++ + генераторы; см. README там)
AGENTS.md        # правила разработки и тестирования
README.md        # этот файл
old/             # референс старого C++/Qt4 прототипа (не часть продукта, не трогать)