Permainan ini tidak pernah merancang teka-teki dengan tangan. Ia menumbuhkan satu teka-teki dari satu angka saja, lalu memainkan teka-teki itu melawan dirinya sendiri untuk memastikan teka-teki tersebut tidak terlalu sepele dan tidak pula mustahil, sebelum Anda sempat melihatnya.
Ditulis dan disunting dalam bahasa Inggris. Versi bahasa Indonesia ini dihasilkan oleh terjemahan mesin; jika ketepatan menjadi penting, naskah asli berbahasa Inggris adalah yang berlaku. Baca naskah asli dalam bahasa Inggris →
Sebuah level Contraption tidak disimpan di mana pun. Tidak ada berkas yang mencantumkan di mana gawang berada atau bagaimana tepian-tepian disusun. Sebaliknya, seluruh level, yaitu titik awal bola, posisi gawang, jumlah dan penempatan dinding tetap, serta persediaan bagian yang diserahkan kepada Anda, dihitung dari satu angka awal yang disebut seed. Berikan seed yang sama kepada generator dan Anda akan mendapatkan teka-teki yang sama persis, byte demi byte. 1
Hal itu mungkin karena satu-satunya sumber "keacakan" generator adalah sebuah pembangkit bilangan pseudo-acak deterministik yang kecil. Yang digunakan Contraption adalah mulberry32, pembangkit 32-bit ringkas karya Tommy Ettinger; Anda dapat mengenalinya dari konstanta khasnya, 0x6d2b79f5, yang ditambahkan ke state pada setiap pengambilan. 2 Pembangkit ini cepat, muat dalam beberapa baris saja, dan, yang terpenting, sama sekali tidak acak: ia adalah deret matematis tetap yang hanya tampak teracak. Beri ia titik awal dan ia akan menghasilkan aliran angka yang sama selamanya. Generator kemudian membaca aliran itu untuk memutuskan di mana segala sesuatu ditempatkan.
Mode Harian memanfaatkan determinisme ini untuk melakukan sesuatu yang bersifat sosial. Seed-nya tidak acak, melainkan dibuat dari kalender. Permainan mengambil tanggal hari ini dalam waktu universal, menuliskannya ke dalam string pendek seperti "contraption:2026-7-28", dan menjalankan teks itu melalui sebuah fungsi hash untuk meringkasnya menjadi satu bilangan 32-bit. 1
Fungsi hash-nya adalah FNV-1a, pengacak non-kriptografis yang terkenal: ia bermula dari sebuah offset tetap, yaitu desimal 2166136261 atau 0x811c9dc5, dan untuk setiap karakter ia melipat huruf tersebut ke dalam dengan operasi exclusive-or lalu mengalikannya dengan bilangan prima FNV 16777619. 3 Hasilnya adalah sebuah angka yang stabil untuk hari tertentu dan sangat berbeda dari satu hari ke hari berikutnya, sehingga perubahan satu karakter saja pada tanggal akan mengacak seed sepenuhnya. Karena kalender sama bagi semua orang, seed-nya pun sama, dan begitu pula teka-tekinya. Dua orang asing di sisi dunia yang berlawanan membuka mode Harian dan menghadapi lapangan yang identik, dan justru itulah yang membuat perbandingan skor menjadi bermakna.
Tantangan harian itu adil bukan karena sebuah server mengirimkan level yang sama kepada semua orang, melainkan karena salinan milik setiap orang secara mandiri menghitung ulang level yang sama dari tanggal yang sama.
Geometri acak itu mudah; geometri acak yang bagus tidaklah mudah. Generator yang sekadar menebar sebuah gawang dan beberapa tepian kadang-kadang akan menghasilkan level di mana bola, yang dijatuhkan dari atas, langsung jatuh ke gawang dengan sendirinya. Itu bukan teka-teki, itu adegan sinematik. Maka sebelum Contraption menerima sebuah dunia kandidat, ia menjalankan uji diam-diam yang dalam kode disebut preSolved: ia mensimulasikan level tanpa satu bagian pun yang ditempatkan dan memeriksa apakah bola polos mencapai gawang hanya dengan gravitasi. Jika ya, level itu dibuang dan generator mengocok ulang. 1
Ini adalah pembalikan halus dari cara Anda biasanya memandang sebuah mesin fisika. Fungsi simulate() yang sama, yang memainkan mesin buatan Anda, diarahkan ke dalam, pada saat pembangkitan, untuk mengaudit tingkat kesulitan level itu sendiri. Mesin fisika ini sekaligus menjadi wasit bagi solusi Anda dan pemeriksa mutu bagi teka-tekinya.
Menolak level yang terlalu mudah baru separuh pekerjaan. Bahaya lainnya adalah level yang mustahil, yaitu gawang yang terselip di suatu tempat yang tidak dapat dijangkau oleh susunan bagian mana pun. Contraption berjaga terhadap hal ini dengan sebuah pemecah brute-force kecil bernama plausiblySolvable. Ia tidak berpikir dengan cerdik. Ia sekadar mencoba. 1
Secara khusus, ia menyapukan satu jalur landai melintasi kisi posisi di atas lapangan dan, di setiap titik, mencobanya dengan empat kemiringan berbeda. Untuk setiap penempatan percobaan itu ia menjalankan simulasi penuh dan bertanya: apakah satu jalur landai itu berhasil mengantarkan bola pulang? Begitu ada satu penempatan yang berhasil, level itu dinyatakan dapat dipecahkan dan dikirimkan kepada Anda. Jika tidak ada satu pun yang berhasil setelah seluruh sapuan selesai, generator memilih untuk membuang level itu dan mencoba seed yang baru.
| Parameter sapuan | Rentang | Arti |
|---|---|---|
| Landai X | 15 → 85, langkah 14 | kolom melintasi lapangan |
| Landai Y | 30 → 120, langkah 18 | baris menurun di lapangan |
| Sudut yang dicoba | 4 | ±0.45 dan ±0.8 radian |
| Uji per penempatan | 1 simulasi penuh | apakah bola mencapai gawang? |
Perlu dikatakan dengan jujur apa yang dibuktikan oleh hal ini, karena kodenya pun jujur tentang itu: komentarnya menyebutnya sebagai "pemeriksaan kelayakan yang murah … tidak menyeluruh." Level yang lolos pasti memiliki setidaknya satu solusi kasar dengan satu jalur landai. Level yang gagal mungkin saja masih dapat dipecahkan dengan kipas, roda gigi, atau jalur landai yang lebih cerdik yang tidak pernah dicoba oleh kisi tersebut, sehingga generator tidak memperlakukan kegagalan sebagai bukti kemustahilan. Ia menyimpan dunia non-sepele pertama yang ditemukannya sebagai cadangan, dan jika empat puluh percobaan berlalu tanpa satu pun solusi satu-bagian yang bersih, ia mengirimkan cadangan itu alih-alih berputar tanpa henti. Hasilnya adalah jaminan yang pragmatis: tidak pernah ada kemenangan cuma-cuma, hampir selalu ada jalan masuk yang sungguhan, dan tidak pernah ada penantian tanpa akhir demi level yang "sempurna". 1
Mundur selangkah, dan pembuat level Contraption adalah contoh bersih dari pola pemecahan masalah yang sangat tua dan sangat umum: bangkitkan dan uji. Ajukan sebuah kandidat secara acak; periksa terhadap persyaratan Anda; simpan jika lolos, buang dan ajukan lagi jika gagal. Inilah perulangan di balik konten prosedural dalam permainan yang tak terhitung jumlahnya, di balik sebagian besar komputasi evolusioner, dan, jika dilihat sekilas, di balik seleksi alam itu sendiri: mutasi mengajukan, lingkungan menguji, yang bertahan tetap ada. 4
Yang membuat versi Contraption elegan adalah bahwa ujinya bukanlah proksi murahan bagi kelayakan bermain, melainkan kelayakan bermain itu sendiri. Generator tidak memperkirakan apakah sebuah level adil dengan menghitung tepian atau mengukur jarak. Ia benar-benar memainkan level itu, dua kali: sekali dalam keadaan kosong untuk memastikan level itu bukan hadiah gratis, dan sekali dengan jalur landai penjajak untuk memastikan ada jalan yang tersedia. Fisika deterministik yang sama yang akan menilai solusi Anda adalah fisika yang telah memverifikasi teka-teki itu. Tidak ada "pemeriksa level" terpisah yang bisa melenceng dari aturan sebenarnya, karena hanya ada satu himpunan aturan, yang digunakan untuk segalanya.
Dan karena semuanya deterministik, audit ini bebas dari keberuntungan di kedua arah. Seed harian tidak dapat bersekongkol untuk memberi seorang pemain lapangan yang lebih mudah daripada pemain lain, dan tidak dapat memberi siapa pun lapangan yang tidak adil, karena sebelum level itu menjadi tantangan, ia sudah bertahan setelah dimainkan, oleh permainan itu sendiri, melawan dirinya sendiri.