časť 20
Denná výzva v páse a šesť rozohraných hier naraz
Veľká dlaždica dennej výzvy sa zmenila na nízky pás a okno, hra si pamätá výsledok dňa a každý druh hry má vlastné miesto na uloženie aj vlastný zámok. Ako sa overilo, že sa pri presune nestratila žiadna rozohraná hra.
Dlaždica dennej výzvy bola najväčšia na domovskej obrazovke a napriek tomu nepovedala jedinú vec, ktorú si hráč pri nej pýta: či je dnešok hotový. Zadanie z 23. a 24. októbra 2026 vzišlo z jedného pohľadu na obrazovku. Dlaždica mala dátum, nastavenie, body a celé pravidlo dňa, rozbíjala mriežku, hlavolam dňa bol len odznak na dlaždici Puzzle Labs a ponúkala sa vždy len posledná rozohraná hra. Z toho vznikli päť častí práce a jedna veľká otázka: čo sa stane s hrou, ktorú má hráč rozohranú, keď sa spôsob jej ukladania zmení?
Tento článok je záznam toho, ako sa to riešilo. Pozornosť si zaslúži najmä posledná časť: presun uložených hier je presne ten druh zmeny, pri ktorom stačí jedna chyba a hráč príde o rozohranú misiu alebo o zaplatený pokus.
Pás namiesto dlaždice
Dlaždica dennej výzvy zmizla. Nad dlaždicami je teraz jedno nízke tlačidlo naprieč celou šírkou: „Denné výzvy · 24. októbra“, počet „Dnes 1 / 2 splnené“ a čip za každú dennú aktivitu. Pod 560 px sa zalomí do dvoch riadkov. Kliknutie alebo Enter otvorí okno so zoznamom: v riadku je ikona, názov, dátum dňa, veta o stave („Splnené: výhra v 23. kole, 108 b.“), nastavenie dňa, tlačidlo ⓘ a tlačidlá Hrať, Pokračovať alebo Zopakovať podľa stavu.


Dôležitejšie než vzhľad je, ako sú aktivity zapísané. Každá je jeden záznam v zozname Dailies.LIST v súbore js/data/dailies.js: identifikátor, ikona, názov, funkcia stavu, funkcia tlačidiel a text pre ⓘ. Funkcie stavu sú čisté, teda nevedia nič o aplikácii a testujú sa samostatne. Veci, ktoré hra nevie z dát (rozohraná hra v mieste „daily“, nastavenie dňa), sa dodávajú v kontexte. Pridanie tretej dennej aktivity je preto jeden záznam v zozname plus jeden obslužný kód v aplikácii a test zlyhá, ak záznam obslužný kód nemá alebo naopak.
| aktivita | ikona | kedy sa ukáže |
|---|---|---|
| Denná výzva | 📅 | od začiatku (po uvítacej karte) |
| Hlavolam dňa | 🧪 | spolu s dlaždicou Puzzle Labs |
Pás sa nezobrazí vôbec, ak nie je odhalená žiadna denná aktivita. Hráč, ktorý má dennú výzvu a ešte nemá laboratóriá, vidí jeden čip.
Čo si hra pamätá o dni
Dovtedy hra ukladala iba dni, ktoré sa vyhrali (kvôli úspechom). Nevedela preto povedať „dnes: prehra v kole 14“. Nové pole profile.dailyGame drží posledných 14 dní, v ktorých sa výzva hrala: deň, výsledok (výhra, výhra na body, prehra, prehra na body, remíza), kolo, skóre, počet dohraných hier a počet výhier. Pravidlo je jedno: kolo a skóre patria prvej výhre dňa, ak nejaká je, inak poslednej hre. Prehra teda ukazuje ✗, kým ju nevystrieda výhra, a výhru už nevezme späť žiadna neskoršia prehra.
Zápis sa robí v tej istej mutácii profilu ako samotná hra, takže sa jedna hra nemôže započítať dvakrát. A nič, čo sa vyplatilo predtým, sa nemení: prvú výhru dňa pre odmeny a úspechy čítajú funkcie z ach.days, ako doteraz. Starší profil dostane doplnené dni z toho, čo už obsahuje: každý deň z ach.days (najviac posledných 14) sa stane výhrou, s kolom a skóre z histórie, ak v nej záznam existuje. Dnešnú prehru nemá odkiaľ doplniť, a preto sa nehádá.
Pravidlo dňa
Denná výzva má od 22. októbra pravidlo „Dlhé vojny sa končia“ (topenie zastavených stohov po troch kolách bez zmeny majiteľa a ponuka ukončiť pat). Predtým bola jeho veta priamo na dlaždici. Teraz je na dvoch miestach: v ⓘ pri výzve a v okne Pravidlá tejto hry ako samostatná časť „Pravidlo dňa“, keď práve beží denná hra. Čísla vo vete sa berú z Settings.WEAR, takže text a pravidlo sa nemôžu rozísť. Hra zo staršieho uloženia, ktorá také pravidlo nemá, časť nezobrazí.
Šesť druhov, šesť miest
Najväčšia časť práce nebola vidieť. Hra dovtedy mala jedno miesto na rozohranú hru. Kto začal Kniežatstvá[1], prepísal rozohranú misiu kampane, a kto mal zaplatený pokus na Uber misiu alebo železnú misiu a spustil Kniežatstvá, o pokus prišiel. Dva taby navyše nemohli hrať dve rôzne hry, lebo zámok „jedna hra – jeden tab“ bol jediný.
Rozhodlo sa o šiestich druhoch: classic, free, daily, mini, campaign a iron. Odveta s bossom, Uber misia a Zlatý goblin patria do kampane, bez ohľadu na sektor. Hlavolam, lekcia, sledovaná hra a hra otvorená zo snímky žiadne miesto nezaberajú, ako doteraz.

| rozhodnutie | prečo |
|---|---|
šesť kľúčov audamir.save.<druh>, nie jeden kľúč s mapou | dva taby, ktoré hrajú dva druhy, píšu do dvoch kľúčov; jeden kľúč by bol cyklus čítaj-zmeň-zapíš, v ktorom sa hra stráca |
druh miesta je jeho kľúč, Store.loadSave(druh) ho overí podľa meta | ručne vyrobený súbor nesmie dostať minihru do miesta Kniežatstiev |
zámok na druh: Web Lock <predpona>.game.<druh>, bez Web Locks nájom audamir.lock.<druh> | všetko, čo sa už dokázalo pre jeden zámok, platí pre každý |
| tab vlastní najviac jeden druh (druh hry, ktorú hrá) | tab, ktorý len prezerá, nevlastní nič |
| zaplatený pokus sa pýta len pri hre toho druhu, v ktorom čaká | hra iného druhu o pokus už neprichádza |
Dôsledok je viditeľný: Kniežatstvá sa dajú hrať, kým čaká zaplatený pokus na Uber misiu. Dva taby môžu hrať dva druhy naraz a otázka „Hra je otvorená v inom tabe“ sa kladie len pri rovnakom druhu. Riadok druhu, ktorý vlastní iný tab, hovorí „Otvorené v inom tabe“ a ponúka len „Prevziať tu“.
Zoznam rozohraných hier na domovskej obrazovke ukazuje tri riadky (najnovší uložený prvý) a potom „Zobraziť všetky (n)“. Rozhodnutia, ktoré zadanie nechalo otvorené, sú v návrhu označené ako predvolené, ktoré môžem zmeniť: nová hra druhu nahradí rozohranú hru toho istého druhu bez otázky (ako doteraz), záznam dňa sa drží 14 dní, kým rozohrané hry sa časom neobmedzujú, a hlavolam dňa sa odhaľuje s Puzzle Labs.
Rozsah zmeny: 51 súborov, 1 668 pridaných a 384 odstránených riadkov. Pás a okno s dátami mali 25 súborov. Pravidlá hry (rules.js, ai.js, engine.js, flow.js, mods.js) sa nezmenili, a to sa kontrolovalo: node tools/baseline.js (172 odtlačkov) a node tools/calibrate.js --verify (18 meraní) vyšli totožné.
Ako sa dokázalo, že sa nič nestratilo
Starý jediný kľúč audamir.save sa musí presunúť do miesta svojho druhu raz, pri štarte stránky, skôr než ho niečo nakreslí. Postup je „najprv zapíš, potom odstráň“: ak by sa zápis nepodaril, stará hra zostane. Ak v mieste druhu už hra je, ostane novšia podľa času uloženia, pričom hra bez času je najstaršia. Ak je miesto len na jednu kópiu, starý kľúč sa odstráni a zápis sa skúsi znova, pri neúspechu sa vráti späť. Nečitateľná hodnota sa zahodí a starý záznam zámku zmizne. Migrácia nič neplatí, len presúva hodnotu.
Tu platí pravidlo, ktoré projekt získal pri premenovaní identifikátorov: ručne písané vzorky prejdú, kým skutočné dáta ukážu chybu. Preto tools/daily-hub-migration.js použije starý kód. Zo stavu hry tesne pred zmenou vyrobí skutočnú históriu v nepravom DOM-e: výhry a prehry v Kniežatstvách, voľnú hru, dennú výzvu vyhranú vo viacerých dňoch a rozohranú hru každého zo šiestich druhov v jedinom mieste starého kódu. Potom sa nad každý výpis spustí nová aplikácia. Overuje sa:
- hra leží v mieste svojho druhu bajt po bajte, starý kľúč aj záznam zámku zmizli a riadok je na domovskej obrazovke,
- profil sa po načítaní rovná profilu starého kódu (mince, skúsenosti, história, úspechy, rebríček), okrem nového poľa
dailyGame, - záznam dňa obsahuje štyri skoršie dni s kolom a skóre z histórie,
- Pokračovať pokračuje v tej istej hre (seed, režim, kolo) a pri Kniežatstvách, voľnej hre a dennej výzve sa hra dohrá s rovnakými rozhodnutiami ako v starom kóde. Profil po nej je presne ten, ktorý vyrobil starý kód, takže sa nič nezaplatilo dvakrát.
Čo našla nezávislá recenzia
Návrh po zostavení prečítala nezávislá kontrola (24. 10. 2026, len na čítanie). Na hlavných cestách nenašla stratu ani dvojitú výplatu, ale našla päť skutočných problémov. Všetky sa opravili; tri hlavné:
- Zámok sa porovnával so zlou hrou. Kontrola držania miesta porovnávala s hrou, ktorá tam bola pred novou. Ak iný tab zámok zobral počas tvorby mapy štartu, tab dohral celú hru a zápis na konci odmietol. Do kontroly sa teraz posiela hra, ktorá začína (test v oboch mechanizmoch zámku). Chyba bola zdedená z predchádzajúceho návrhu zámku.
- Hra bez času prepísala novšiu. Hra zo starého kľúča bez poľa
tsmohla prepísať novšiu v mieste druhu. Teraz je hra bez času najstaršia a migrácia zapisuje skôr, než odstráni. - **Každá udalosť
storagez iného tabu prekreslila domovskú obrazovku.** V tabe, ktorý hral, sa v polovici misie kampane prepol kubik avatara na zlatý. Uloženie iného druhu teraz nemení dáta tohto tabu, len zoznam rozohraných hier pri zobrazení domovskej obrazovky.
Ďalšie dva nálezy (štart, ktorý sa neuskutočnil, ale držal nárok, a kolo z poškodeného miesta prevzaté bez kontroly) sa opravili tiež. Okrem nich návrh pomenúva dve obmedzenia, ktoré zostali.
Čo zostalo neoverené a čo zostalo otvorené
- Zastaraný profil v zamrznutom tabe. Dva taby, ktoré hrajú dva druhy naraz, majú každý svoju kópiu profilu. Živý tab sa dorovnáva pri každej udalosti
storage, ale tab, ktorý prehliadač zmrazil alebo odložil do vyrovnávacej pamäte dozadu a dopredu, môže po dohraní hry zapísať zastaraný profil. Pre kampaň a železný beh toto okno existovalo už predtým, teraz je aj pre Kniežatstvá a dennú výzvu. Lacné riešenie (prečítať profil pred zápisom výsledku) zasahuje každú koncovú kartu, a preto sa nerobilo. - Starý tab otvorený cez aktualizáciu. Starý jediný kľúč sa presúva raz pri štarte stránky. Ak ho starý tab neskôr dohrá, zanechá v mieste snímku, ktorú starý kód nikdy nevymaže (maže len starý kľúč). Po aktualizácii treba staré taby obnoviť.
- Skutočný hover nad ⓘ sa nekontroloval; hover v paneli prehliadača nenastavil
:hover, a preto ho kryje len test. - Zostavená verzia (
dist/web) sa na tomto stroji neprešla smoke testom, lebo Chromium v balíku snap tu nejde. - Texty v češtine, srbčine, ruštine, španielčine, portugalčine, francúzštine a nemčine sú návrhy, ako zvyšok týchto katalógov. Najdôležitejšie na prečítanie je veta o tom, čo platí opakovaná výhra.
Čo si z toho odnášam
- Čo sa dá dokázať starým kódom, nemá sa dokazovať ručne písanou vzorkou. Kontrola, ktorá z rozohranej hry vyrobí profil pôvodným kódom a dohrá ju novým, odhalí nielen stratu hry, ale aj dvojitú výplatu.
- Kľúč na druh je lepší než jedna mapa. Dva taby, ktoré píšu do jedného kľúča, si prepisujú hry. Dva taby, ktoré píšu do dvoch kľúčov, nie.
- Hotovo neznamená rovnaké pre všetkých. Zadanie predpokladalo, že platí len prvá výhra dňa, a zmeralo sa, že to platí pre jednu časť odmien a pre druhú nie. Také veci sa majú zapísať ako otázka, nie ticho opraviť.
- Kontrola, ktorá závisí od dátumu, nie je kontrola. Dlho sa zdalo, že migrácia občas zlyháva; zlyhávala kontrola. O tom viac v článku o chybách týždňa (pripravovaný článok č. 24).
Zdroje a poznámky
- Stav: návrh a záznam overovania v dokumentácii hry, stav k 24. 10. 2026 (zlúčené ako verzia 0.49.1; oprava kontroly migrácie 26. 10. 2026). Opis migračnej kontroly a nezávislej recenzie je podľa nej.
- Rozsah zmien (51 súborov, 1 668 pridaných a 384 odstránených riadkov; pás a okno 25 súborov) sú riadky podľa
git show --statv repozitári hry, nie miera práce. - Nespúšťalo sa pri písaní:
baseline.js(172 odtlačkov) acalibrate.js --verify(18 meraní) vyšli totožné podľa dokumentácie hry, nie znova. - Čo v článku nie je: vznik pravidla dňa „Dlhé vojny sa končia“ (22. 10. 2026); články série ho nepopisujú.
- Séria: rovnaký postup pri premenovaní identifikátorov je v článku Ako testovať hru, ktorá sa nikdy neprestane meniť, odmeny a úspechy v článku Úspechy a úvod.
Čo sa nepodarilo overiť: skutočný hover nad ⓘ, zostavenú verziu dist/web a nástroje tools/daily-browser.js a tools/lock-browser.js (podľa dokumentácie sa na tomto stroji nespúšťali); preklady do siedmich ďalších jazykov sú návrhy.
Poznámky
- Do verzie 0.65.6 z 31. októbra 2026 sa volal Klasik. ↩︎