časť 09
Políčka z malých šesťuholníkov, alebo ako vyrobiť mapu, ktorá sa dá zopakovať
Každá partia pôvodného Dice Wars mala inú mapu. Generátor nepravidelných políčok je krátky nápad a dlhá zmluva s minulosťou: uloženými hrami, zdieľanými odkazmi a dennou výzvou.
Prvá verzia hry mala šesť pravidelných mozaík: trojuholníky, štvorce, kosoštvorce, tehly, šesťuholníky, osemuholníky. Pekné, čisté a nudné. Pôvodný Dice Wars vyzeral inak. Podľa recenzie JayIsGames a zdrojového kódu HTML5 verzie (mriežka 28 × 32 šesťuholníkových buniek a najviac 31 políčok) bola mapa zložená z drobných šesťuholníkov a každé políčko vzniklo náhodným zlepením niekoľkých z nich. Výsledok: nepravidelné políčka a každá partia iná mapa.
Zadanie znelo, aby Kniežatstvá[1] vyzerali takto. A hneď k nemu otázka: bude fungovať seed, keď je dát toľko? Odpoveď je rozdelená na dve časti. Generátor je krátky príbeh. Slová „seed funguje“ sú dlhý príbeh.
Ako vzniká mapa
Generátor je funkcia Grid.build('blob', …). Postup sa dá zhrnúť do siedmich krokov (dokumentácia ich vedie desať):
- Tvar mapy. Z malých šesťuholníkov (strana 1) sa vyberie súvislý tvar (ostrov, súostrovie, prstenec alebo obdĺžnik) s približne
7 Nšesťuholníkmi, kdeNje počet políčok. - Stredy políčok. Rozhodia sa rovnomerne: nový stred sa prijme, len ak je dosť ďaleko od prijatých.
- Rast. V každom kole môže každé políčko pribrať jeden šesťuholník, s pravdepodobnosťou danou jeho „rýchlosťou“ (0,55 až 1,45), takže vznikajú malé aj veľké políčka. Vyššiu váhu majú šesťuholníky, ktoré už majú viac susedov v políčku, takže políčka sú súvislé, ale nepravidelné.
- Oprava malých políčok. Políčko s menej než štyrmi šesťuholníkmi dostane šesťuholníky od väčších susedov (ak sa sused nerozpadne). Ak sa nedá, zmizne, a to sa stáva v 3 % máp.
- Vyhladenie hraníc. Šesťuholník, ktorého väčšina susedov patrí inému políčku, prejde k nemu. Dve kolá odstránia väčšinu tenkých výbežkov. Priemerná „kompaktnosť“ (obvod voči veľkosti) klesla z 2,32 na 2,16, deviaty decil z 2,65 na 2,36. Kruh má približne 1,9 až 2,0.
- Diery. Obrys políčka musí byť jedna slučka. Ak by rozdelenie uzavrelo iné políčko alebo záliv, skúsi sa až šesť rozdelení. V praxi sa to deje pri 1 % prvých pokusov a opakovanie to vždy vyrieši; záverečné zlúčenie ostáva ako poistka.
- Obrys. Je zjednotením šesťuholníkov políčka. A stred políčka, kam sa kreslia kocky, je bod najďalej od okraja.
Číslo pre porovnanie: dnes (192 máp, 9 479 políčok) má políčko v priemere 7 šesťuholníkov (od 4 do 16), v priemere takmer 4 susedov (3,95) a mapa sa vygeneruje za zhruba 20 ms.
Čo má seed spoločné s minulosťou
Seed je text („KOCKY“), z ktorého vznikne celá mapa. To je pohodlné: mapu možno zdieľať odkazom, denná výzva je pre všetkých rovnaká a uložená hra nemusí nosiť obrysy políčok. Uložená partia nesie len vlastníka a počet kociek každého políčka a geometria sa pri obnove vygeneruje znova. Mapa s obrysmi má asi 24 kB, uložená hra po troch kolách asi 10 kB vrátane záznamu.
Ale z toho vyplýva zmluva s minulosťou: generátor sa nesmie zmeniť tak, aby sa zmenila mapa z rovnakého seedu, inak sa rozbijú všetky uložené hry, odkazy a záznamy. Tri ochrany:
- Čistá aritmetika. Aby mapa vyšla v každom prehliadači rovnako, generátor používa iba sčítanie, odčítanie, násobenie, delenie a odmocninu (presne definované v IEEE 754),
Maps poradím vkladania a triedenie s úplným usporiadaním. V súbore generátora nie je jediné volanieMath.sin,Math.cos,Math.loganiMath.random: funkcie, ktorých výsledok štandard presne nepredpisuje, sa nepoužívajú. - Zlatý odtlačok. Test uchováva odtlačok mapy z pevného seedu. Ak sa generátor zmení náhodou, test spadne.
- **
GEN_VERSION.** Ak sa generátor zmení úmyselne, zvýši sa číslo verzie a staré uložené hry sa zahodia (a odtlačok sa prepíše). Hra nikdy neobnoví partiu z cudzej verzie generátora.
Hry s procedurálnymi svetmi poznajú to isté. Seed vo svete Minecraftu platí vždy len pre verziu generátora, v ktorej vznikol. Tu je tá zmluva zapísaná v teste, nie v pamäti vývojára.
Čo to urobilo s hrou
Nový tvar nesmel pokaziť to, čo bolo namerané (pozri predchádzajúci článok o kalibrácii). Výsledky:
- Obtiažnosť: nová hodnota nastavenia „Náhodné tvary“ má 0 bodov, je teda rovnako ľahká ako trojuholníky (AI úrovne 2 vyhráva 18,9 %, úrovne 3 vyhráva 34,9 %, pri šesťuholníkoch 13,3 % a 36,7 %).
- Starý svet sa nepohol. Osemnásť kontrolných meraní (
--verify) vyšlo identických: generovanie starých tvarov sa nezmenilo ani o jediný bit. - Poradie hráčov: výhoda prvého ťahu je rovnaká ako pri šesťuholníkoch (2 hráči 93 %, 3 hráči 61 %, 4 hráči 41 %, 8 hráčov 16 %).
- Dĺžka partie: o štvrtinu kratšia, lebo políčok je menej (8 až 19 kôl namiesto 10 až 22).
- Odtlačky bežných hier: zo 172 sa zmenili iba štyri, tie pre Kniežatstvá. Ostatných 168 je rovnakých.
Denná výzva zámerne nemá náhodné tvary. Pridanie hodnoty do zoznamu, z ktorého sa vyberá tvar dňa, by zmenilo nastavenie všetkých dní, aj tých, ktoré už boli odohrané. Aj túto vetu stráži test.
Overenie: 37 mutantov
Generátor, kreslenie a nastavenia sa overili mutačnou kontrolou: do kódu sa zámerne vložia chyby (mutanty) a skúša sa, či ich testy odhalia. Zo 37 mutantov testy zachytili 35, z toho tri až po rozšírení testov o zlatý odtlačok viacerých máp, ikonu terénu a mapy s dierami z jediného pokusu. Zvyšné dva boli ekvivalentné: boli to nadbytočné kontroly (súvislosť jazera, ktorú už zaručoval prstenec susedov, a nadbytočná podmienka vyhladenia). Tie sa z kódu odstránili. Prežitý mutant je totiž buď chýbajúci test, alebo zbytočný kód.
Čo si z toho odnášam
- Nápad je krátky, zmluva je dlhá. Generátor má približne tristo riadkov. Garancia, že rovnaký seed dá navždy rovnakú mapu, je väčšia práca než samotný generátor.
- Zapíš zmluvu do testu. Zlatý odtlačok vie povedať „zmenilo sa to“ aj o tretej ráno.
- Hráč nevidí generátor, vidí mapu. Prvý nápad na stred políčka bol „správny“ podľa algoritmu a zlý podľa oka. Kontrola je vždy aj pohľad.
- Prežitý mutant je dar. Buď test, alebo mŕtvy kód.
Aktualizácia z 2. novembra 2026
Dňa 2. novembra 2026 sa HTML5 verzia originálu prečítala celá (Čo je v zdrojovom kóde originálu (pripravovaný článok č. 42)) a niekoľko miest tohto článku treba spresniť. Pôvodný text ostáva, ako bol.
- Ako vzniká mapa originálu. Úvod píše, že „každé políčko vzniklo náhodným zlepením niekoľkých“ malých šesťuholníkov. Mriežka 28 × 32 a najviac 31 políčok sú správne, ale políčka sa nezlepujú: rastú po jednom, každé z jadra ôsmich buniek a prstenca zo všetkých voľných susedov jadra, a ďalšie začne v kandidátovi s najmenšou prioritou; políčko s piatimi bunkami alebo menej sa zruší. Simulácia 5 000 máp z opisu dáva 30,0 políčka po 20,5 bunky (TUNING §44.2).
- Oddiel „Ako vzniká mapa“ (sedem krokov) a čísla pod ním opisujú generátor „náhodných tvarov“ z 20. októbra, nie postup originálu. Nie je to ani dnešná mapa Kniežatstiev: tie prešli 29. októbra na mapu „pole“, obdĺžnik, v ktorom políčka zaberú, čo zaberú, kreslený od oka podľa snímok originálu (pri 7 hráčoch 42,0 políčka po 13,0 bunky a 4,19 susedov; TUNING §44.3). Ostrov s asi siedmimi bunkami na políčko ostal vo voľnej hre. Pole nie je kópiou postupu originálu.
- „Zadanie znelo, aby Kniežatstvá vyzerali takto.“ Zadanie bolo napodobniť vzhľad originálu (nepravidelné políčka z malých šesťuholníkov); jeho postup sa vtedy nepoznal. Kópiou postupu je až hra Kmene, ktorá je od 2. novembra 2026 vo vývojovej vetve hry (Kmene: kópia, ktorá sa dá zmerať (pripravovaný článok č. 43)). Kniežatstvá sa nemenili práve pre zmluvu s minulosťou z oddielu o seede: zmena generátora by rozbila uložené hry, záznamy a odkazy.
- Zdroje. Odkaz na kód HTML5 verzie dokladá len mriežku a strop políčok, nie vznik políčka zlepením.
Zdroje a poznámky
- Pôvodná hra: recenzia JayIsGames a zdrojový kód HTML5 verzie (mriežka a počet políčok). Rozhodnutia a čísla:
docs/DESIGN.md§19, postupdocs/TUNING.md§18. Štatistiky:node tools/blobs.js(20. 10. 2026; mapa v článku:node tools/blobs.js --svg mapa.svg --seed KOCKY --target 32 --map island). - Minecraft: seed spolu s verziou hry určuje svet; generátor sa medzi verziami menil. Všeobecne známy fakt, nie z merania.
Poznámky
- Do verzie 0.65.6 z 31. októbra 2026 sa volal Klasik. ↩︎