hrxdev
Bahasa Indonesia

#1 Inti deterministik, ditegakkan oleh kompiler

· Nick

Belum ada yang bisa dilihat, jadi catatan pertama ini membahas bagian yang tidak akan dilihat siapa pun: inti simulasi. Game ini dimaksudkan untuk menjalankan hingga 1.000 narapidana dan staf pada 20 tick per detik dan bisa menjelaskan mengapa siapa pun melakukan apa pun. Itu hanya berhasil jika masukan yang sama selalu menghasilkan dunia yang sama. Saya memutuskan menjadikannya sifat yang diperiksa mesin, sejak hari pertama.

Posisi saat ini

Saya berada di tonggak pertama, kerangka inti. Simulasinya adalah pustaka .NET murni tanpa kode Godot, dan klien Godot 4 sejauh ini hanya membuka adegan 3D kosong. Belum ada model dunia, belum ada ubin, belum ada karakter, belum ada simpanan. Anggaran 1.000 karakter adalah target; saya belum mengukur apa pun pada skala itu.

Tick

Waktu di inti adalah hitungan tick bilangan bulat, 20 per detik. Tidak ada waktu berbasis bilangan pecahan. Satu tick menjalankan tiga fase: menerapkan perintah dari luar, menjalankan sistem-sistem dalam urutan yang ditulis di satu tempat, lalu menerapkan perubahan yang ditunda dan memajukan penghitung. Jika sebuah galat lolos dari tick, dunia ditandai rusak dan berhenti. Hari ini daftar sistemnya kosong; loop itu ada supaya sistem pertama punya tempat.

Perintah dan log

Dunia hanya berubah lewat perintah. Perintah adalah rekaman kecil dengan id tipe yang tetap dan pengodean biner yang ditulis tangan. Untuk setiap perintah, dunia mengodekannya, memberinya cap tick dan nomor urut, memvalidasinya (hanya baca), menulisnya ke log, dan baru kemudian menerapkannya. Perintah yang ditolak juga dicatat, yang seharusnya membantu untuk laporan bug. Seed ditambah log dimaksudkan untuk mereproduksi sebuah jalannya permainan secara persis. Format file replay belum ditulis.

Bilangan acak

Saya menulis sendiri generator bilangan acaknya (SplitMix64 dan xoshiro256**) dan melarang Random dari pustaka standar di inti. Dunia punya empat aliran bernama (perintah, kebutuhan, AI, peristiwa), diturunkan dari seed dan disimpan dalam keadaan dunia, sehingga ikut disimpan dan di-hash. Untuk pekerjaan yang urutannya tidak boleh berpengaruh, ada generator tanpa keadaan berbasis kunci dari domain, entitas, dan tick. Keluaran untuk seed 42 dikunci, karena itulah pada dasarnya format replay: ubah generatornya dan setiap replay lama rusak.

Hash dunia

Sebuah hasher kecil yang peka urutan melipat seed, tick, aliran acak, dan ringkasan log perintah menjadi 64 bit. Dua jalannya permainan yang seharusnya identik bisa dibandingkan dengan satu angka. Saat ini ia hanya mencakup bagian-bagian itu, karena dunia belum berisi apa pun selain itu. Membandingkan hash setiap N tick selama permainan berjalan adalah langkah berikutnya.

Menjadikan nondeterminisme sebagai galat build

Saya tidak ingin bergantung pada ingatan akan aturan. Inti dibangun dengan penganalisis API terlarang: waktu jam dinding, bilangan acak tanpa seed, GUID acak, hash string yang diacak, thread dan alat bantu paralel, SIMD, serta API string yang bergantung pada budaya semuanya menggagalkan build. Pemeriksaan lain memastikan tidak ada keadaan statis yang bisa berubah dan memindai kode hasil kompilasi untuk apa pun yang lolos. Komputer saya memakai lokal Rusia dengan koma desimal, alasan bagus untuk melarang API yang bergantung pada budaya.

Lalu saya melangkah lebih jauh dan melarang koleksi hash standar (Dictionary, HashSet, dan sejenisnya) dari inti, karena urutan iterasinya adalah sumber penyimpangan klasik. Inti mendapat array, list, dan dua koleksi kecil buatan sendiri dengan urutan yang terdokumentasi. Ini tidak kedap sepenuhnya: API yang mengembalikan koleksi hash lewat antarmuka generik masih bisa lolos, dan sebagian perlindungan hanya bekerja dalam pengujian.

Cara dibangunnya

Peralatan di sekitar kode juga diotomatisasi, dan skrip yang sama berjalan di Windows dan macOS. Pendekatan umumnya ada di Cara dibuat.

Berikutnya

Yang masih terbuka di tonggak ini: model dunia dengan lantai bertingkat, file simpanan dan replay, uji determinisme, dan runner skenario tanpa antarmuka dengan baseline benchmark. Setelah itu datang tampilan pembangunan di Godot. Lihat peta jalan.

← Semua catatan devlog