Projekt DSA se zrodil v roce 1998 v rámci cyklu seminářů z oblasti počítačové akustiky a fonetiky, zaměřených na pomoc tělesně postiženým, na FI MU v Brně. Základní myšlenka byla prostá: Počítačových her, důležité to složky softwarové výbavy, použitelných pro zrakově postižené, není mnoho. Velké firmy produkující hry se o tuto oblast trhu zrovna neperou, freewarová produkce nezávislých nadšenců rovněž není valná. Nezbývá tedy, než aby se do věci vložila akademická obec. Vzniklo tedy několik projektů k této problematice, některé zanikly, jiné se rozvíjejí.
DSA se zaměřil na pro tyto účely víc než vhodnou oblast - na textovky. Zdálo by se, že právě textovka, v podstatě jakákoli, je pro nevidomého člověka použitelná, prakticky bez potřeby nějakých úprav. Bohužel, opak je pravdou. V současné době se většina autorů textovek jaksi nemůže spokojit s holým textem, cítí potřebu opatřovat svoji hru obrázky, grafickými fonty, ovládáním myší, a podobně, čímž překračují možnosti screen readerů i schopnosti ovládání nevidomého úživatele.
Druhým problémem zejména českých textovek je jejich značná "nakolenovitost" (to je novotvar, znamená, že jsou dělány na koleně) a fakt, že vytvořit takový produkt vyžaduje určité programátorské schopnosti. S těmi se však bohužel málokdy pojí schopnosti spisovatelské, takže většina českých textovek (netvrdím, že všechny) je po literární a dramatické stránce chabá, neřkuli tragická.
Nabízí se řešení: editor na textovky, oproštěný od výše zmíněných vad (grafika a spol.), který by mohli používat lidé bez větších znalostí programování, zato s literárními schopnostmi. Přesně o to se pokouší projekt DSA.
Bude se jednat o klasické textové adventury. Hra tedy bude obsahovat určitý počet místností (oken), mezi nimiž se hráč bude pohybovat, předmětů, které bude lze sbírat, používat, kombinovat, a v neposlední řadě též postav, s nimiž bude moci komunikovat. Program je určen pro systém Windows (95 a výše), je ovládán čistě pomocí klávesnice a umožňuje pouze holý textový výstup, anebo, jak název naznačuje, třebaže to dosud nebylo zmíněno, výstup zvukový. Využít možnosti screen readerů, které každý nevidomý uživatel počítače používá, je pro tvůrce hry jistě pohodlné, avšak mnohem atraktivnějšího výsledku lze dosáhnout pomocí vlastních zvukových nahrávek, to jest ruchů a namluvených dialogů.
Formulář programu se skládá z jednoho dynamicky se měnícího menu (ListBox) a textového pole pro výpis textu (Memo). Menu obsahuje klasické textovkové příkazy typu Rozhlédni se, Prozkoumej, Jdi, Vezmi, Polož a Použij, umožňuje vybírat ze seznamů dostupných předmětů a cest, ukládat či načítat pozici a pracovat s nastavením programu.
Zatímco přehrávač DSA je určen hráčům a jeho ovládání je tedy naprosto intuitivní, editor scénářů již vyžaduje určité ne snad přímo programátorské znalosti, přinejmenším však jistou schopnost algoritmického uvažovaní. První krůčky v jejím osvojení je jistě možno provést právě v tomto editoru, nepůjde to však bez trochy práce.
Základním kamenem celého scénáře jsou dva druhy objektů - okna a předměty. Okna jsou místa, kam se hráč může dostat, vztahuje se k nim základní popis místa, seznam dostupných cest (do jiných oken) a seznam předmětů, které se v tom místě nacházejí. K předmětům se pak řadí vše, co se ve hře vyskytuje, tedy od nástrojů, které lze přenášet (kladivo), přes mohutné nepřenosné objekty (skála) či přímo abstraktní entity (nápad), až po postavy (duch Williama Shakespeara).
Jméno okna (předmětu) musí být v celém scénáři jedinečné a musí být alespoň dvouznakové. Pokud potřebujeme jednoznakové jméno nebo dva předměty téhož názvu (to se může často hodit), přidáme ke jménu text ve hranatých závorkách [,], coby komentář. Jméno také nesmí obsahovat mezeru. Tyto podmínky ošetřuje editor (kontroluje duplicitu a v případě potřeby přidá ke jménu index, a nahrazuje mezery znakem podtržítko _. Je třeba na to dát pozor při editování textových polí. Při zobrazení ve hře se pak text v hranatých závorkách vypouští a podtržítka nahrazují mezerami.
V jazyku se využívají konstanty A - aktuální okno, B - předchozí okno, C - inventář. Na začátku je A i B nastaveno na výchozí okno, podle vlastností scénáře (viz dále).
Proměnné jsou následující: P00 - P99 přepínače, C00 - C99 čítače, T00 - T19 timery a S00 - S19 řetězce (stringy). Přepínač nabývá hodnoty 0 nebo 1, čítač celočíselných hodnot z intervalu 0 - 255 (na začátku oba typy 0). String může obsahovat libovolný text, nedoporučuje se přesáhnout 255 znaků. Timery zatím nejsou otestovány, jejich použití se plánuje následovně: Na začátku je hodnota 0 a nemění se. Jakmile se nastaví (příkazem SET) na hodnotu větší než 0, bude se zvětšovat o 1 každou vteřinu. Timer může nabývat hodnoty nejvýše MaxInt (ve Windows95 kolem dvou miliard), při přetečení se nastaví na 1 (to by to ovšem někdo musel mít zapnuté pětašedesát let...).
Okna mají následující pole: 'Rozhlédni se', 'Při příchodu' a 'Při odchodu'. První obsahuje text, který se hráči vypíše příkazem rozhlédni se, zbývající dvě se používají zřídka, například chceme-li počítat (v čítači C00), kolikrát hráč navštívil dané okno, přidáme do pole 'Při příchodu' příkaz SET(C00,+1); Kromě toho je tu ještě řádek 'Kam', obsahující název okna ve 2. pádě, jako text pro příkaz Jdi. Podobně mají předměty řádek 'Co', pro název ve 4. pádě (sekyra - vzal jsi sekyru, apod.).
Předměty obsahují textová pole: 'Prozkoumej', 'Vezmi', 'Polož', 'Použij' a 'Promluv si', korespondující s odpovídajícími příkazy. Navíc jsou tu přepínače 'Lze vzít', 'Použít na' a 'Postava'. Je-li 'Lze vzít' true, potom se při příkazu vezmi nejprve předmět přidá do inventáře, a pak se provede pole 'Vezmi'. To se provádí i pokud je 'Lze vzít' false, ale předmět se nesebere. Podobné pořadí probíhá i u příkazu polož, položit lze ovšem každý předmět, nacházející se v inventáři. Pokud chceme zabránit položení nějakého předmětu, musíme přidat do pole 'Polož' příkazy REM(A,predmet); ADD(C,predmet); které předmět zase vezmou.
Přepínač 'Použít na' označuje předmět, jenž lze použít jen v kombinaci s jiným předmětem. Volání příkazu ve hře pak vypadá například takto: Hráč zadá "použij otvírák na konzervu", načež se interpretuje pole 'Použij' předmětu Otvírák a jako parametr %1 je nastavena Konzerva. Pole tedy může obsahovat řádky:
[%1=Konzerva] Otevřel jsi konzervu. Uvnitř bylo jídlo. EXCH(Konzerva,Jídlo); [%1=Plechovka[1]] Vypáčil jsi víčko plechovky. EXCH(Plechovka[1],Plechvka[2]); ADD(A,Víčko);Pak se provede pouze první z nich.
Přepínač 'Postava' může označovat předměty, s nimiž lze mluvit. Pokud má scénář ve vlastnostech nastaveno 'Lze mluvit s předměty' na false, nabídnou se v menu 'Promluv si' pouze postavy (předměty s 'Postava' nastaveným na true).
Vlastnosti scénáře obsahují nastavení platná pro celý scénář. Zejména je to 'Úvodní text', čili intro, které se provede na začátku hry. Pole 'Začít na pozici' určuje okno, v němž hra začíná, 'Předměty do začátku' určují počáteční stav inventáře. 'Maximum předmětů' udává maximální počet předmětů, které se vejdou do inventáře. Po jejich dovršení se nedají další předměty sbírat (při pokusu o to se pouze provede pole 'Vezmi'). Dovršení maxima se nekontroluje při provedení příkazu ADD(C,předmět);, takovým způsobem je možno maximum přesáhnout. Ošetřit se to dá pomocí podmínky FULL. Pozor - nastavení maxima na hodnotu 0 znamená, že se nedá vzít ani jeden předmět. Chcete-li mohutnost inventáře neomezovat, nastavte maximum na 99 nebo víc. Pak se jeho hodnota ignoruje.
Každý řádek může obsahovat žádný nebo více příkazů. Příkaz musí být oddělen od textu (mezerou nebo koncem řádku), a musí být zakončen středníkem. Text, který to nesplňuje, stejně jako nerozpoznaný příkaz, se při hře vypíše. Parametry příkazu se zadávají v závorkách, oddělují se čárkou a nesmí mezi nimi být mezera. To platí zejména pro názvy oken či předmětů, zadáváte-li je z klávesnice, dejte pozor na nahrazení mezer podtržítky.
Řádek může obsahovat nejvýše jedno podmínění. To se vztahuje pro celý řádek a musí být uvedeno na začátku řádku. Podmínění je ohraničeno hranatými závorkami [,] a může obsahovat jednu nebo více podmínek, oddělených středníkem, v takovém případě se bere jejich konjunkce. Pokud podmínce bezprostředně předchází vykřičník (!), bere se negace podmínky, stejně lze negovat celé podmínění řádku vykřičníkem bezprostředně před úvodní závorkou ([).
Začíná-li řádek znakem ampressand (&), ignoruje se.
Při zpracování pole se nejprve vyhodnotí všechny podmínky, a teprve potom se provádějí příkazy. Z toho plyne, že pokud nějaký příkaz změní hodnotu čítače a následující podmínka ho testuje, tento test dopadne podle původní hodnoty čítače. Např. řádky
[P01=0] Rozsvítils světlo. SET(P01,1); [P01=1] Zhasnul jsi světlo. SET(P01,0);Budou fungvat správně.
Jedinou výjimkou z tohoto pravidla je příkaz READ. Musí být volán na zvláštním řádku (může být podmíněn) a následující řádky se provedou až poté, co uživatel zadá řetězec z klávesnice. Při testování následujících podmínek bude mít čtený string zadanou hodnotu. Např.:
Zadej heslo: READ(S00); [S00=12345] Otevřel jsi trezor. EXCH(Trezor[1],Trezor[2]); ![S00=12345] Trezor se neotevřel.Ozvučení scénáře se provádí vkládáním zvuků. Zvuk je ve scénáři reprezentován svým identifikátorem, tedy jedinečným jménem, které se váže ke jménu souboru na disku. Zvuk je definován záznamem ve tvaru identifikátor=text(soubor):priorita. Vkládání řeší příkaz PLAY(identifikátor), který zařadí daný zvuk, pokud existuje, do fronty. Přehráván může být maximálně jeden zvuk, odstatní čekají ve frontě v pořadí, v jakém byly volány, než aktivní zvuk skončí nebo je přerušen příkazem STOP. Příkaz STOPALL vyprázdní frontu. Priorita zvuku je číslo mezi 0 a 9, zatím nemá žádný význam.
V editoru se zvuky snadno zadávají (v záložce zvuky), zadanému souboru je přiřazena relativní cesta vzhledem k aktuálnímu adresáři. Při hře se tato cesta bude uvažovat vzhledem k adresáři, v němž se nachází scénář.
A=X | Aktuální okno je X |
B=X | Předchozí okno je X |
Cmm=n | Čítač mm je nastaven na hodnotu n (mm:0..99, n:0..255) |
Cmm<n | Čítač mm je menší než n |
Cmm>n | Čítač mm je větší než n |
Cmmxn | Čítač mm je různý od n (podobně pro timery) |
Pmm=b | Přepínač mm je nastaven na hodnotu b (b:0..1) (podobně pro stringy) |
IN(X,Y) | Předmět X se nachází v okně Y |
%p=Q | Parametr p je nastaven na Q (p:1..3, Q libovolné) zatím využit pouze %1 pro označení předmětu, na nějž je aktuální předmět použit |
FIRST | Poprvé provedená akce (rozhlédnutí, prozkoumání...) |
FULL | Víc nepobereš (počet předmětů=maximum) |
LAST | Stejná podmínka jako na předešlém řádku |
ELSE | Žádná z podmínek neplatí (neprovedl se žádný podmíněný řádek) |
ADD(X,Y); | Přidej předmět Y do okna X |
REM(X,Y); | Zruš předmět Y v okně X. Pokud tam není, neprovede se nic. |
EXCH(X,Y); | Nahradí předmět X předmětem Y. Pouze pokud se X nachází v aktuálním okně nebo inventáři. |
ADDCS(X,Y); | Přidá do okna X cestu do okna Y |
REMCS(X,Y); | Odebere z okna X cestu do okna Y. Pokud tam není, neprovede nic. |
SET(Pmm,n); | Nastaví přepínač mm na hodnotu n. Obdobně pro čítače, tam lze za n použít i +n nebo -n pro příčtení (odečtení) hodnoty. |
GO(X); | Nastaví aktuální okno na X |
REMALL(X); | Zruší všechny předměty v okně. Nečastější použití pro inventář ve chvíli, kdy má hráč přijít o všechny předměty. |
TRANS(X,Y); | Přesune všechny předměty z okna X do okna Y. Je-li Y=C, přidají se do inventáře jen předměty, které lze vzít (z X se odstraní všechny) |
WAIT; | Čeká na zmáčnutí klávesy. |
READ(Smm); | Čte string. Tento příkaz musí být na samostatném řádku. |
PLAY(zvuk); | Vloží zvuk do fronty přehrávaných zvuků |
STOP; | Zastaví přehrávání aktuálního zvuku. |
STOPALL; | Zastaví přehrávání aktuálního zvuku a vyprázdní frontu. |
CLEAR; | Nastaví všechny přepínače a čítače na 0. Vhodné při přechodu do další části hry bez možnosti návratu. Na timery a stringy nemá vliv. |
Předchozí popis byl značně stručný a těžko lze očekávát, že by z něj někdo vše pochopil, to uznávám. Snad se mi časem podaří sepsat trochu obsáhlejší manuál, zatím se pokusím osvětlit některé nejasnosti na příkladu.
Dejme tomu, že scénář obsahuje okna: Ulice, Dvůr a Garáž a předměty Auto, Lavička, Klíčky, Pes a Kočka s následujícím textem:
Ulice
rozhlédni se: Prázdná ulice, stojí tu jediné auto.
[FIRST]Vedle sis všiml vchodu do dvora. ADDCS(Ulice,Dvůr);
při příchodu: [IN(A,Pes);P01=0] Z druhého konce ulice přiběhl velký
černý pes. SET(P01,1);
při odchodu:
cesty:
předměty: Auto
Dvůr
rozhlédni se: Dvorek jako malovaný. Je tu lavička.
při příchodu: PLAY(ptacci);
při odchodu:
cesty: Ulice
předměty: Lavička
Garáž
rozhlédni se: Podzemní garáž. Tady to zatím končí.
při příchodu: [FIRST]CLEAR;
při odchodu:
cesty:
předměty: Auto
Auto
prozkoumej: Daewoo kabriolet, jasně červený a skoro nový, radost
pohledět.
vezmi: Trochu těžké, nemyslíš?
polož:
použij: [!IN(C,Klíčky)] Dovnitř se dostaneš snadno, ale bez klíčků
se ti nedaří nastartovat.
[A=Ulice;IN(C,Klíčky)] Dojel jsi do jedné známé garáže. GO(Garáž);
[A=Garáž;IN(C,Klíčky)] Nemáš, kam bys jel.
promluv si:
lze vzít: false
požít na: false
postava: false
Lavička
prozkoumej: Dřevěná a poměrně zachovalá.
[FIRST] Rozvaluje se na ní kočka. ADD(A,Kočka);
vezmi:
polož:
použij: [P00=0] Posadil ses na lavičku. Je to příjemné. SET(P00,1);
[P00=1] Odpočatý jsi zase vstal. SET(P00,0);
promluv si:
lze vzít: false
požít na: false
postava: false
Klíčky
prozkoumej: Evidentně klíčky od auta.
vezmi:
polož:
použij: [%1=Auto] Zkusil jsi nastartovat. Auto chytá skvěle. PLAY(motor);
promluv si:
lze vzít: true
požít na: true
postava: false
Kočka
prozkoumej: Je mourovatá a snad dobře naladěná.
vezmi: Jen ses jí dotkl, pěkně tě škrábla. SET(C00,+1);
[C00=9] Umíráš na otravu krve. LOSE;
polož:
použij:
promluv si: "Nazdar, číčo," oslovíš kočku.
"Zdravíčko," odvětí.
[FIRST] "Nevidělas tu někde klíčky od toho pěknýho fára?"
[FIRST] "Jasně, štípla jsem je pánovi dnes ráno, takže musel jít
pěšky, a jelikož
[FIRST]je poseroutka, vzal si psa s sebou. Takže teď mám dům pro
sebe. Jestli je
[FIRST]chceš, klidně si je vem." Podá ti klíčky. ADD(C,Klíčky);
ADD(Ulice,Pes);
lze vzít: false
požít na: false
postava: true
Pes
prozkoumej: Dobrman, vypadá poměrně nakrknutě.
vezmi: [FIRST] Na tvém místě bych to neriskoval.
![FIRST] Varoval jsem tě. Pes tě zakousl. LOSE;
polož:
použij:
promluv si: "Neviděl jsi tu takovou malou strakatou zlodějku?"
vyhrkne na tebe pes, než stačíš něco říct.
"Jasně," odvětíš, "sedí támhle na lavičce."
"Až já ji dostanu..." zavrčí pes a odběhne. REM(A,Pes); REM(Dvůr,Kočka);
lze vzít: false
požít na: false
postava: true
Nerad bych v někom vzbudil dojem, že s DSA editorem stačí sednout a za hodinku dvě je hra hotová. Předchozí příklad mi nějaký čásek zabral a přitom je to jen kratičká ukázečka. Asi není těžké pochopit, co přesně to dělá, nicméně je to demonstrační příklad, proto jej vysvětlím řádek po řádku:
Tak tedy Ulice: Není tu žádná cesta a jen jediný předmět - auto. Teprve až se hráč poprvé rozhlédne, přibude tu cesta do dvora. Musí tam být samozřejmě podmínka FIRST, aby cesta nepřibývala znovu a znovu při každém rozhlédnutí. V průběhu hry může do okna přibýt předmět pes. Až se to stane a hráč sem vejde, vypíše se mu informace o tom, že tu pes je. Přepínač P01 pak slouží k tomu, aby se to vypsalo jen jednou - nelze použít podmínku FIRST, protože při prvním příchodu tam pes ještě nemusí být.
Dvůr: Pokaždé když tam hráč vejde, přehraje se zvuk ptacci, patrně cvrlikání ptáčků, že.
Garáž: Zde začíná další fáze hry, proto se přepínače a čítače mohou vynulovat, ovšem jen při prvním příchodu, to je snad jasné.
Auto: Pokud hráč nemá v inventáři klíčky, daleko nedojede. Pokud ano a nachází se na ulici, pojede do garáže. Pokud už je v garáži, nepojede nikam. Tak už to v životě chodí. Auto přirozeně nelze vzít, dá se použít jen přímo a není to postava.
Lavička: Když si ji hráč poprvé prohlédne, objeví kočku. Může se na ni posadit (na lavičku), nebo z ní vstát, podle přepínače P00.
Klíčky: Dají se vzít a použít v kombinaci s jiným předmětem, moc si s nimi nepokecáš. Když je použiješ na auto, jen si tak pro radost nastartuješ (přehraje se zvuk motoru), k jízdě slouží příkaz použij auto. Na to už hráč musí přijít sám.
Kočka: Když se ji hráč pokusí vzít, poškrábe ho. Pokud je to masochista a udělá to desetkrát, dostane otravu krve a hra končí. Při prvním rozhovoru vydyndá klíče od auta a v té chvíli se na scéně (na ulici) objevuje pes. Všimněte si, že podmínka FIRST musí být na každém řádku znovu. Zde je jich tolik kvůli zalamování řádků na obrazovku, v editoru lze celou koččinu odpověď vtěsnat na jeden řádek, pokud se vám nechce podmínku pořád opisovat. Jiným řešením, zvláště u dlouhých podmínek, je použít podmínku LAST, která znamená totéž co podmínka na předchozím řádku. Lze ji použít i v konjunkci s dalšími podmínkami. Kočka se vzít nedá, víme proč, použít taky ne, ale svým způsobem je to postava.
Pes: Ani jeho není radno brát, poprvé ještě hráče varujeme, ale pokud si nedá říct, má smůlu. Při rozhovoru se ukáže zkažený charakter hráče, logicky pak pes i kočka zmizí.
Teď už je doufám vše jasné, pokud ještě stále něco nechápete, napište mi.
Veškeré dotazy, návrhy, připomínky či výhružky posílejte prosím na adresu autora: Ondřej S. Nečas