Programování textových her v TADS 3, část 3. – Předměty

V minulém díle jsme se naučili vytvořit místnosti a propojit je do mapy světa. Svět je ale zatím hrozně pustý a prázdný, musíme ho zaplnit objekty. Některé objekty budou přenosné a hráči si je budou moci vzít, jiné budou pevnou součástí lokace. V dobře udělané hře bychom na každou věc, prakticky na každé podstatné jméno zmíněné v popisu místnosti, měli mít ve hře objekt, aby ho hráč mohl prozkoumat a dozvědět se o něm více informací.

Jednoduchý objekt, jeho název a slovník

Základem všech fyzických objektů ve hře je třída Thing. Takové předměty může postava hráče sebrat, nosit je s sebou a někde zase položit. Příklad objektu vidíte níže, jeho definici napíšeme hned pod místnost, ve které chceme, aby objekt byl nalezen. Všimněte si, že na rozdíl od místnosti začíná definice objektu znaménkem plus. Velice podrobně o významu znaménka plus budeme mluvit v následujícím díle seriálu, takže prozatím si jen pamatujte, že znaménko umístí objekt do místnosti.

+ newComponent: Thing
    'nová nový náhradní zesilovač součástka/součástky/díl/VIZ-54/VIZ54/VIZ/
        pouzdro*součástky' 'nová součástka' *3
    "Je to výkonový integrovaný zesilovač VIZ-54 v keramicko-kovovém pouzdře s
        otvorem na přišroubování k chladiči. Vypadá nově a hezky se leskne.
        Bohužel je jen jeden a potřebuješ tři. "

    gcName = 'nové součástky, nové součástce, novou součástku, nové součástce,
        novou součástkou'
    gcVocab = 'nové novou nového novému novém novým náhradním součástky/
        součástce/součástku/součástkou/zesilovače/zesilovači/zesilovačem/dílu/
        dílem/pouzdra/pouzdru/pouzdrem*součástek*součástkám*součástkách*
        součástkami'
;

Při vytváření objektu musíme zadat několik vlastností, jako slovník, název objektu a popisek prozkoumání. Tyto vlastnosti v drtivé většině případů zadáme prostřednictvím šablony, takže se s názvy vlastností vocabWords, name a desc v praxi moc nesetkáváme.

Slovník

Slovník je první řetězec v jednoduchých uvozovkách, který jsme u objektu (hned po názvu třídy Thing) uvedli. Slouží parseru, aby věděl, jakými všemi možnými způsoby může hráč objekt pojmenovat, až bude psát své příkazy. Formát slovníku není úplně triviální, takže si ho pojďme vysvětlit. Aby parser mohl správně porozumět tomu, co hráč píše, musí rozlišovat druhy slov na podstatná jména, přídavná jména a u některých objektů i množné číslo podstatného jména.

V řetězci slovníku nejprve uvedeme všechna přídavná jména, kterými může hráč objekt označit, a oddělujeme je mezerami. Za ně napíšeme všechna podstatná jména a ty mezi sebou oddělujeme lomítkem (přídavné přídavné podstatné/podstatné). Parser ví, že hráč může používat různé kombinace přídavných a podstatných jmen, ale že přídavná uvede vždy před podstatnými. Pozná tedy „náhradní součástka VIZ-54“ i „nový zesilovač“, či kterékoliv jednotlivé slovo. Potřebujeme-li vynechat podstatné jméno a zadat jen mnoho přídavných, uvedeme místo podstatného jména pomlčku (přídavné přídavné -).

Někdy máme ve hře více podobných objektů, které se např. liší jen přídavným jménem, jako například nová součástka a porouchaná součástka. V takových případech je velmi vhodné do slovníku obou objektů uvést i množné číslo. Zadává se na konci řetězce definující slovník po podstatných jménech a oddělí se od nich hvězdičkou. Jakmile hráč použije množné číslo v příkazu, hra pochopí, že hráč mluví o obou objektech. Když zadá např. příkaz >prozkoumej součástky, hra mu zobrazí popisy obou objektů.

Název

Název objektu je druhý řetězec v jednoduchých uvozovkách. Hra použije název objektu kdykoliv, kdy bude potřebovat objekt pojmenovat v nějakém svém sdělení, jako např. při výpisu inventáře, v různých zprávách, že se něco stalo a nebo vysvětlení, proč něco nemůže hráč udělat atp.

Rod

Za názvem následuje mluvnický rod objektu, který jazykový balíček potřebuje ke správnému skloňování hlášek. To je to číslo dekorované hvězdičkou. V českém jazyce rozlišujeme čtyři rody – mužský životný (*1), mužský neživotný (*2), ženský (*3) a střední (*4). Za rodem už následuje běžný popisek prozkoumání ve dvojitých uvozovkách.

S mluvnickým rodem je ještě jedna potíž. Jeden objekt může občas mít více synonym a každé v jiném rodu. Uvažte třeba „ten dům“, „ta budova“, „to stavení“. Podobná situace nastane i v případě, kdy jedním objektem vyjadřujeme dohromady více různých dekorací, které nemá cenu rozdělovat do více objektů. Za hvězdičkou uvádíme ten rod, který je hlavní, který patří k zadanému názvu objektu. Aby parser věděl, jakým zájmenem se na objekt odvolávat, když reaguje na příkaz hráče, kde hráč mohl zvolit nějaké synonymum, musíme mu o dalších rodech říci pomocí vlastnosti changeGender. V řetězci stačí uvést alespoň kousek slova spolu s jeho rodem.

+ Component
    'zvlněná křivka jemná mlha jasné zeleň krajina/kopec/kopce/kopců/mraků/
        mraky/déšť/slunce/porostu/porost' 'krajina' *3
    "Dramaticky zvlněná křivka kopců na nichž jsou děla umístěna nebezpečně
        blízko na dostřel se chvílemi skrývá v jemné mlze mraků skrápěna deštěm,
        jindy zas jasné slunce rozzáří zeleň porostu. "

    changeGender = 'kop:2, mrak:2, déš:2, slun:4, porost:2'
    gcName = 'krajiny, krajině, krajinu, krajině, krajinou'
    gcVocab = 'krajiny/krajině/krajinu/krajinou/kopci/kopcem/kopcům/kopcích/
        kopci/mrakům/mracích/deště/dešti/deštěm/slunci/sluncem/porost/porostem'
;

Množné číslo

Některé objekty, které budeme ve hře mít, budou představovat něco v množném čísle. Ať už to bude hromádka několika věcí, nebo to budou třeba dveře, které jsou pomnožné (mají tvar množného čísla, i když se jedná o jeden objekt). Takové objekty označíme vlastností isPlural:

+ tresorDiamonds: Thing 'diamanty/diamant' 'diamanty' *2
    "Několik malých diamantů v průhledném plastovém pytlíku. Všechny jsou úplně
        stejné, jeden jako druhý. "

    isPlural = true
    gcName = 'diamantů, diamantům, diamanty, diamantech, diamanty'
    gcVocab = 'diamantů/diamantům/diamantech/diamantu/diamantem'
;

Skloňování

Také jste si zajisté už všimli dvou dalších vlastností gcName a gcVocab, které v ukázkách uvádím na konci definice objektu. Zatímco název a slovník objektu v záhlaví používám kvůli udržení přehlednosti jen pro definici v prvním pádu, těmito dvěma vlastnostmi do hry pak doplním zbývající pády. Pro hru je potřeba dodat všechny pády kromě pátého (oslovujeme/voláme), který dáváme jen postavám do slovníku. V gcName tedy napíšeme postupně 2., 3., 4., 6. a 7. pád oddělené čárkou a formát gcVocab je stejný, jako pro slovník v záhlaví.

Řešení nejednoznačností

Jednou ze skvělých vlastností TADSu je, jak dobře se dokáže vyrovnat s nejednoznačnostmi v příkazech zadaných hráčem. Velice to pomáhá plynulosti hry.

>kopni do panelu
A co tím „panelu“ máš na mysli? Podlahový panel, nebo nouzový ovládací panel?

>ovládací
Zapřel ses a vší silou kopnul do panelu, ale asi to nemělo ten účinek, ve který jsi doufal. Panel se vyresetoval a opět svítící zelené kontrolky ukazují, že autopilot plně (a blbě) řídí loď.

Ať se budete snažit sebevíce, určitě se vám stane, že několik objektů bude pojmenováno stejně. I kdybyste se vyhnuli stejným podstatným jménům, u častých přídavných jmen jako „malý“, „červený“ apod. se tomu prakticky nedá vyhnout. Když si parser není jistý, umí se hráče zeptat, a hráč mu může odpovědět třeba jen přídavným jménem. TADS umí rozlišit i úplně stejné objekty podle polohy (jablko na stromě nebo jablko na zemi?) či vlastnictví (svůj kafovak nebo Borisův kafovak?) apod.

Když budete vytvářet některé objekty, které se dají snadno zaměnit (třeba tlačítka – tlačítek bude ve hře třeba více), dejte si pozor na jejich název. V Základně na asteroidu s sebou hráč nosí tablet, který má „zapínací tlačítko“. V kontextu tabletu se tlačítko zaměnit nedá, ale v podpalubí jsou také tlačítka na nouzovém panelu. Když hráč zadá >stiskni tlačítko, hra se musí zeptat, které tlačítko má na mysli. Zda tlačítka na panelu, nebo zapínací tlačítko. V takové situaci může být hráč snadno zmaten, soustředí se na ovládací panel, a už zapomněl, že s sebou nese tablet a zapínací tlačítko je na něm. Proto při řešení nejednoznačnosti je v otázce lepší zvolit alternativní název „tlačítko tabletu“, který se zadá do vlastnosti disambigNameKohoCo.

+ tabletButton: ComponentDeferrer, Button, Component
    'zapínací domů zpět home tlačítko (na) tabletu/tlačítko'
    'zapínací tlačítko' *4
    "Jediné fyzické tlačítko, které na tabletu je. Slouží k zapnutí displeje a
        případně k návratu na úvodní nabídku. "

    disambigNameKohoCo = 'tlačítko tabletu'

    gcName = 'zapínacího tlačítka, zapínacímu tlačítku, zapínací tlačítko,
        zapínacím tlačítku, zapínacím tlačítkem'
    gcVocab = 'zapínacího zapínacímu zapínacím tlačítka tlačítku tlačítkem'
;

Všimněte si, že slovník je dostatečně volný, aby hráč mohl tlačítko označit mnoha různými způsoby. Na uvedeném příkladu jste si mohli všimnout ještě jedné zvláštnosti. Slovo „na“ je ve slovníku uvedeno v závorkách. To parseru říká, že hráč sice může takové slovo použít, když bude o objektu mluvit, ale musí spolu s ním použít i nějaké další slovo. Samotné slovo „na“ nestačí k tomu, aby parser rozpoznal daný objekt. Označují se tak velice obecná slova, která by se mohla snadno zaměnit a která by hráč určitě nepoužil sama o sobě, když bude objekt uvádět v nějakém příkazu.

SpecialDesc

Po vstupu nebo po rozhlédnutí v místnosti hra automaticky vypíše všechny přenosné objekty, které zde leží. Na nepřenosné objekty ale normálně nijak upozorňováno není, protože se předpokládá, že se o nich autor zmínil v popisu místnosti. Občas se hodí na nějaký objekt zvláště upozornit, protože je pro hru důležitý, ale není vhodné se mu věnovat v základním popisu místnosti. Takovému objektu můžeme nastavit vlastnost specialDesc na dvojitými uvozovkami ohraničený řetězec, která na rozdíl od běžného popisku prozkoumání bude vložena do popisu místnosti a bude zde mít svůj samostatný odstavec. Představme si třeba tovární halu s nějakým strojem – v popisu místnosti zmíníme prostor a okolí, všechny východy, a stroj, který tvoří dominantu haly a hráč s ním má něco dělat, si automaticky přidá do popisu místnosti svůj vlastní odstavec pomocí specialDesc.

Alternativně k vlastnosti specialDesc můžeme nastavit initSpecialDesc, která bude mít stejnou funkci, ale bude aktivní (a zastoupí prve jmenovanou vlastnost) jen dokud je objekt v úvodním stavu, což normálně znamená, dokud ho hráč poprvé nevezme. (Nicméně co úvodní stav znamená, můžeme změnit úpravou metody isInInitState, takže může platit až do jiné události ve hře, než pouhého sebrání předmětu.)

Přesně stejně funguje i vlastnost initDesc, která zastoupí běžný popisek prozkoumání, dokud je objekt v úvodním stavu. Tuto vlastnost můžete použít u objektů, které jsou třeba malé a špatně vidět. Nastavíme jejich initDesc na málo konkrétní popisek: „Vedle pařezu se leskne nějaký malý mosazný předmět.“ Po sebrání se už hráč z běžného prozkoumání dozví, že se jedná o mosazný klíč.

Thing, hierarchie tříd a dědičnost

V prvním díle seriálu jsme si říkali, že objekt resp. třída je soubor vlastností (proměnných obsahující data) a metod (funkcí, které můžeme zavolat). V praxi se stane, že např. potřebujeme třídu, která je skoro jako Thing, většina jejích vlastností a metod je stejná, ale liší se v několika detailech. A to nám právě umožňuje dědičnost. Je to způsob, jak vytvořit novou třídu, tzv. potomka a v programu uvést jen ty vlastnosti a metody, které má navíc či které se liší. Budete-li číst zdrojový kód některé třídy odvozené od Thing, uvidíte právě jen ty odlišnosti. Musíte si pak představit, že třída má i všechny vlastnosti a metody, které automaticky zdědila od svého předka.

Třída Thing vytváří běžné přenosné objekty a stojí na vrcholu rozsáhlé hierarchie specializovaných tříd, které slouží k vytvoření nejrůznějších druhů objektů, které v textových hrách potkáme. Jenom vypsat celý strom dědičnosti by zabralo několik stránek! O některých důležitých třídách si postupně povíme a ukážeme si je v praxi, zdaleka ale nezvládneme všechny.

Mezi několik běžně používaných specializovaných tříd přenosných objektů patří následující:

  • Food je něco, co může postava sníst. Mňam :-)
  • Flashlight je svítilna, kterou může hráč zapnout a vypnout. Kromě ní existují i další zdroje světla s odlišným chováním FueledLightSource, Candle, Matchstick. Všechny najdete jako potomky základního zdroje světla LightSource.
  • Readable je objekt, jako třeba kniha. Kromě běžného prozkoumání může hráč i >přečíst knihu, a dozví se více. Delší popis se vloží do vlastnosti readDesc jako dvojitými uvozovkami ohraničený řetězec. Prozkoumání totiž v textovkách znamená jen zaměření pozornosti na zevnějšek, kdežto při čtení vezme postava knihu do ruky a prolistuje ji.
  • Wearable je určeno pro oblečení, obuv, ale i třeba přívěsky a podobné objekty, které může hráč obléknout či si je nasadit a mít je na sobě.

Všechny tyto třídy už mají základní logiku chování naprogramovanou, např. jídlo snězením zmizí, svítilna jde zapínat a vypínat a skutečně poskytuje světlo v temných místnostech apod. Na autorovi je jen doplnit popisky.

Nepřenosné objekty

Objekty odvozené od třídy Thing a jejích potomků, o kterých jsme si zatím říkali, jsou předměty, které může postava hráče vzít, přenášet mezi lokacemi a případně je někam odložit. Při zabydlování scenérie budeme ale chtít vytvořit řadu nepřenosných objektů, které jsou součástí lokace. Právě k tomu jsou určeny potomkové třídy NonPortable. Na rozdíl od přenosných objektů nebudou nepřenosné vypsány v rámci rozhlédnutí v místnosti, leda by měly nastavenu vlastnost specialDesc. Třídu NonPortable ale nepoužíváme přímo, vybereme některého konkrétního potomka. V základu se rozdělují do dvou skupin na Fixture a Immovable.

Fixture je něco, co je pevnou součástí lokace, u které je na první pohled jasné, že nejde přemisťovat. Používá se třeba na dveře, okna, vypínače na zdi či ve venkovním prostředí domy, stromy atp. Konkrétně si můžeme vybrat jednu z následujících tříd:

  • Fixture představuje pevný objekt, který na pokus o sebrání, pohnutí a položení někam reaguje chybovými zprávami cannotTakeMsg, cannotMoveMsg a cannotPutMsg. Pokud na objektu tyto vlastnosti nenastavíte na svůj jednoduchými uvozovkami ohraničený řetězec, použije se standardní knihovní hláška.
  • CustomFixture reaguje jednou společnou chybovou zprávou cannotTakeMsg na všechny tři způsoby přemístění.
  • Decoration je nedůležitý objekt, který byl do hry přidán k doplnění scenérie, protože byl někde zmíněn. Hráč ho může prozkoumat, ale na jakékoliv jiné příkazy reaguje zprávou notImportantMsg, která normálně říká, že objekt není důležitý.
  • Distant je objekt, se kterým hráč nemůže manipulovat, protože je příliš daleko. Představme si Měsíc na obloze, vzdálené hory apod. Podobně jako u dekorace můžeme standardní hlášku tooDistantMsg změnit.
  • Unthing představuje něco, co v lokaci chybí, ale hráč by se po tom mohl shánět a chtít to prozkoumat či s tím něco udělat. Hodí se pro předměty, které z nějakého důvodu zmizely, někdo je ukradl atp. Reaguje zprávou notHereMsg, kterou doporučuji změnit a vysvětlit, proč tu předmět není.

Immovable jsou předměty, které se sice nedají přemístit, ale není to o nich na první pohled zřejmé, hráč se to dozví, až to teprve zkusí. Představme si různé věci, které nejsou nijak přidělané, ale jsou příliš velké či těžké, jako větší kusy nábytku, další postavy apod.

  • Immovable podobně jako Fixture reaguje na pokus o sebrání, pohnutí a položení někam chybovými zprávami cannotTakeMsg, cannotMoveMsg a cannotPutMsg.
  • CustomImmovable zase reaguje jednou společnou chybovou zprávou cannotTakeMsg na všechny tři způsoby přemístění.
  • Heavy je objekt, se kterým nejde pohnout, protože je moc těžký. Třeba velký kámen. Není nijak přidělán, ale přesto s ním hráč nehne. Jediný rozdíl od Immovable je ve formulaci důvodu, proč s ním hráč nic nezmůže.
  • TravelPushable je objekt, který nejde zdvihnout, ale lze ho odtlačit do jiné lokace příkazy >tlač objekt na sever apod.

Na závěr si uveďme jeden příklad použití třídy CustomImmovable pro pilotní křeslo, ve kterém používáme jednu společnou chybovou zprávu při pokusu o manipulaci s ním. Povšimněte si také změněné předložky, třída Chair má výchozí předložku „na“, protože hráč typicky sedí na židli. My ale chceme, aby hráč seděl „v“ křesle. Téhož bychom dosáhli použitím třídy Armchair místo třídy Chair.

+ pilotChair: Chair, CustomImmovable
    'pilotní křeslo pilota/křeslo*křesla' 'křeslo pilota' *4
    "Pilotní křesla vypadají docela nově, je to jeden z těch nejrozšířenějších
        typů, které se přizpůsobují anatomii sedícího pilota, po drobném zásahu
        i ve skafandru, kdyby to bylo potřeba. "

    cannotTakeMsg = 'Křeslo je pevně přidělané k podlaze. '
    objInPrep = 'v'

    gcName = 'křesla pilota, křeslu pilota, křeslo pilota, křesle pilota,
        křeslem pilota'
    gcVocab = 'piotního pilotnímu pilotním křesla křeslu křesle křeslem
        -*křesel*křeslům*křesla*křeslech*křesly'
;

Klíče a zamčené dveře

Když už jsme si v předchozím článku ukázali, jak se propojují místnosti pomocí dveří, nesmíme opomenout klasický textovkový hlavolam – dveře zamčené klíčem. Je to úplně jednoduché, někam schováme klíč, což bude úplně obyčejný přenosný objekt, pro jehož vytvoření použijeme třídu Key. Objekt si nějak pojmenujeme, třeba brassKey, a pak dveřím přidáme vlastnost keyList = [brassKey]. Poslední potřebnou změnou je přidání ještě jedné třídy dveřím pomocí vícenásobné dědičnosti, takže budou deklarované jako LockableWithKey, Door.

Ovládací prvky

TADS disponuje i řadou tříd pro vytváření nejrůznějších ovládacích prvků, jako jsou tlačítka, která může hráč zmáčknout, páky, za které může zatáhnout či je zatlačit, vypínače, které se dají zapnout a vypnout, ciferníky, které s dají nastavit na hodnotu apod. Přidáte-li si do své hry objekty třídy Button, Lever, SpringLever, OnOffControl, Settable, NumberedDial či LabeledDial, budete už muset naprogramovat nějakou akci, která se k objektům váže, protože samy o sobě nic užitečného nedělají. O akcích budeme ale mluvit až v přespříštím článku, takže na tomto místě spíše jen poradíme, že až budete nějaký takový ovládací prvek potřebovat, je nejlepší se podívat na příklad jeho použití do TADS 3 Tour Guide a přizpůsobit si ho pro svou potřebu.

Hidden a PresentLater

Některé předměty, ať už přenosné nebo dekorace, se musejí ve hře objevit až později. Můžeme čekat, až nastane určitá událost, jako třeba oheň, který se objeví až po výbuchu, můžeme chtít objekt přidat do hry, až hráč něco prozkoumá, aby nebyl vidět hned od prvopočátku atp. Takové objekty ve zdrojovém kódu umístíme na své místo úplně stejně, jako by byly na místě od začátku, ale na jejich vytvoření použijeme jednu ze dvou tříd Hidden a PresentLater. Obě dělají podobnou věc, ale každá jinými prostředky.

  • Hidden je plnohodnotná třída odvozená od Thing, takže představuje přenosný objekt. Objekt je ve hře přítomen, ale je kompletně skryt před zraky postav, dokud ho nenecháme se zjevit zavoláním metody discover().
  • PresentLater naproti tomu je mix-in třída, která se nepoužívá samostatně, ale přidává se k libovolným jiným třídám pomocí vícenásobné dědičnosti a stojí na prvním místě vlevo v seznamu předků. Na začátku hry je objekt přemístěn pryč a na své místo se vrátí po zavolání metody makePresent().

Ačkoliv by se mohlo zdát, že obě třídy dělají to samé, je tu několik rozdílů, které stojí za povšimnutí. Zatímco Hidden objekt je stále na tom samém místě, PresentLater je ukryt přemístěním pryč. U PresentLater nemůžeme využít vlastnost moved, kterou se obvykle zjišťuje, zda hráč objekt už někdy sebral, protože ukrytí přemístěním ji nastaví na true. Naproti tomu ale máme více možností, jak řídit objevení. Chceme-li, aby se ve hře zjevilo více objektů současně, můžeme jim prostřednictvím vlastnosti plKey nastavit určitý klíč, tedy název, podle kterého je budeme rozpoznávat, a pak zavoláním PresentLater.makePresentByKey('klíč') je nechat objevit najednou, místo postupného volání makePresent() každého jednotlivého objektu. PresentLater objekty také mohou zase mizet a opakovaně se objevovat.

Smyslové vjemy

Kromě všech hmatatelných předmětů má TADS i poměrně propracované možnosti, jak zacházet s různými smyslovými vjemy. Nechali jste se unést a romanticky ve své hře popsali, jak do místnosti pronikají krásným mozaikovým oknem mihotavé paprsky světla? Fajn, tak potom budete potřebovat objekt třídy Vaporous, aby hráč mohl paprsky světla prozkoumat!

TADS má prostředky, jak zacházet se všemi pěti smysly. Nejjednodušší zacházení má chuť a hmat. Stačí jakémukoliv objektu nastavit vlastnosti tasteDesc a feelDesc na řetězec ohraničený dvojitými uvozovkami a hra začne reagovat na příkazy >ochutnej objekt a >dotkni se objektu. Podobným způsobem můžeme zacházet i se sluchem a čichem, v jednoduchých situacích stačí naplnit vlastnosti soundDesc a smellDesc daného objektu, ale v tomto případě nám TADS nabízí i poněkud sofistikovanější možnosti, kdy modelujeme zvuk a pach jako speciální samostatný objekt a hráč pak bude upozorněn na jeho přítomnost v lokaci.

V Základně na asteroidu jsme tuto možnost využili ve skladu, kde jsme chtěli hráče jemně navést na objevení rozvodů vzduchotechniky, které fungovaly jako tajná chodba vedoucí do Borisovy kajuty. Níže vidíte, jak to vypadalo přímo ve hře. Jakmile hráč vstoupil do skladu, byl upozorněn na zvuk chrápání, a když ve skladu chvíli něco dělal, tak se upozornění občas zopakovalo, takže byl motivován pátrat po zdroji.

Sklad
Sklad je docela rozlehlý, ale většinu prostoru zabírají regály s nejrůznějšími balíky obsahující vybavení a náhradní díly. V jednom z rohů je vyhrazené místo pro opravy s pracovním stolem a diagnostickým přístrojem a poblíž vchodu stojí bíle natřená lékárna. U stropu se táhnou rozvody vzduchotechniky, přímo nad stolem je větrací mřížka.

Lékárna obsahuje lékařské vybavení.

Slyšíš slabý zvuk chrápání.

>p mřížku
Přímo nad stolem je větrací mřížka rozvodů vzduchotechniky. Brání nasávání předmětů do rozvodů. Je poměrně velká, má rozměry cca 60×60 cm. Je zavřená. Vychází z ní slabý zvuk chrápání.

>p chrápání
Chrápání vychází z větrací mřížky a je velice tiché.

Ve zdrojovém kódu jsme objekt třídy Noise umístili do mřížky, která je jeho zdrojem. Hned v dalším článku si podrobně probereme umisťování objektů do jiných objektů.

+ supplyGrating: Fixture 'větrací mřížka' 'větrací mřížka' *3
    "Přímo nad stolem je větrací mřížka rozvodů vzduchotechniky. Brání nasávání
        předmětů do rozvodů. Je poměrně velká, má rozměry cca 60×60 cm. "

    gcName = 'větrací mřížky, větrací mřížce, větrací mřížku, větrací mřížce,
        větrací mřížkou'
    gcVocab = 'mřížky/mřížce/mřížku/mřížkou'
;

++ supplyNoise: Noise 'tiché slabé chrápání/zvuk' 'tiché chrápání' *4
    hereWithSource = "Slyšíš slabý zvuk chrápání. "
    displaySchedule = [2, 2, 3, 3, 4]
    descWithSource = "Chrápání vychází z větrací mřížky a je velice tiché. "
    sourceDesc = "Vychází z ní slabý zvuk chrápání. "
    noLongerHere = "Chrápání už neslyšíš. "

    gcName = 'tichého chrápání, tichému chrápání, tiché chrápání, 
        tichém chrápání, tichým chrápáním'
    gcVocab = 'tichého tichému tichý tichém tichým slabého slabému slabý slabém
        slabým chrápáním/zvuku/zvukem'
;

Vlastnost hereWithSource obsahuje text, který se zobrazí při vstupu do místnosti a při hráčově pobytu v místnosti se občas opakuje. Rozvrh opakování se řídí vlastností displaySchedule. Ta říká, že se má hlášení zopakovat po dvou tazích, pak opět po dvou tazích, pak po třech atd. Když hráč zadá příkaz >prozkoumej chrápání nebo >poslouchej chrápání, objeví se odpověď descWithSource. Vlastnosti hereWithSource a descWithSource mají ještě dva své protějšky …WithoutSource, které se použijí tehdy, kdy hráč objekt, který je zdrojem, nevidí (třeba budík schovaný pod polštářem). Nakonec vlastnost sourceDesc se připojí k prozkoumání objektu, který je zdrojem zvuku či pachu a jakmile hráč místnost opustí, zobrazí se mu hlášení noLongerHere. S pachy se zachází úplně stejně, jen se použije třída Odor.

Takové zacházení může být trochu overkill, a tak TADS nabízí i zjednodušené třídy SimpleNoise a SimpleOdor, které představují zvuk či pach, který nemá konkrétní zdroj a je trvalou součástí celé lokace. U těchto tříd nastavíme jen jediný popisek, který se automaticky použije ve všech potřebných situacích.

Další díly seriálu

Mohlo by se vám líbit...

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.