İçindekiler

Kısaca: Strateji oyununda her başkent ya da kaynak, bir maliyet sınırına kadar çevresine yayılır; her konum da en yakın kaynağını bilmek ister. MKA Engine bu iki işi motorun temel işlemi olarak verir; maliyeti, sınırı ve sonucun anlamını ise oyun yazar. 282 kaynaklı, oyun ölçeğine yakın bir ölçümde en yakın kaynak yolu, modların (oyuna eklenen kural paketlerinin) çalıştığı WebAssembly ortamında yaklaşık 13 ms sürdü; kaynak başına ayrı yayılım yaklaşık 2,7 saniye aldı.
Neden her kaynak için ayrı çağrı yetmedi?
Bir haritaya her başkentten bir mürekkep damlası düşürdüğünü düşün. Her damla kendi sınırına kadar yayılır, ama iki damlanın karşılaştığı yerde hangisinin önce vardığını bilmek istersin. Oyunun bugünkü yolu her başkent için ayrı bir yayılım çağrısı yapıyor; her çağrı bütün harita boyunda bir yanıt döndürüyor ve mod bu yanıtları tek tek birleştiriyordu. Bu birleştirmeye katlama diyoruz. Oyunun kendi düzeltme geçişleri de eklenince aynı iş birçok kez yapılıyordu.
Motor ne ekledi?
Sınırlı çok kaynaklı yayılım. Tek çağrıda birçok kaynak verilir. Her kaynak, kendi sınırına kadar, kendi sahibinin kenar kurallarıyla yayılır; kaynaklar birbirinin alanını almaz. Dönen sonuç yalnız ulaşılan konumlardır; bir kaynağın ulaştığı her konum bir isabettir.
Etiketli en yakın kaynak. Her konum, kendi etiketiyle (konumun hangi kaynak grubuna ait olduğunu gösteren değerle) eşleşen kaynaklar arasından en düşük maliyetlisinin değerini alır. Sonuç harita boyunda bir dizidir: her konum için tek bir değer. Bu değerleri tutan sütunu (her konum için bir değer tutan tablo kolonunu) mod kendisi yazar.
İlk çözüm, her isabeti modun belleğine vermekti. Kaynak sayısı arttıkça toplam isabet de büyüyordu: 282 kaynak, her biri yaklaşık 17 bin isabetle, toplam 4,8 milyon isabet üretti. Bu, modun 16 MiB'lik belleğini aşıyordu; işi 41 çağrıya bölünce de işlem bütçesi (yakıt) bitiyordu. Bu yüzden her konum için yalnız en yakın kaynağı döndüren ayrı yol eklendi.
Motor ne tutar, oyun ne seçer?
| Konu | Motor | Oyun |
|---|---|---|
| Yayılımın işleyişi | Maliyete göre yayılır, sınırda durur | — |
| Maliyet | Maliyet girdilerini çağrı başına bir kez okur | Maliyetin formülü ve kaynağı, örneğin arazi ya da yol |
| Sınır | Sınırı parametre olarak alır | Sınırın değeri |
| Etiket | Eşleştirir, her konum için bir kaynak seçer | Hangi konumun hangi etikete ait olduğu |
| Sonuç | Yanıtı dizi olarak döndürür | Sonucun anlamı: yakınlık, pazar erişimi ya da ikmal |
Bu ayrım bilerek yapıldı. Yakınlık, pazar erişimi ve ikmal aynı yayılım işlemiyle kurulur, ama her biri farklı bir kural ister: bazısı en yakın kaynağı, bazısı her kaynağın kendi alanını ister. Motor ikisini de destekler; hangisinin kullanılacağını oyun seçer.
Ölçümler
Ölçümleri ekransız bir ölçüm koşusuyla aldık: 30 000 konumlu bir harita; doğrudan motor kodunda 280, WebAssembly ortamında 282 kaynak. Her ölçüm yedi turda alındı; her turda ölçülen yollar art arda koşuldu. Makinede başka derlemeler sürüyordu ve yük ortalaması 14 ile 27 arasındaydı; bu yüzden mutlak sayılar gürültülüdür, karşılaştırma ise aynı turda alınan oranlarla yapılır. Tablodaki değer her yolun yedi turunun ortancasıdır: yedi değer sıralandığında ortadaki.
| Yol | Ortanca (ms) |
|---|---|
| 280 ayrı yayılım çağrısı (bugünkü yol) | 88,4 |
| Tek çağrıda 280 kaynak | 10,1 |
| Yol | Ülke boyu sınır (24 birim) | Oyun ölçeği sınırı (226 birim) |
|---|---|---|
| En yakın kaynak, tek çağrı | 8,2 | 13,1 |
| Kaynak başına yayılım, modda katlama | 83,3 | 2 691,8 |
Doğrudan motor kodunda fark yaklaşık 8,7 kattır: 280 ayrı çağrının her biri maliyet girdilerini yeniden okur, tek çağrı bunu bir kez yapar. Tek kaynakta fark küçüktür (0,26 ile 0,30 ms). WebAssembly ortamında oyun ölçeğinde fark yaklaşık 200 kat, ülke boyu sınırda yaklaşık 10 kattır. Oyun ölçeği sınırı kaynak başına yaklaşık 17 bin, toplam 4,8 milyon isabet üretir. Bu farkın iki kaynağı var: yanıt toplam erişimle büyümez, harita boyunda kalır; aynı etiketin bütün konumları yerleşince de arama durur. Yanıt harita boyudur: 30 000 hücre, yaklaşık 480 KB. WebAssembly ölçümü, aynı gün alınan doğrudan motor ölçümüyle aynı düzendedir.
Bedeli ne?
- Yanıt her çağrıda harita boyundadır: en yakın kaynak yolu bile tam diziyi döndürür, yalnız bir değeri değil.
- Sonucu doğrudan tablo sütununa yazan bir yol da düşünüldü. Yazma maliyeti ölçülemeyecek kadar küçük çıktığı için yazılmadı.
- Ölçüm tek makinede, paylaşımlı yükte alındı. Oyunun tam tur süresi ve gerçek maliyet formülleri ölçülmedi.
Sık sorulanlar
Sınırlı yayılım nedir?
Bir kaynaktan başlayıp maliyet sınırına kadar çevreye yayılan ulaşılabilirlik hesabıdır. Birden çok kaynak için her biri kendi sınırına kadar yayılır ve kaynaklar birbirinin alanını almaz.
En yakın kaynak nasıl bulunur?
Her konum, kendi etiketiyle eşleşen kaynaklar arasından en düşük maliyetli olanın değerini alır. Kaynak sayısı büyük olsa da bu tek bir çağrıda, harita boyunda bir yanıt olarak döner.
Motor bu hesabı oyun kuralı olarak yazar mı?
Hayır. Motor yalnız yayılmanın temel işlemini verir; maliyeti, sınırı ve sonucun oyundaki anlamını oyun seçer.
Ölçümler ne kadar güvenilir?
Tek makinede, paylaşımlı yükte alındı. Mutlak sayılar gürültülüdür, ama aynı turlarda alınan oranlar tutarlıdır. Oyunun tam tur süresi ve gerçek maliyet formülleri ölçülmedi.
Kaynaklar ve kayıtlar
Dış kaynaklar: WebAssembly güvenlik belgesi (yeni sekmede açılır), MDN: WebAssembly kavramları (yeni sekmede açılır).
İlgili günlükler: Oyunda mod desteği, Olaylar ve çarpanlar.
Bu günlük hakkında sorularınız ya da önerileriniz varsa iletişim sayfasından yazabilirsiniz. Motorun genel tanıtımı için MKA Engine sayfasına, bütün günlükler için Geliştirici Günlükleri listesine bakabilirsiniz.
Kaynaklar ve ilgili belgeler
Bunlar da ilginizi çekebilir
- Bir strateji oyununun dünya haritası nasıl yapılır?
MKA Engine için gerçek veriden 27.357 konumluk bir 1337 dünya haritası ürettik: arazi, nehirler, boğazlar, nüfus ve konum sınırları nasıl çıkarıldı?
- Oyun motoruna giden yol
MKA Engine'e nasıl başladık: dört oyunu okumak, belirlenimciliği yasa saymak, aşama aşama ölçerek ilerlemek ve şu an neredeyiz.