PlayPendium
Contraption · Харч для думок

Рівень, який сам доводить, що його можна розв’язати

Гра ніколи не створює головоломку вручну. Вона вирощує її з одного-єдиного числа, а потім розігрує цю головоломку сама проти себе, щоб переконатися, що та не є ані тривіальною, ані неможливою, перш ніж ви взагалі її побачите.

Сьогоднішня дата 1 число, перетворене хешем на сід
стає
Щоденна головоломка 1 ідентичне поле для всіх

Написано й відредаговано англійською. Цю українську версію створено машинним перекладом; там, де важлива точність, авторитетним є англійський оригінал. Читати оригінал англійською →

01 · Усе з одного числа

Цілий світ, згорнутий у сід

Рівень Contraption ніде не зберігається. Немає файлу, в якому записано, де стоять ворота чи як розташовані виступи. Натомість увесь рівень — стартова позиція м’яча, положення воріт, кількість і розміщення нерухомих стін, набір деталей, які вам видають, — обчислюється з одного початкового числа, яке називають сідом (seed). Дайте генератору той самий сід — і ви отримаєте, байт у байт, ту саму головоломку. 1

Це можливо тому, що єдине джерело «випадковості» в генератора — невеликий детермінований генератор псевдовипадкових чисел. Contraption використовує mulberry32, компактний 32-бітний генератор, автор якого — Томмі Еттінгер; його можна впізнати за характерною константою 0x6d2b79f5, яка додається до стану при кожному витягуванні числа. 2 Він швидкий, вміщується в кілька рядків і, що найважливіше, зовсім не випадковий: це фіксована математична послідовність, яка лише виглядає перемішаною. Дайте йому стартове значення — і він вічно видаватиме один і той самий потік чисел. Потім генератор читає цей потік, щоб вирішити, де що розмістити.

02 · Щоденна головоломка

Як дата стає спільним викликом

Режим «Щодня» спирається на цю детермінованість, щоб зробити дещо соціальне. Його сід не випадковий — він виготовляється з календаря. Гра бере сьогоднішню дату за всесвітнім часом, записує її в короткий рядок на кшталт «contraption:2026-7-28» і проганяє цей текст через хеш-функцію, щоб уварити його до одного 32-бітного числа. 1

Хеш-функція — це FNV-1a, добре відомий некриптографічний змішувач: він починає з фіксованого зміщення, десяткового 2166136261, тобто 0x811c9dc5, і для кожного символу вплітає літеру через виключне АБО, а потім множить на просте число FNV 16777619. 3 У результаті виходить число, стабільне для певного дня і геть інше наступного, тож зміна одного символу в даті повністю розкидає сід. Оскільки календар для всіх однаковий, однаковим є і сід, а отже, й головоломка. Двоє незнайомців на протилежних кінцях світу відкривають «Щодня» й бачать перед собою ідентичне поле — саме це й робить порівняння результатів осмисленим.

Щоденний виклик чесний не тому, що сервер надсилає всім один і той самий рівень, а тому, що кожна копія гри незалежно переобчислює той самий рівень із тієї самої дати.

03 · Генератор ставить під сумнів сам себе

Відкидання головоломки, яка розв’язується сама

Випадкова геометрія — це просто; хороша випадкова геометрія — ні. Генератор, який просто розкидає ворота й кілька виступів, іноді видасть рівень, де м’яч, скинутий згори, сам собою падає прямісінько у ворота. Це не головоломка, це кат-сцена. Тож перш ніж Contraption прийме світ-кандидат, він проводить тихий тест, який у коді називається preSolved: симулює рівень без жодної розміщеної деталі й перевіряє, чи досягає голий м’яч воріт лише під дією гравітації. Якщо так, рівень відкидається, і генератор кидає знову. 1

Це тонка інверсія звичного погляду на фізичний рушій. Та сама функція simulate(), яка розігрує вашу машину, повертається всередину, на етапі генерації, щоб проревізувати складність самого рівня. Рушій одночасно і суддя вашого розв’язку, і контролер якості головоломки.

04 · Крихітний вбудований розв’язувач

«Чи можна це зробити однією деталлю?»

Відкинути надто легкий рівень — лише половина справи. Інша небезпека — рівень неможливий, де ворота заховані там, куди не дістане жодне розташування деталей. Contraption страхується від цього невеликим розв’язувачем грубої сили на ім’я plausiblySolvable. Він не мудрує. Він просто пробує. 1

А саме: він проводить одну рампу по сітці позицій над полем і в кожній точці пробує її з чотирма різними нахилами. Для кожного з цих пробних розміщень він запускає повну симуляцію й запитує: чи довела ця одна рампа м’яч додому? Щойно будь-яке розміщення спрацьовує, рівень оголошується розв’язуваним і відправляється вам. Якщо після повного проходу не спрацювало жодне, генератор воліє відкинути рівень і спробувати новий сід.

Пошук розв’язувача з однією деталлю: груба сітка, по чотири нахили в кожній точці
Параметр проходуДіапазонЩо означає
Рампа X15 → 85, крок 14стовпці впоперек поля
Рампа Y30 → 120, крок 18рядки вниз по полю
Випробувані кути4±0.45 і ±0.8 радіана
Тест на кожне розміщення1 повна симуляціячи досягає м’яч воріт?

Варто чесно сказати, що саме це доводить, — і код теж чесний щодо цього: коментар називає це «дешевою перевіркою на правдоподібність … не вичерпною». Рівень, який пройшов, напевно має принаймні один грубий розв’язок з однією рампою. Рівень, який не пройшов, усе ще може бути розв’язуваним за допомогою вентилятора, механізму чи хитрішої рампи, якої сітка ніколи не пробувала, тому генератор не вважає провал доказом неможливості. Він зберігає перший знайдений нетривіальний світ як запасний варіант, і якщо сорок спроб минають без чистого розв’язку однією деталлю, він відправляє цей запасний варіант замість того, щоб зациклюватися назавжди. Результат — прагматична гарантія: ніколи не буде дармової перемоги, майже завжди є справжній шлях усередину, і ніколи не буде нескінченного очікування «ідеального» рівня. 1

05 · Глибока ідея

Генерувати й перевіряти — найскромніший вид інтелекту

Відступіть на крок — і генератор рівнів Contraption виявиться чистим прикладом дуже старого й дуже загального шаблону розв’язання задач: генерувати й перевіряти. Запропонуйте кандидата навмання; перевірте його на відповідність вимогам; залиште, якщо пройшов; відкиньте й запропонуйте нового, якщо ні. Це цикл, що стоїть за процедурним контентом у незліченних іграх, за значною частиною еволюційних обчислень і, якщо примружитися, за самим природним добором: мутація пропонує, середовище перевіряє, ті, хто вижив, залишаються. 4

Що робить версію Contraption елегантною, так це те, що тест — не дешевий сурогат реальної гри, він і є реальна гра. Генератор не оцінює, чи чесний рівень, рахуючи виступи чи вимірюючи відстані. Він буквально грає в рівень, двічі: один раз порожнім, щоб переконатися, що це не подарунок, і один раз із пробною рампою, щоб переконатися, що шлях існує. Та сама детермінована фізика, яка судитиме ваш розв’язок, — це фізика, яка перевірила головоломку. Немає окремого «валідатора рівнів», який міг би розійтися зі справжніми правилами, бо набір правил лише один, і він використовується для всього.

А оскільки все це детерміноване, ревізія вільна від удачі в обидва боки. Щоденний сід не може змовитися, щоб дати одному гравцеві легше поле, ніж іншому, і не може нікому дати нечесне поле, бо перш ніж рівень стає викликом, він уже пережив те, що в нього зіграла сама гра — проти себе.

Sources & notes
  1. Seed-to-level generation, the preSolved rejection test, the plausiblySolvable one-ramp solver (grid ranges, four angles, up to 40 attempts, fallback world), and the daily-seed date string are all read directly from Contraption's own game engine and random-number code. Grounded in the game's code, not invented.
  2. mulberry32 is a compact 32-bit pseudo-random generator by Tommy Ettinger; it advances its state with the constant 0x6d2b79f5 and has a period of 2³². Author's reference gist (with his own later caveats on its equidistribution). gist.github.com/tommyettinger/46a874533244883189143505d203312c
  3. "Fowler–Noll–Vo hash function." Wikipedia, the 32-bit FNV offset basis is 2166136261 (0x811c9dc5) and the FNV prime is 16777619 (0x01000193); FNV-1a XORs each byte into the hash first and then multiplies by the prime. en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function
  4. On generate-and-test / "generation followed by evaluation" as a general search and problem-solving strategy, and its kinship with procedural generation and evolutionary methods. See "Procedural generation," Wikipedia. en.wikipedia.org/wiki/Procedural_generation
  5. Further reading on Procedural generation, [2410.15644] Procedural Content Generation in Games: A Survey with Insights on Emerging LLM Integration. arxiv.org.
  6. Further reading on Procedural generation, Procedural Content Generation in Games: A Survey with Insights on Emerging LLM Integration. doi.org.
  7. Further reading on Procedural generation, "Procedural City Generation with Combined Architectures for Real-time V" by Gr. open.clemson.edu.
Was this worth reading?
← Back to Contraption
PlayPendium · About · Contact · Privacy · Terms · Cookies · Accessibility · Copyright · Browse all games · Inspirations · © 2026