hrxdev
Türkçe

#1 Derleyicinin güvence altına aldığı deterministik bir çekirdek

· Nick

Henüz bakılacak bir şey yok, bu yüzden bu ilk yazı kimsenin görmeyeceği kısım hakkında: simülasyon çekirdeği. Oyunun saniyede 20 tick ile 1.000’e kadar mahkûm ve çalışanı çalıştırması ve herkesin neden öyle davrandığını açıklayabilmesi hedefleniyor. Bu ancak aynı girdilerin her zaman aynı dünyayı vermesiyle mümkün. Bunu ilk günden itibaren makinenin denetlediği bir özellik yapmaya karar verdim.

Şu an neredeyiz

İlk kilometre taşındayım: çekirdek iskeleti. Simülasyon, içinde hiç Godot kodu olmayan sade bir .NET kütüphanesi; Godot 4 istemcisi şimdilik boş bir 3D sahne açıyor. Dünya modeli, karo, karakter ya da kayıt yok. 1.000 karakter bir hedef; o ölçekte henüz hiçbir şey ölçmedim.

Tick

Çekirdekteki zaman, saniyede 20 olan tam sayı bir tick sayısıdır. Kayan noktalı zaman yoktur. Bir tick üç aşamadan oluşur: dışarıdan gelen komutları uygulamak, sistemleri tek bir yerde yazılı sırayla çalıştırmak, ardından ertelenmiş değişiklikleri onaylayıp sayacı ilerletmek. Bir tick’ten bir hata sızarsa dünya arızalı olarak işaretlenir ve durur. Bugün sistem listesi boş; döngü, ilk sistemin yerleşeceği bir yer olsun diye var.

Komutlar ve bir kayıt

Dünya yalnızca komutlarla değişir. Komut, sabit bir tür kimliği ve elle yazılmış ikili bir kodlaması olan küçük bir kayıttır. Her komut için dünya onu kodlar, tick ve sıra numarasıyla damgalar, doğrular (salt okunur), kayıt defterine yazar ve ancak ondan sonra uygular. Reddedilen komutlar da kaydedilir; bu, hata raporlarına yardımcı olmalı. Tohum artı kayıt, bir oyunu birebir yeniden üretebilmeli. Tekrar dosyasının biçimi henüz yazılmadı.

Rastgele sayılar

Rastgele sayı üreteçlerini kendim yazdım (SplitMix64 ve xoshiro256**) ve çekirdekte standart kütüphanenin Random sınıfını yasakladım. Dünyanın dört adlandırılmış akışı var (komutlar, ihtiyaçlar, yapay zekâ, olaylar); tohumdan türetilirler ve dünya durumunda saklanırlar, yani kaydedilirler ve özete dahil edilirler. Sıranın önemli olmaması gereken işler için alan, varlık ve tick’e dayanan, durumsuz ve anahtarlı bir üreteç var. 42 tohumu için çıktılar sabitlenmiştir; çünkü bu fiilen tekrar biçimidir: üreteci değiştirirseniz eski tüm tekrarlar bozulur.

Dünyanın özeti

Sıraya duyarlı küçük bir özet işlevi; tohumu, tick’i, rastgele akışları ve komut kaydının bir özetini 64 bitte birleştirir. Aynı olması gereken iki çalıştırma tek bir sayıyla karşılaştırılabilir. Şu an yalnızca bu parçaları kapsıyor, çünkü dünyada başka bir şey yok. Oyun sırasında her N tick’te bir özetleri karşılaştırmak bir sonraki adım.

Determinizmsizliği derleme hatasına çevirmek

Kuralları hatırlamama güvenmek istemedim. Çekirdek, yasaklı API çözümleyicileriyle derlenir: duvar saati zamanı, tohumsuz rastgele sayılar, rastgele GUID’ler, rastgeleleştirilmiş dize özetleri, thread’ler ve paralel yardımcılar, SIMD ve kültüre bağlı dize API’leri derlemeyi bozar. Başka kontroller değişebilir statik durum olmadığını doğrular ve derlenmiş kodu gözden kaçan bir şey var mı diye tarar. Benim makinem ondalık virgüllü Rusça yerel ayarı kullanıyor; kültüre bağlı API’leri yasaklamak için iyi bir neden.

Sonra daha da ileri gidip standart özet tabanlı koleksiyonları (Dictionary, HashSet ve benzerleri) çekirdekten yasakladım, çünkü yineleme sıraları klasik bir sapma kaynağı. Çekirdeğe diziler, listeler ve sırası belgelenmiş iki küçük kendi koleksiyonu kalıyor. Bu da kusursuz değil: özet tabanlı bir koleksiyonu genel bir arayüz üzerinden döndüren bir API yine de sızabilir ve korumanın bir kısmı yalnızca testlerde çalışıyor.

Nasıl yapılıyor

Kodun etrafındaki araçlar da otomatik, ve aynı betikler Windows’ta da macOS’ta da çalışıyor. Genel yaklaşım Nasıl yapılıyor sayfasında.

Sırada ne var

Bu kilometre taşında hâlâ açık olanlar: katlı dünya modeli, kayıt ve tekrar dosyaları, determinizm testi ve bir kıyaslama başlangıç değeriyle başsız bir senaryo çalıştırıcısı. Ondan sonra Godot inşa görünümü geliyor. Yol haritasına bakın.

← Tüm devlog yazıları