Skutečně jsem toho zase tak moc neměnil, ale neodpustil jsem si opravit odsazení, to opravuji i dětem, když je učím programovat ;-)
V příštím díle seriálu budu právě vysvětlovat provádění akcí a k čemu jsou jednotlivá stádia verify, check, action atd.
globalParamName
Na vlastnost globalParamName jsem se sám musel podívat, protože jsem ji ještě nepoužil. Jde o parametry zpráv. Když píšeš nějaké zprávy, tak se do nich dají dosazovat názvy objektů (a třeba zájmena apod. vztahující se k těm objektům) pomocí parametrů. Ponejvíce toho využívá knihovna, protože ta potřebuje univerzální hlášky, které se hodí pro jakýkoliv objekt. Programátor píšící hru to potřebuje jen tehdy, kdy píše něco obecnějšího, jako fungl novou akci. Pokud už ale píše konkrétní chování jednoho konkrétního objektu, nemusí zprávu parametrizovat, může napsat rovnou ten konkrétní objekt.
Taková zpráva může vypadat třeba následovně: "{Kdoco dobj} už {je} pod {kýmčím iobj}. " V rámci takových zpráv jsou předdefinované názvy "dobj", "iobj" a "actor", které dosadí patřičný objekt. Tak např. {Kdoco dobj} vloží název přímého objektu v prvním pádu a s velkým písmenem na začátku. Když bychom se ve zprávě chtěli odvolat na něco jiného, než přímý či nepřímý objekt resp. postavu provádějící akci, můžeme si nový objekt zaregistrovat. Dělá se to zavoláním gMessageParam(s) s příslušnou proměnnou, která umožní pak použít parametr vztahující se k té dané proměnné, jako třeba ring nebo key:
foundKeyOnKeyringMsg(ring, key)
{
gMessageParams(ring, key);
return 'Zkusil{a} {jsi} každý klíč na {komčem ring} a zjistil{a} {jsi},
že {kdoco key} pas{uje|oval[a key]} do zámku. ';
}
Kromě iobj, dobj a actor (určité parametry, jako {a}, {jsi} apod. se automaticky vztahují k actor, pokud u nich není napsáno něco jiného, proto ve zprávách nemusí být {jsi actor}), které jsou registrované automaticky během zprácování akce, a kromě proměnných, které si uživatel sám ručně zaregistruje pro jednorázové použití pomocí gMessageParam(s), lze kterémukoliv objektu pomocí globalParamName určit nějaký název parametru a ten pak bude dostupný ve zprávách.
Tedy zavedl-li jsi globalParamName = 'otec', znamená to, že pak můžeš použít {komučemu otec} v nějaké zprávě, což se přepíše na "otci". Takhle tedy asi ne moc užitčné, ale třeba u některých postav ve hrách, které hráč nezná a během hry se s nimi seznámí, to může být užitečné. Třeba v Heidi je "uhlíř", který po seznámení je pak představován jako "Joe Black", proto má globalParamName = 'burner' a ve všech rozhovorech, kde je zmíněno jeho jméno, je dosazeno parametrem "Jakmile {jsi} podala prsten {komučemu burner}, jeho oči zaplály nadšením...". Zpráva se pak vytiskne buď s "uhlířovi" nebo "Joe Blackovi" podle toho, zda se s ním Heidi seznámila (příkazy "řekni o sobě" resp. "zeptej se na něj").
Rod
V anglické lokalizaci se rod nastavuje právě pomocí vlastností isHim resp. isHer, ale pro češtinu by to nebylo moc praktické. Angličtina totiž rody používá jinak. V podstatě všechno je "it", dokud to není živý objekt, takže nastavují tyto vlastnosti jen u pár objektů. V češtině jsou ale rody rozprostřeny v podstatě nahodile po všech živých i neživých objektech, a tak jsem pro zkrácení dělal ten zápis s hvězdičkou a číselným vyjádřením. V češtině tedy vlastnosti isHim/isHer/isIt jsou kompletně nahrazeny vlastností gender a z ní pak čerpají další metody, jako canMatchHim a další, které používá parser.
Komplexní kontejnery
Komplexní kontejnery jsou potřeba všude tam, kde určitý objekt potřebuje mít více než jeden druh kontainmentu. Např. stůl, na který i pod který lze položit věci. Nebo kontejner, který může mít uvnitř sebe věci, ale zároveň má i nějaké komponenty z venku. A právě postava sedící na posteli je také vlastně v kontejneru, takže spolu s prostorem pod to jsou dva různé kontejnery v rámci jednoho objektu. Komplexní kontejner je takový dispečer nebo proxy, která rozděluje požadavky na jednotlivé podkontejnery v rámci jednoho objektu a tím obchází limitaci kontejnerové hierarchie.
U té akce by to chtělo ještě pořešit LookUnder, resp. ono je více možností. Teď to funguje zhruba takhle:
>p pohovku
Pamatuje příjezd ruských vojáků do Prahy. Není jisté, zda ten první nebo až ten
druhý. Vypadá to, že pod pohovkou je schovaný nějaký předmět.
>p masku
Nic takového jako „masku“ tu nevidíš.
>podívej se pod pohovku
Pod rozvrzanou pohovkou je plynová maska.
>r
Obývák
Nacházíš se v obýváku. Rozvrzaná pohovka je jediný kus nábytku, který tu
momentálně je.
Pod rozvrzanou pohovkou je plynová maska.
Otec tu stojí.
>p masku
Pochází z dávné minulosti. Je s podivem, že stále drží pohromadě.
Jak je z ukázky vidět, tak neproběhne ta zpráva s objevením masky (a nezavoláš discover), ale když si všimneš, tak se maska odkryje a je vidět. Totiž kontejnery automaticky zviditelňují Hidden objekty, pokud jim to nezakážeš. Ale udělají to jen tak mimochodem, nezobrazí tu zprávu, resp. zobrazí lister, takže to nevypadá tak slavnostně.
Takže jsou dvě možnosti. Buď doplnit akci LookUnder, kde se stane to samé, jako při prozkoumání pohovky dříve a kontrolovat a zprávu vypsat jen tehdy, pokud tam maska je a ještě nebyla objevena a nebo můžeš zprávu nechat vypsat v discover metodě masky. Prostě napíšeš zprávu a zavoláš inherited. Když to zkusíš, zjistíš, že to první je lepší, protože se to odehrává v rámci zpracování akce. Když bys to udělal v discover metodě, bude problém potlačit výpis objektů, který by se připsal ke zprávě o objevení a vypadalo by to divně. Tedy ono to jde potlačit, ale už by se zde ctěnému publiku ježily vlasy, takže mysím ideální varianta:
+ pohovka: ComplexContainer, Bed, Heavy 'rozvrzaná pohovka' 'rozvrzaná pohovka' *3
"Pamatuje příjezd ruských vojáků do Prahy. Není jisté, zda ten první nebo až ten druhý.
<<if !maska.discovered>>Vypadá to, že pod pohovkou je schovaný nějaký předmět. "
gcName = 'rozvrzané pohovky, rozvrzané pohovce, rozvrzanou pohovku, rozvrzané pohovce, rozvrzanou pohovkou'
gcVocab = 'rozvrzané rozvrzanou pohovky/pohovce/pohovku/pohovkou'
/*
* Pohovka kombinuje dva různé kontejnery. Jednak je to Bed, takže na ní může spočívat postava, druhak má prostor
* pod sebou, kde je ukryta maska. Proto musíme pohovku deklarovat jako komplexní kontejner a prostor pod pohovkou
* bude subkontejnerem.
*/
subUnderside: ComplexComponent, Underside
{
dobjFor(LookUnder)
{
action()
{
if(!maska.discovered)
{
"Nalezl jsi masku! A to masku plynovou, nikoliv maškarní. ";
maska.discover();
}
else inherited;
}
}
}
;
/*
* Plynová maska musí být třídy Wearable, aby si ji hráč mohl nasadit. To je třída, která se používá pro oblečení
* a podobné věci. Zároveň ji kombinujeme pomocí vícenásobné dědičnosti se třídou Hidden, která zajistí, že objekt
* bude na začátku hry skrytý, tedy jako by neexistoval. Ve hře se objeví až po zavolání jeho metody discover().
*/
++ maska: Hidden, Wearable 'plynová maska' 'plynová maska' *3
"Pochází z dávné minulosti. Je s podivem, že stále drží pohromadě. "
/* Maska se nachází v subkontejneru. */
subLocation = &subUnderside
gcName = 'plynové masky, plynové masce, plynovou masku, plynové masce, plynovou maskou'
gcVocab = 'plynové plynovou masky/masce/masku/maskou'
;
Což povede k snad už správnému textu:
>p pohovku
Pamatuje příjezd ruských vojáků do Prahy. Není jisté, zda ten první nebo až ten
druhý. Vypadá to, že pod pohovkou je schovaný nějaký předmět.
>podívej se pod pohovku
Nalezl jsi masku! A to masku plynovou, nikoliv maškarní.
>podívej se pod pohovku
Pod rozvrzanou pohovkou je plynová maska.
>r
Obývák
Nacházíš se v obýváku. Rozvrzaná pohovka je jediný kus nábytku, který tu
momentálně je.
Pod rozvrzanou pohovkou je plynová maska.
Otec tu stojí.
>vem ji
Hotovo.
>podívej se pod pohovku
Pod rozvrzanou pohovkou nic nevidíš.
Akorát jsem při tom našel ještě jednu chybu v knihovně, v souboru msg_neu.t se musí opravit tahle metoda:
class LookWhereContentsLister: DescContentsLister
showListEmpty(pov, parent)
{
/* show a default message indicating the surface is empty */
gMessageParams(parent);
defaultDescReport('\^' + parent.objInName + ' {|[jsi]} nic
nevid{[íš]|ěl[a]}. ');
}
;