A szavaktól a mondatok felé

A kalandjátékok utasításaira általában jellemző, hogy az alany hiányzik belőlük ill. rejtett (első vagy második személyű), s csaknem kivétel nélkül valamilyen igei állítmányra épülnek, amihez gyakran különféle tárgyak, jelzők és határozók csatlakozhatnak. Utóbbiak önmagukban egyszerűek, egy-két szóból állanak, s ami még nagyon jelentős egyszerűsítés, hogy alá-, fölérendelt tagmondatok sosem fordulhatnak elő. (Legalábbis ezidáig nem volt rá még példa…) Tipikusan egyszerű parancs pl. az alábbi: VEDD FEL A KULCSOT. Ebben föllelhető mindkét alapvető szófaj: az ige és a főnév – tulajdonképpen az összes többi szófaj fölfogható úgy is, mintha ezek speciális esetei lennének. Az ige fontos tartozéka (vagy inkább: része) még az igekötő is, hiszen ha azt mondjuk, hogy VEDD FEL, VEDD LE vagy VEDD MEG, azok teljesen eltérő cselekvésre utalnak. E kettő együttesen dönti el, hogy mit akarunk csinálni, a főnevek és társaik pedig a cselekvésünk célját határozzák meg, azáltal, hogy az elérhető tárgyak és szereplők közül konkrétan kijelölnek valamit. Ez nem mindig egyértelmű: egyrészt létezhet a játékban több hasonló nevű tárgy is, másrészt használhatunk különféle gyűjtőneveket. Előbbi esetre példa lehet az, ha többféle különböző kulcs van: ilyenkor mindegyiknek van valamilyen sajátos jelzője, mely megkülönbözteti az összes többitől (pl. „kis kulcs” vagy „nagy kulcs” stb.); a főnevek elé melléknevek járulnak (VEDD FEL A NAGY KULCSOT). Gyűjtőnév esetén pedig az illető szó ugyan pontosan megjelöli a tárgyat, ám egyszerre akár többet is – legjobb példa erre a MINDEN szónak az alkalmazása: egy VEGYÉL FEL MINDENT utasítás egyszerre vonatkozik a közelünkben látható valamennyi tárgyra. Melléknevek szintjén is elképzelhető hasonló, pl. így: VEDD FEL AZ ÖSSZES KULCSOT. (Hogy miért is célszerű a melléknevet is speciális főnévként nyilvántartani, az kitűnik abból, hogy alkalomadtán ezek is a főnevekhez hasonlóan ragozódhatnak. Egy jólnevelt kalandjáték ugyanis, ha nem egészen biztos a dolgában, további kérdéseket tesz fel: megkérdezi tőlünk, hogy melyik kulcsot szándékozunk fölvenni. Erre mi felelhetjük azt is, hogy a NAGY KULCSOT – vagy egyszerűen ennyit: NAGYOT. A melléknév ilyenkor kifejezetten úgy viselkedik, mintha főnév lenne; fordított esetben pedig egyes főnevek is állhatnak a melléknévi jelzők helyén.) Mivel igencsak ritka eset (úgy értem, egy kalandjátékban…) az, hogy teljesen azonos tárgyakból legyen több példány ugyanazon a helyen, s ráadásul ezek közül többre, de nem valamennyire akarunk hivatkozni egyidejűleg, ezért számnevek csak elvétve fordulnak elő; ilyenkor, mint sejthető, a melléknévhez hasonlóak, csak funkciójuk más. Ugyancsak fehér holló egy másikfajta jelzős szerkezet, nevezetesen a birtokos jelző: egyfelől erre is csak viszonylag ritkán kerül szükség, másfelől meg akkor is kiválthatjuk más, egyszerűbb jelzőkkel a szerepét. Pl. ha az iménti nagy kulcs egy őr kezében van: egy VEDD EL AZ ŐR KULCSÁT helyett a FOGD A NAGY KULCSOT utasítás sokkal egyszerűbb. Jóllehet ezek kezelése eléggé bonyolult eljárást igényel, mindenesetre sokat emel egy játék színvonalán, ha – mint értékes egzotikumot – ilyesmit is beleépítünk. Annál nagyobb igény lehet ezzel szemben (márminthogy a játékosok oldaláról) egy másik, teljes főnévi értékű szófajra, a névmásra: ha leírjuk, hogy BESZÉLGESS VELE vagy NÉZZ , miközben a legutóbbi parancsunk egy KÖSZÖNJ A MADÁRIJESZTŐNEK volt, ez kétségkívül azt jelenti, hogy ezúttal is a madárijesztőre gondolunk – az utolsóként előfordult főnevet helyettesíthetjük valamilyen névmással. Érthetetlen, hogy ezt is csak alig néhány program ismeri, amikor pedig a megvalósítása egyszerű (hisz’ mindössze egy szócseréről, behelyettesítésről van szó), és igen nagy könnyebbség, ha nem kell a hosszadalmas MADÁRIJESZTŐ szót mindig újra és újra bepötyögni, hanem helyette ezt a „kézreálló” pár betűt…

A határozók már nem önálló szófajok, hanem csak mondattani egységek – lényegében a főnevek eltérő ragozású alakjai. Miután a szórend szabad, és más támpontunk nincsen, egyedül a ragozásuk alapján tudjuk csoportosítani a különféle kifejezéseket. Túlságosan körülményes és fölösleges is volna azonban valamennyi raghoz külön határozót rendelni, így legcélravezetőbb öt csoportba sorolni őket (az egy csoportba tartozó ragok nemigen szoktak előfordulni egy parancsban együtt, és körülbelül hasonló dolgot jelentenek, így nyugodtan tekinthetjük azonosnak őket): 1.) tárgy: -t raggal vagy rag nélkül; 2.) helyhatározó: -n, -ban, -nál, -ról, -ból, -tól; 3.) célhatározó: -ra, -ba, -nak, -hoz; 4.) eszközhatározó: -val; 5.) egyéb: -ért, -ig… stb. Pl. az ADJ PÉNZT A KOLDUSNAK utasítás három mondatelemet tartalmaz: egy igét, egy tárgyat és egy célhatározót (az, hogy ezt a nyelvtanban részeshatározónak nevezik, ne zavarjon túlzottan bennünket…). A ragokon túl használhatunk névutókat is a főnév jelentésének módosítására, így helyhatározó lehet az is, hogy ASZTAL ALATT, vagy a KULCCSAL helyett eszközhatározó, hogy KULCS RÉVÉN vagy KULCS SEGÍTSÉGÉVEL stb. stb.

Összefoglalva tehát, minden egyes begépelt parancs lényegében a következő részekből tevődik össze: az ige (a beleértett igekötőjével együtt), valamint a felsorolt ötféle tárgy ill. határozó. A parancsot akár fölfoghatjuk úgy is, mint egy rekordot, aminek ez a hatféle mezője van. A programon belül persze a szavak nem szövegként jelennek meg, hanem minden egyes dolgot valamilyen sorszám azonosít. Pl. ha a „kinyitni” ige a 13-as sorszámot kapta az előzetes tervezés során, akkor ez azt jelenti, hogy az ige változójába egy 13-as szám kerül. Amelyik fajta eleme hiányzik a mondatnak, az természetesen a 0-ás értéket kapja. Ez gyanúsan egyszerűnek látszik, holott valójában egyáltalán nem az: ugyanis ez a végeredményül kapott egyszerűség a valóságban egy hosszú és bonyolult értelmezési folyamatot takar, melynek folyamán a különféle szókapcsolatok és más szerkezetek fokozatosan a lehető legtömörebb viszonyokká bomlanak le. Ahhoz, hogy ez megvalósuljon, tucatnyi eltérő algoritmust kell egymás után lefuttatni, amelyek mindegyikének feladata a megfelelő szavak vagy szópárok cseréje, helyettesítése valamilyen másik, egyszerűbb szóval. Ezek a cserék táblázatokban való keresések útján történnek. Efféle algoritmus lehet például az, amelyik az igék és igekötők különálló párosát egyetlen összetett igére cseréli ki (a NYISD és a KI szavakat törli, és helyükre egy KINYITNI szót ír – ha pedig nemlétező párosítást talál, pl. azt írtuk, hogy NYISD ÖSSZE, ami nincs benne a táblázatban, akkor hibát jelez, és az ige értelmezhetetlen). Vagy egy másik, mely a névmás helyére elegánsan becsempészi az utolsóként alkalmazott főnevet. Egy olyan, mely a „melléknév + főnév” szókapcsolatot egyetlen új főnévvel helyettesíti be (a NAGY és a KULCS szavak sorszámait kiiktatva, helyettük egy másik, a NAGY KULCS szó sorszámát illeszti a mondatba). És így tovább; minél több ilyen funkcióval ellátjuk, annál intelligensebb lesz a programunk. (És annál nehezebb lesz megírni…) Természetesen az sem mindegy, milyen sorrendben hajtjuk végre ezeket az egyes szabályokat a mondatban. Pl. ha azt találjuk leírni, hogy NAGYOT, akkor az először is felbomlik a – kissé idegenszerűen hangzó – NAGY AZT szókapcsolatra, majd az AZ helyére bekerül a KULCS főnév (mint névmás-helyettesítés!), s csupán ezután lehet belőle NAGY KULCSOT. Egy szöveges kalandjáték értelmező programját elkészíteni körülbelül hasonló feladat, mintha mondjuk egy PROLOG fordítóprogramot óhajtanánk írni…

A parancs és a mondat kifejezéseket az eddigiekben egy kissé összekeverten használtuk, úgyhogy lassanként ideje lenne szétválasztanunk őket egymástól: míg egy parancs mindig egyetlen meghatározott cselekvésre utal, vagyis lényegében tagmondat (a fentiekben hozott példák mind parancsok voltak), addig egy mondat nyugodtan akár több parancsból is állhat. (Már amelyik program hajlandó ezt tudomásul venni…) Vagy az ellenkező irányból megközelítve a dolgot: egy mondat az a szövegmennyiség, amit a játékos egy szuszra begépel a bevitel során, s a parancs ennek egy-egy önállóan végrehajtható része. A mondaton belüli parancsok elválasztására írásjeleket (pont, vessző és társaik), valamint az ÉS szócskát vagy annak szinonimáit (MAJD, TOVÁBBÁ, VALAMINT… stb.) használjuk. A játék a mondatban lépésről lépésre halad előre; mihelyt egy parancsot végrehajtott, utána kezdi el értelmezni a következőt. Pl. egy tipikus összetett mondat így hangzik: VEDD FEL A KULCSOT ÉS NYISD KI VELE AZ AJTÓT. Ebben az esetben a két tagmondatot akár egy-egy külön mondatként is le lehetne írni, de előfordul olyan is, hogy szorosabb összefüggés kapcsolja őket össze, miáltal szétválaszthatatlanok lesznek – ez akkor állhat fenn, mikor a második parancsból kihagyunk valamit, amit már tartalmaz az első. Pl.: GYÚJTSD MEG A GYERTYÁT ÉS A MÉCSEST. Itt a második parancsból kimaradt az ige. Ahhoz, hogy ezt értelmezni tudjuk, egy aprócska trükköt kell alkalmazni a programban, nevezetesen amíg a mondatnak nincs vége, addig az aktuális parancs változóit sohasem töröljük, hanem csak az újabbik parancs szavai mindig felülírják a régit – így tehát a teljes első parancs változatlanul megmarad, mindössze a MÉCSES, mint tárgy fogja felülírni az előző tárgyat, a GYERTYÁ-t. Ezáltal egyetlen állítmány mögé tetszőleges számú tárgyat fölsorakoztathatunk. Sokkalta nehezebb volna – éppenhogy a lépésenkénti végrehajtás miatt! – ugyanezt az ellenkező irányból is megcsinálni, valahogy ilyképpen: NYISD KI ÉS CSUKD BE AZ AJTÓT. Ebben az esetben ugyanis a programnak szinte „előre kéne gondolkodnia”: amikor odáig jut, hogy NYISD KI, még fogalma sincsen róla, hogy mire is vonatkozik ez a dolog – jóllehet a keresett főnév benne van a mondatban, csak jóval később volna esélye megtalálni azt. Az eredmény: a számítógép megkérdi, hogy „Mit akarsz kinyitni?”. Ennek feloldására be lehetne vezetni egy ún. öröklési rendszert, ami abból állna, hogy még mielőtt hozzálátna a legelső lépés végrehajtásához, a program végigértelmezné a teljes mondatot, és mindegyik tagmondat állapotát eltárolná valahol, egy rekordokból álló láncban úgy, hogy az aktuális rekord mindig örökölné – az iméntiekben leírt módon – az előzőnek azt a részét, ami nem változott. Azután ugyanezt végigcsinálná fordított irányban, az utolsótól az első felé haladva is – és ami valahonnan hiányzik, azt mindig a másikból vett megfelelő részekkel pótolná és kiegészítené benne ekkor is. Eközben az első parancsba, ahonnan hiányzik a tárgy, beíródna az utána következő tagmondat tárgya (ami esetleg szintén a következőből örökölte azt, és így tovább). Csupán ezt követően hajtódnának végre a parancsok.

Amivel aztán el is érkeztünk az értelmezés következő állomásához: mi történjék, amikor valamilyen szó végképp hiányzik a mondatból. Erre több megoldás is kínálkozik. Lehet egyszerűen a felhasználó képébe vágni, hogy márpedig ez nem egy értelmes mondat, és legközelebb szíveskedjék jobban megválogatni a szavait… Ennél valamivel udvariasabb (és intelligensebb) megoldás, amikor a homályos részekre vonatkozó kérdéseket teszünk fel, és további kiegészítéseket várunk. Pl. ha csak annyit kaptunk parancsként, hogy NYISD, akkor feltesszük neki a következő kérdést: „Mit akarsz kinyitni?” – ami után következő bevitelként kétféle felelet várható. A játékos vagy begépel egy teljesen új mondatot, nagylelkűen elfelejtve az előzőt – vagy pedig a kérdésünkre válaszol, és mindössze a hiányzó tárgyat adja meg. Hogyan készítsük fel a játékot a helyes reagálásra mindkét esetben, amikor e kettőt tulajdonképpen nem is igazán lehet megkülönböztetni egymástól? Hát úgy, hogy nem is különböztetjük őket meg. Az előbb láttuk, hogy az esetleg összefüggő részmondatok miatt a parancsok változóit mindig a mondat végén töröljük, amikor egy új mondatba kezdünk. Egyszerűen annyit kell tennünk, hogy mikor valamilyen kérdést intézünk a kalandorhoz, olyankor az újabb bevitel megkezdése előtt nem töröljük ezeket a változókat, azaz nyitva hagyjuk a mondatot – akármit begépel a tisztelt felhasználó, az a jelenleg meglévő parancsot fogja felülírni, éppúgy, mintha az a következő parancs volna. Teljesen mindegy, hogy töredékeket kapunk-e tőle, vagy egy új mondatba kezd. Így akár több, eltérő tartalmú kérdés is követheti egymást, és mégis valamennyi válasz ugyanazt a parancsot fogja fokozatosan gazdagítani – szabályos kis párbeszéd alakulhat ki a program és a felhasználója között. Komolyabb probléma akkor adódik, ha már bevezettük az előzőkben vázolt örökléses rendszert – ilyenkor ugyanis a kérdés feltevése előtt meg kell jegyezünk az egész mondat állapotát, majd a kiegészítés megtétele után ismételten végigfuttatni rajta oda-vissza a parancsokat összefűző eljárást.

Harmadik, és egyben legintelligensebb megoldása a hiányos mondatok esetének, ha a program maga automatikusan megkísérel behelyettesíteni a kimaradt részek helyére valamit, és ha csak ez végképp nem sikerül neki, akkor teszi fel a kérdést. Pl. a NYISD megadása esetén sorjában végignézi az összes elérhető tárgyat, s csak ha nincs közöttük egyetlen olyan sem, ami nyitható, akkor kérdi meg a kezelőjét, hogy voltaképpen mire is gondolt. (Vagy ha többet talált, akkor azt, hogy melyiket.) Hasonlít ez némiképpen a gyűjtőnevek kezeléséhez. Leggyakoribb gyűjtőnév a korábban már megemlített MINDEN szó: ilyenkor a parancs végrehajtását egy külső ciklusba kell ágyazni – sorban egymás után behelyettesíteni a kívánt szó helyére az összes elérhető tárgynevet, és mindegyikkel egyesével végrehajtani ugyanazt a parancsot. (Érdemes elgondolkodni rajta, hogy mi történik akkor, ha netán a huncut játékos egyazon parancson belül többször is alkalmazott valamilyen gyűjtőnevet. Pl. így: MUTASS MEG MINDENT MINDENKINEK. Ez az, ami a programozó idegeit végképp próbára teszi…)


Következő: „Helyiségek összefüggő labirintusa”

 

 

A kalandjáték fogalmának tisztázása

Kalandjáték és mitológia

A számítógép beszélni tanul

A szavaktól a mondatok felé

Helyiségek összefüggő labirintusa

Barangolás a térképen

Lakberendezővé változunk

Hogyan találjunk meg valamit

„Sokasodjatok és növekedjetek”

Az idő kerekéhez kötve

Néhány jótanács és további lehetőségek

A program működésének leírása

Használati útmutató