Programování textových her v TADS 3, část 2. – Lokace

Herní svět typické textové hry je rozdělen do tzv. lokací, což jsou místnosti či malé oblasti venkovního prostoru, kde se postava hráče nachází. Hráč pak obvykle dosáhne na libovolné předměty, které se v lokaci nacházejí, a může s nimi manipulovat. O nich se dozví v popisu místnosti, kterou hra zobrazí těsně po jeho vstupu. To všechno známe, takže jak na to v TADSu? Pochopitelně pomocí objektově orientovaného programování.

Definice místnosti

controlRoom: Room 'Velín' 'do velínu'
    "Jsi ve velící místnosti, odsud se řídí těžba i všechny důležité činnosti
        související s provozem základny. Uprostřed je pohodlné pracoviště s
        velikým křeslem, velkými obrazovkami a gumovým popruhem na ruce, aby se
        operátor nevznášel od terminálu, když píše na klávesnici. Podél zadní 
        stěny stojí několik racků nacpaných servery. "
;

Zde vidíte definici jednoduché místnosti. Každou místnost chceme nějak pojmenovat, abychom pak mohli místnosti propojit mezi sebou. Zvolili jsme název objektu controlRoom, je to vlastně název proměnné, ve které je objekt uložen. Za dvojtečkou následuje třída, ze které je objekt odvozen. Místnosti se odvozují ze třídy Room nebo některého potomka. Potom musíme uvést několik názvů místnosti v jednoduchých uvozovkách. První je titulek místnosti, jak se zobrazí při rozhlédnutí, proto ho píšeme s velkým písmenem na začátku. Druhý povinný název je název místnosti jakožto cíle cesty, ten se použije při vypisování směrů. Uvádí se vč. případné předložky, hra ho použije např. v následujícím kontextu:

Zřetelné směry vedou na sever do jídelny, na jih do skladu, na východ zpátky do východní části chodby, na západ do velínu, na severozápad na toaletu a nahoru do kupole.

Název cíle cesty se používá i při popisu pohybu NPC postav mezi lokacemi. Pokud takové ve hře máme, bývá potřeba doplnit ještě i třetí název, a to název počátku cesty, odkud postava odchází. Zde by to mohlo být 'z velínu', ale v naší ukázce jsme to nepotřebovali. Nakonec následuje ve dvojitých uvozovkách popis místnosti, který se zobrazí při vstupu do místnosti a pokaždé, když hráč zadá příkaz >rozhlédni se.

Šablony

Když tuto definici porovnáme s ukázkou definice místnosti z prvního článku, všimneme si, že je stručnější. Nikde tu nevidíme žádné názvy vlastností, čekali bychom roomName, destName a desc, do kterých by byly textové řetězce přiřazené. Místo toho jen píšeme samotné textové řetězce. Toto zjednodušení, které se v TADSu často používá, je možné díky šablonám. Pro různé třídy existují pravidla, jaké vlastnosti v jakém pořadí můžeme na počátku definice objektu uvést a ony se automaticky zapíší do patřičných vlastností objektu. Šablona místnosti vypadá takto:

Room template 'roomName' 'destName'? 'srcName'? 'name'? "desc"?;

To znamená, že musíme uvést alespoň jeden řetězec v jednoduchých uvozovkách, který se vloží do roomName, a za ním můžeme přidat další volitelné řetězce pro další vlastnosti. Otazník značí volitelnou součást šablony. Do patřičných vlastností se jich zapíše tolik, kolik jich skutečně uvedeme. Přitom TADS dává pozor na dekoraci vlastností, tj. v tomto případě druh uvozovek, ta se musí shodovat se šablonou. V příkladu velínu výše, kde jsme zadali dva řetězce v jednoduchých a jeden ve dvojitých uvozovkách, dojde k naplnění roomName, destName a desc. Setkáte se ale i s jinými dekoracemi, než jen uvozovkami, třeba o pár odstavců níže uvidíte šipečku, která znamená cíl propojení.

Druhy místností

Kromě třídy Room, která vytvoří úplně obyčejnou místnost, můžeme použít některého potomka:

  • DarkRoom vytvoří místnost, ve které není vůbec žádné světlo. Dokud si hráč nějaký zdroj světla nepřinese, nemůže v místnosti prakticky nic dělat.
  • FloorlessRoom vytvoří místnost, ve které není podlaha. Hodí se např. ve hrách, kde hráč může šplhat po skále nebo vylézt do koruny stromu. Cokoliv hráč upustí, skončí ve spodní lokaci, kterou zadáme do vlastnosti bottomRoom.
  • OutdoorRoom je místnost, ve které nejsou stěny a podlaha se stropem je vyměněna za zem a oblohu, takže se hodí pro venkovní lokace.
  • ShipboardRoom se používá pro lokace situované na palubách lodí, kde místo tradičních směrů pohybu podle světových stran, které by v takovém prostředí nedávaly smysl, se použijí pohyby na příď, záď, levobok a pravobok.

Propojování místností na mapě

Kdykoliv vytváříme místnost, do které chceme, aby se dalo odněkud vejít, tak si ji pojmenujeme. Níže např. vytváříme objekt pojmenovaný corridorWest odvozený ze třídy Room. Podobně máme pojmenované všechny místnosti. Nyní stačí přiřadit k vlastnostem pojmenovaným po světových stranách objekty místností, do kterých se tím směrem dá jít. Napíšeme-li east = corridorEast, říkáme, že směr na východ vede do místnosti pojmenované corridorEast.

Dostupné jsou směry světových stran (north, south, east, west), šikmé směry (northeast, northwest, southeast, southwest), dále směry nahoru a dolů (up, down) a také dovnitř a ven (in, out). Kromě těchto směrů existují ještě speciální směry na palubě lodi.

Při tolika možnostech se může stát, že směr ven je stejný, jako směr nahoru, a proto lze přidat přemapování směru makrem asExit. V nabídce směrů v záhlaví se ukáže jen jeden hlavní směr, ale pokus projít tím druhým směrem povede do stejného cíle.

corridorWest: Room
    'Západní část chodby' 'do západní části chodby' 'ze západní části chodby'
    "Jsi na západním konci hlavní chodby spojující všechny prostory v obytné
        části základny. Stěny jsou obložené světlými plastovými panely, ve
        stropě jsou některé z nich prostřídány s panely osvětlovacími, podlaha
        je pokrytá tlumícím neklouzavým materiálem a na mnoha místech jsou madla
        usnadňující pohyb stejně jako v úplné beztíži. Vedou odsud vstupy do
        velína na západ, jídelny na severu, do skladu na jihu a žebřík nahoru do
        kupole. Na severozápadě je malý záchod. Chodba pokračuje na východ. "

    east = corridorEast
    west = controlPassageOutside
    south = supplyRoom
    northwest = toiletDoorOutside
    north = canteenPassageOutside
    up = dome
    out asExit(up)
;

Některé směry v příkladu výše ve skutečnosti neukazují přímo na jinou místnost, ale na konektor, který teprve vede do jiné místnosti. Konektor je objekt, který umožňuje spojení dvou lokací. Vlastně i každá místnost je zároveň autokonektorem, proto ji lze uvést přímo jako cíl cesty. Někdy se ale hodí definovat konektor samostatně.

Typickým příkladem konektoru jsou dveře, jako v případě směru na severozápad v ukázce výše. Jsou fyzickým objektem, který lze prozkoumat, který se nachází v lokaci hráče a kterým lze projít do cíle své cesty. Než se k jejich popisu dostaneme, podíváme se ale na pár jednodušších konektorů, které nepředstavují fyzický objekt, ale jen zajišťují doprovodné efekty při průchodu.

Ukecané a falešné konektory

Většina konektorů ve hře prostě hráče zavede do jiné lokace. Jakmile hráč vstoupí do nové místnosti, zobrazí se tučně nadpis místnosti a popisek rozhlédnutí. Ve většině situací to takhle stačí, protože lokace představují např. sousední místnosti v budově nebo blízké oblasti ve venkovním prostředí mezi kterými není nic zajímavého a důležitého pro hru. Přesto se občas najdou přechody mezi lokacemi, kde z nějakého důvodu je vhodné věnovat pár slov samotné cestě. Může to být např. delší úsek cesty, kterou hráč absolvuje nebo je způsob přemístění natolik neobvyklý, že si zasluhuje vysvětlit.

>s
Opatrně jsi vyskočil do výšky a zachytil ses úchytů na rampě pod zakotvenou lodí.

Pod zádí lodě
Jsi ve východní části servisní klece na rampě pod zadní částí lodi, která pokračuje dál na západ pod příď lodě. Prostor nad hlavou ti zakrývá trup lodi, který odsud vypadá ještě mohutněji, než jaký opravdu je.

Tyto situace lze vyřešit konektorem třídy TravelMessage, který automaticky zobrazí zprávu při průchodu hráče. Všimněte si způsobu zápisu vloženého objektu. Místo rovnítka za názvem vlastnosti je dvojtečka a název třídy (stejně jako za besideAirlock). Potom ve složených závorkách můžete uvést jakékoliv vlastnosti či metody. V tomto případě ale opět využíváme šablonu, proto nejsou žádné vlastnosti vyjmenované. Symbol šipky v šabloně označuje cíl konektoru a potom následuje popisek průchodu.

besideAirlock: Room 'Před základnou' 'před základnu'
    "Stojíš u kupole základny nedaleko přechodové komory. Na severu je na rampě
        ukotvená loď, na západě je otevřený vstup do přechodové komory. V dáli
        na východě leží překladiště kontejnerů.<.reveal hint-port-visited>
        <<if !gRevealed('lunch')>>Automaty vykládají kontejnery a postupně
        nahrazují přivezené těmi k odvezení. "

    west = airlockOuterDoorOutside
    in asExit(west)
    north: TravelMessage { -> underShipBack "Opatrně jsi vyskočil do výšky a
        zachytil ses úchytů na rampě pod zakotvenou lodí. " }
    up asExit(north)

    east: DeadEndConnector { 'k překladišti' "Vydal ses na východ k překladišti,
        ale v cestě je příliš mnoho vysokých a ostrých kamenů, tudy se k nim
        nedostaneš, za riziko poškození skafandru to nestojí, takže ses zase
        vrátil zpátky. " }
;

Schopnost při průchodu vypsat zprávu využívají i falešné konektory, které ve skutečnosti nikam nevedou. Třída FakeConnector vytváří takový konektor, který na první pohled vypadá, že někam vede a že jím lze projít, ale přitom průchod hráče neumožní. Tyto konektory se často používají na okrajích herního světa k vytvoření iluze většího světa a při pokusu o průchod zobrazí zprávu, proč hráč nemůže projít. Je potřeba zvolit takovou výmluvu, která dává smysl v rámci světa, ve kterém se děj odehrává. Např. postava hráče může říci, že tím směrem nejspíš hodně daleko není nic zajímavého, nebo se může bát po cestě jít atp. Obvykle se používají různé motivační důvody.

FakeConnector se používá tehdy, pokud důvod odmítnutí cesty je znám dopředu a postava hráče se ani nepokusí konektorem projít. Jestliže se postava hráče pokusí projít, ale na půl cesty si z nějakého důvodu rozmyslí svou cestu (např. narazí na zával v tunelu) a vrátí se do původní lokace, měl by být použit DeadEndConnector. Rozdíl je v doprovodných efektech a kontrolách, které se spustí, když hráč zadá příkaz k cestě.

Dvě strany dveří

Při propojování místností pomocí dveří je potřeba si dobře uvědomit, jak dveře fungují. Pro jejich vytvoření se používá dvojice objektů, která popisuje každou ze stran dveří. Tedy v každé ze dvou lokací je jeden objekt, který představuje tu stranu dveří, která je obrácena do té které místnosti.

V ukázce níže jsou dveře v kokpitu pojmenované cDoor a dveře ve společenské místnosti cDoorOutside. Směr v definici každé z místností (na palubě lodi se používají směry fore a aft – na příď a na záď) ukazuje na svůj objekt dveří. Obě poloviny dveří se pak propojí mezi sebou tím, že u jednoho z objektů (ne u obou) se uvede za šipkou název toho druhého objektu. Povšimněte si, jak v definici objektu cDoorOutside šipka ukazuje na objekt cDoor.

cockpit: ShipboardRoom
    'Pilotní kabina' 'do pilotní kabiny' 'z pilotní kabiny'
    "Kabina je rozdělena na dvě rovnocenné části, levou a pravou, pro dva
        piloty. Celý předek kabiny zabírá palubní deska, nad níž je malý průzor.
        Před palubní deskou jsou dvě anatomická pilotní křesla. Na levoboku jsou
        dveře ven bez přechodové komory. "

    aft = cDoor
;

+ cDoor: Door 'vnitřní tlakové dveře/těsnění*dveře' 'vnitřní tlakové dveře' *3
    "Jsou to mohutné dveře schopné udržet atmosféru v oddělené části lodi. Po
        obvodu je měkké těsnění, které občas prověřuješ. Z obou stran jsou
        výrazné tlakoměry ukazující tlak na druhé straně dveří. V případě
        potřeby tlakový uzávěr může lehce zaklapnout a udrží i velmi prudkou
        změnu tlaku. "
;

livingRoom: ShipboardRoom
    'Společenská místnost' 'do společenské místnosti' 'ze společenské místnosti'
    "Společenská místnost je největší místností uprostřed lodi. Po stranách na
        levoboku a pravoboku jsou zvukotěsné a neprůhledné kryty spacích kójí.
        Vzadu pokrývá stěny malá vestavěná kuchyňka, nebo spíš sada automatů
        pro přípravu konzervovaného jídla a nápojů i ve stavu beztíže. Podlaha
        je pokrytá tlumicím polyuretanem, strop má v sobě vestavěné osvětlovací
        pásy a mřížky vzduchotechniky. V předním koutě stojí běžecký pás. Vstup
        do pilotní kabiny na přídi lze vzduchotěsně uzavřít. "

    fore = cDoorOutside
;

+ cDoorOutside: Door -> cDoor
    'tlakové vstup (do) (pilotní) (kabiny) dveře/těsnění' 'tlakové dveře' *3
    "Jsou to mohutné dveře schopné udržet atmosféru v oddělené části lodi. Po
        obvodu je měkké těsnění, které občas prověřuješ. Z obou stran jsou
        výrazné tlakoměry ukazující tlak na druhé straně dveří. V případě
        potřeby tlakový uzávěr může lehce zaklapnout a udrží i velmi prudkou
        změnu tlaku. "
;

V ukázce jsem pro ilustraci ponechal u dveří jejich slovník a název. V následujícím článku věnovaném předmětům budeme o těchto vlastnostech mluvit podrobně.

Další druhy konektorů

Dveří existuje více druhů. Kromě obyčejných dveří existují třídy usnadňující naprogramování určitého druhu dveří, např. SecretDoor, které se tváří jako obyčejný předmět a není patrné, že se jedná o dveře, dokud se neotevřou, HiddenDoor, které nejsou v zavřeném stavu vůbec vidět, či AutoclosingDoor, aneb Brano zavíra samo. Kromě nich lze obyčejné dveře zkombinovat s třídou LockableWithKey a udělat tak uzamykatelné dveře apod., ale detailní popis překračuje rámec článku.

Podobně jako dveře se používají další druhy konektorů, které se liší v určitých detailech, jak jsou ve hře popisovány a na jaké příkazy reagují. Princip je ale podobný. Pokud místnosti nejsou spojené dveřmi, ale nějakým prostupem či chodbou, lze použít objekt třídy ThroughPassage. Dveře jsou vlastně z této třídy odvozené, protože se jimi také prochází, ale dveře lze navíc zavírat, chodbu však nikoliv.

Ve venkovních lokacích se může hodit objekt třídy PathPassage, který reprezentuje např. pěšinku v lese. Hlavní rozdíl je jazykový, spočívá v tom, že se dá jít po kom/čem a ne jít kým/čím resp. skrz koho/co.

Schody či žebříky vedoucí mezi lokacemi je vhodné reprezentovat objekty třídy StairwayUp a StairwayDown, po kterých lze vyjít či sejít resp. vyšplhat a sešplhat.

Enterable a EntryPortal

Ačkoliv to není úplně realistické, lokace ve většině her bývají z praktických důvodů uspořádány do čtvercové sítě a pohyb mezi nimi se odehrává ve směru světových stran (občas zpestřený o směry nahoru a dolů apod.). Pro hráče je to výhodné, mohou si snadno kreslit mapu na čtverečkovaný papír a příkazy pohybu ve směru světových stran se dají zkrátit na jediné písmeno, takže se snadno na příkazové řádce zadávají.

Představme si nyní situaci, kdy hráč stojí na ulici a na sever od něj se tyčí budova, do které může vstoupit. Pochopitelně hráč může zadat příkaz >s a dostat se tak do budovy. Ale může ho také napadnout zadat >jdi do budovy a nebo dokonce, než tak učiní, může chtít budovu prozkoumat. To je pochopitelný požadavek, protože budova, ač představuje jinou lokaci, je z ulice vidět.

Právě pro tyto situace máme třídu Enterable, která představuje objekt, který existuje v jedné lokaci a do něhož lze vstoupit a ocitnout se v jiné lokaci. Nemusí to být jen viditelná budova, lze tak reprezentovat i něco, co hráč přímo nevidí, ale ví, že to tam je. Objekt třídy Enterable není konektorem propojujícím lokace, ale na takový konektor, což mohou být třeba dveře budovy, ukazuje.

V naší hře jsme Enterable objektem reprezentovali např. vesmírnou loď, jak se jeví hráči stojícímu v kupoli. Protože ji odsud nevidí přímo, jako v příkladu s ulicí a budovou, popisek se nesoustředí na vizuální vzhled, ale na to, kde loď je a že do ní lze vejít přechodovým tunelem. Samotné dveře lodi také nejsou vidět, proto je nepopisujeme, ale tunel vidět je a tak má i on svůj samostatný objekt, tentokrát příbuzný EntryPortal, který se liší jen v tom, že se chová jako něco, čím lze projít (místo do čeho lze vstoupit) a reaguje tedy na příkaz >projdi tunelem.

dome: Room 'Kupole' 'do kupole'
    "Kupole je jednou z mála <q>nadzemních</q> částí základny. Většina základny je
        ukrytá pod povrchem, ten funguje částečně jako ochrana před
        mikrometeority a kosmickým zářením. Tvar kupole zvenku skutečně
        připomíná polokouli, ideální tvar pro udržení tlaku uvnitř. Po obvodu
        je vstup do přechodové komory na východě, držák na skafandry a na
        sever vstup do přechodového tunelu, na jehož druhém konci je teď
        zakotvena kosmická loď. "

    north = shipDoorOutside
    up asExit(north)
    east = airlockInnerDoorOutside
    out asExit(east)
    down = ladderDown
;

+ shipDoorOutside: TravelWithMessage, IndirectLockable, Door -> shipDoor
    travelDesc = "Odrazil ses, vyšplhal do tunelu a s občasným odrazem
        vyskákal až do kosmické lodě. "
;

+ EntryPortal -> shipDoorOutside 'přechodový tunel' 'přechodový tunel' *2
    "Přechodový tunel je utěsněný, atmosférou nafouknutý tunel umožňující
        astronautům relativně bezpečný přechod z jednoho kosmického zařízení do
        jiného, aniž by museli používat skafandry. Teď zrovna je jedním koncem
        připevněný ke kabině lodi a druhým koncem ke kupoli základny. "
;

+ Enterable -> shipDoorOutside
    'vesmírná vesmírné kosmická kosmické loď/konzerva/plavidlo' 'vesmírná loď' *3
    "Loď je ukotvená k rampě a k její kabině vede přechodový tunel. Víc toho
        odsud vidět není. "

    dobjFor(Board) asDobjFor(Enter)
;

Všimněte si, jak objekty pro přechodový tunel a loď ukazují na dveře, které teprve jsou konektorem propojujícím kupoli s lokací lodě. Objekt lodi má také přesměrovanou akci Board, tedy nastoupení do lodi, aby se chovalo stejně, jako vstoupení.

Bariéry

Někdy může být žádoucí v určité situaci zabránit postavě, aby konektorem prošla. V Základně na asteroidu hlídal Boris kajuty a hráč se ho musel zbavit, pokud se chtěl po základně volně pohybovat. Bariéra se realizuje dvěma metodami. Metoda canTravelerPass(traveler) se naprogramuje tak, aby vracela logickou hodnotu, zda smí postava projít či ne. V ukázce si všimněte, že ostatní postavy mohou projít bez omezení, a pokud je cestovatelem hráč, smí projít, jen když je technik na záchodě nebo ve své kajutě. Druhou metodou je explainTravelBarrier(traveler), která má za úkol vysvětlit důvod, proč postava nemohla projít.

+ techniciansDoor: Door
    'jižní dveře (technikovy) (od) (do) (kajuty) (technika) dveře' 'dveře' *3
    "Každá kajuta je uzavřena lehkými vzduchotěsnými a zvukotěsnými dveřmi. Měly
        by vydržet mírné výkyvy tlaku na základně. Zevnitř se dají zajistit
        proti otevření, ale astronauti je obvykle nezamykají. "
   
    canTravelerPass(traveler)
    {
        return traveler != me
            || technician.isIn(techniciansRoom)
            || technician.isIn(toilet);
    }

    explainTravelBarrier(traveler)
    {
        "<.p>Strčil jsi do dveří, ale zastavil tě lehce podrážděný technikův
            hlas: <q>Mladej, jestli něco chceš od mě, tak pojď sem a nelez
            mi do kajuty!</q> ";
    }

    isPlural = true
    gcName = 'dveří, dveřím, dveře, dveřích, dveřmi'
    gcVocab = 'jižních jižním jižními dveří dveřím dveřích dveřmi dveří/dveřím/
        dveřích/dveřmi'
;

Chceme-li konektor čistě jen kvůli bariéře bez doprovodných zpráv a bez fyzického objektu v místnosti, můžeme použít třídu RoomConnector. Vytvoříme objekt této třídy a nastavíme vlastnosti room1 a room2, aby ukazovaly na patřičné místnosti a opět vytvoříme metody canTravelerPass a explainTravelBarrier.

Chceme-li aplikovat stejnou bariéru na více konektorů, nemusíme ony dvě zmíněné metody opisovat u každého z nich, ale můžeme je umístit do samostatného objektu třídy TravelBarrier a do jednotlivých konektorů pak společnou bariéru přiřadit ve vlastnosti travelBarrier. Tímto způsobem můžeme vytvořit i složitější bariéry, jako např. PushTravelBarrier, která nebrání normálnímu průchodu, ale jen protlačení nějakého objektu mezi místnostmi, či VehicleBarier, která brání průjezdu hráče v dopravním prostředku. Samozřejmě přesné podmínky průchodu se dají vždy upravit.

Atmosféra

Pro oživení hry, pro vyvolání dojmu, že se ve hře něco děje nezávisle na akcích hráče, že je plná lidí, kteří něco dělají, dějů, které probíhají atp. je možné použít atmosférické hlášky. Jsou to texty, které se přidávají do hry po každém příkazu hráče. Definujeme je tak, že do vlastnosti atmosphereList místnosti přiřadíme nějaký EventList. Na výběr máme hned několik druhů, které se liší svým chováním:

  • EventList bere jednotlivé hlášky ze seznamu v pořadí definice a když dorazí na konec, tak se vypne a přestane cokoliv dělat.
  • CyclicEventList také bere hlášky v pořadí a když jejich zásobu vyčerpá, pokračuje zase od začátku.
  • RandomEventList vybírá hlášku k zobrazení ze svého zásobníku zcela náhodně. Může se proto stát, že se stejná hláška náhodou zobrazí např. dvakrát po sobě a jiná se náhodou dlouho vynechá.
  • ShuffledEventList svůj seznam nejprve zamíchá a pak bere jednu hlášku podruhé. Po vyčerpání se opět zamíchá. V malém počtu opakování zaručuje rovnoměrnější rozložení.
  • StopEventList čerpá hlášky ze své zásoby postupně a po dosažení konce poslední hlášku opakuje stále dokola.

V ukázce níže je atmosféra podmíněná a zobrazuje se jen do té doby, než ve hře nastane čas oběda. Pokud bychom chtěli atmosféru vždy, vynecháme podmínku a napíšeme rovnou atmosphereList: ShuffledEventList { … }.

besideAirlock: Room 'Před základnou' 'před základnu'
    "Stojíš u kupole základny nedaleko přechodové komory. Na severu je na rampě
        ukotvená loď, na západě je otevřený vstup do přechodové komory. V dáli
        na východě leží překladiště kontejnerů.<.reveal hint-port-visited>
        <<if !gRevealed('lunch')>>Automaty vykládají kontejnery a postupně
        nahrazují přivezené těmi k odvezení. "

    atmosphereList = !gRevealed('lunch') ? automatasAtmosphere : nil
    automatasAtmosphere: ShuffledEventList
    {
        [
            'Jeden z automatů se zachytil rampy a vyjel k nákladnímu
                prostoru. ',
            'Dva automaty synchronizovaně přesouvají jeden z těžších
                kontejnerů. ',
            'Na povrch vykoukl další prázdný automat a vydal se k lodi. ',
            'Jeden z automatů do volného nákladního prostoru právě umístil
                kontejner s materiálem. ',
            'Automat zahájil pozvolné brždění s nákladem. ',
            'Automat s kontejnerem se pomalu rozjíždí od rampy. ',
            'Jeden z automatů se zachytil lodi, aby mohl vysunout prázdný
                kontejner. ',
            'Automat pozvolna změnil směr pryč od lodi. ',
            'Dva automaty se pomalu vyhýbají. ',
            'Automat synchronizovaně zmizel pod povrchem. '
        ]
        eventPercent = 50
        eventReduceAfter = 7
        eventReduceTo = 20
    }
;

Atmosférické hlášky dokáží skutečně hráče vtáhnout do děje, ale když jich je moc, tak se časem omrzí. Proto můžeme řídit jejich četnost vlastností eventPercent a volitelně po určitém počtu zobrazení eventReduceAfter nechat klesnout četnost na nižší hodnotu eventReduceTo. Hodnoty četnosti jsou zadané v procentech a vyjadřují pravděpodobnost, že dojde k zobrazení hlášky po příkazu hráče.

Základem EventListu je seznam hodnot, které se určitým systémem vybírají. Nemusejí to být ale jen řetězce v jednoduchých uvozovkách určené k zobrazení, do seznamu lze dát i ukazatel na funkci, která bude zavolána (bez parametrů), dokonce lze vnořit i jiný EventList atd. Vložením hodnoty nil dojde k vynechání položky a nic se v daný okamžik nestane.

Další díly seriálu

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

1 odpověď

  1. Adajahoda napsal:

    Chci se zeptat nepíše mi to háčky nad písmeny. Co se s tím dá dělat?

Napsat komentář

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