advgame.md 14 KB

Kalandjáték

Az advcomp fordítóval lehet AdvGame JSON forrásfájlokat MEG-4 Kalandjátékokká konvertálni. Ezek klasszikus szöveges játékok (hívják őket Interaktív Fikciónak is), ahol a játékos mondatokat gépel be a játékban történő haladáshoz. Ezeket a mondatokat aztán igére és főnev(ek)re bontja, amikre keres. Ha talál szkriptet az aktuális ige és főnév kombinációhoz, akkor azt lefuttatja.

NOTE: Az advcomp fordító képes kattintós felületű kalandjátékokat is fordítani pontosan ugyanazokból a JSON fájlokból. Habár a MEG-4 be tudja tölteni ezeket is, de közben sima szöveges kalandjátékká konvertálja őket, a point'n'click játékmód csak az advgame programmal elérhető.

Korlátok:

  • igék: 32 különböző akció, egyenként 15 bájt, 8 szinonímával (max. 1536 bájt összesen)
  • főnevek: 255 különböző tárgy, egyenként 15 bájt (max. 1536 bájt összesen)
  • üzenetek: 32 különböző sztring szobánként, egyenként 255 bájt (max. 2048 bájt nyelvenként)
  • szkriptek: 1 globális, 63 közös minden szobában, és 63 különböző szobánként
  • utasítások: 21 mnemonik 8 kondícióval, elágazásmentes kivitelezés, 61 utasítás szkriptenként
  • képek: alapból 1 szobánként, de használható egyéni implementáció
  • szobák: 254 összesen, melyek 6 különböző irányban összeköthetőek

Játék állapot

A kalandjáték aktuális állapota egy 256 elemű bájttömben tárolódik. A legelső bájt az aktuális szoba száma, az utolsó 32 bájt a leltárnak van fenntartva, a többi szabadon felhasználható. Ezek lehetnek jelzőbitek, számlálók, bármi. A [szkriptek] ezen a 256 bájtnyi memórián végeznek műveleteket és ez az állapot elmenthető és visszatölthető játékmentésként.

Felső szint

A forrásfájl legfelső szintjén lennie kell egy "AdvGame" JSON struktúrának, ami egyben a fájl azonosítója is. A mezői:

  • sprites: sztring, 256 x 256 pixeles PNG szprájtlap elérési útja, a felső 32 sora üres
  • music: sztringtömb, Amiga MOD (.mod) vagy MIDI (.mid) zenefájlok elérési útjai (8 elemű)
  • sounds: sztringtömb, RIFF WAVE (.wav) formátumú fájlok elérési útjai (31 elemű)
  • setup: számtömb, a játék induló állapota (256 elemű, mind 0 és 255 közötti, az első szám az induló szoba)
  • status: számtömb, melyik játékállapotokat írja ki a státusz (2 elemig, többért lásd custom)
  • vars: sztringtömb, a állapot indexek aliaszai, ún. "változók" (csak a JSON-ben használt)
  • rooms: sztringtömb, a szobaszámok aliaszai (csak a JSON-ben használt)
  • verbs: sztringtömb, a verb1, verb2, verb3 stb. aliaszai (csak a JSON-ben használt)
  • nouns: sztringtömb, a főnevek aliaszai (csak a JSON-ben használt)
  • colors: 5 elemű számtömb, intró háttér- és betű-, szoba háttér- és betű-, valamint promptszín
  • pos: szám, szöveg pozíciója pixelekben a képernyő tetejétől számítva
  • custom: sztringtömb, plusz kusztom C kód a felhasználói felület megjelenítésére (első az intróé, a második a szobák kódja)
  • logic: sztringtömb, általános játék logika szkript, ami mindig minden parancs előtt lefut
  • config0: struktúra, fő játékkonfiguráció
  • config1: struktúra, alternatív játékkonfiguráció (többnyelvűség támogatás)
  • szám/"rooms" aliasz: struktúra, szobadefiníciók.

Alapesetben feltételezi, hogy a szprájtlap ketté van vágva: a felső 128 sor szobánként cserélődik, az alsó 128 sor állandó (felhasználói felület elemei, ikonok stb. ez utóbbiak töltődnek be a sprites-ról). Ha a textpos be van állítva, akkor az intrónál és a szobáknál is textpos (de legfeljebb 96) sor a szprájtlap 32. sorától kezdődően megjelenik a szöveg fölött a képernyőn. A kusztom felület C kóddal pedig akármilyen és akármennyi szprájt kirakható e helyett.

Konfiguráció

Van egy fő- és egy alternatív konfiguráció a többnyelvűség támogatásához. A mezőik:

  • lang: sztring, kétbetűs nyelvkkód
  • text: sztring, intró szövege (429 bájtig)
  • answers: 4 elemű sztringtömb, üzenetek (egyenként 63 bájtig): ismeretlen parancs, nem lehet arra menni, nem használható, játék elmentve.
  • save: sztringtömb, játékmentés igéi (15 bájtig, 8 szinoníma)
  • load: sztringtömb, játékbetöltés igéi
  • list: sztringtömb, leltárlistázás igéi
  • north: sztringtömb, északra navigálás igéi
  • west: sztringtömb, nyugatra navigálás igéi
  • east: sztringtömb, keletre navigálás igéi
  • south: sztringtömb, délre navigálás igéi
  • up: sztringtömb, emeletre navigálás igéi
  • down: sztringtömb, alagsorba navigálás igéi
  • verb1: sztringtömb, 1-es akció igéi (a kulcs lehet valamenyik "verbs" aliasz is)
  • verb2: sztringtömb, 2-es akció igéi
  • verb3: sztringtömb, 3-as akció igéi
  • verb32: sztringtömb, 32-es akció igéi
  • nouns: sztringtömb, tárgyak főnevei (255 sztringig)

A parszolás során a három UNICODE karakternél rövidebb szavaknak teljes egészében, egyébként csak a szó elején kell egyeznie. Emiatt ha például a verb1-nek [ "kinyit" ], a nouns-nak meg [ "lád" ] van megadva, akkor fel fogja ismerni azt is, ha a játékos kinyit láda vagy kinyitom a ládát parancsot gépeli be.

Szobák

A szobák sorszáma 1 és 254 közötti lehet (a 0-ás szoba az intró illetve reset valamint nem járható irány navigációs parancsoknál, a 255-ös meg a mentett játékállás helye). Egy szoba struktúra mezői:

  • image: sztring, egy PNG elérési útja, legfeljebb 256 x 96 pixeles
  • text0: sztringtömb, a config0-hoz tartozó szövegek (32 sztringig, egyenként 255 bájt)
  • text1: sztringtömb, a config1-hez tartozó szövegek
  • north: szám / sztring / sztringtömb, északi irány szkript
  • west: szám / sztring / sztringtömb, nyugati irány szkript
  • east: szám / sztring / sztringtömb, keleti irány szkript
  • south: szám / sztring / sztringtömb, déli irány szkript
  • up: szám / sztring / sztringtömb, felfele irány szkript
  • down: szám / sztring / sztringtömb, lefele irány szkript
  • logic: szám / sztring / sztringtömb, a szobába lépéskor automatikusan lefutó szkript
  • verbX: szám / sztring / sztringtömb, önálló igés szkriptek (X értéke 1 és 32 közötti, vagy "verbs" aliasz)
  • verbX Y: szám / sztring / sztringtömb, egy főnévvel rendelkező szkriptek (Y értéke 1 és 255 közötti, vagy "nouns" aliasz)
  • verbX Y Z: szám / sztring / sztringtömb, két főnévvel rendelkező szkriptek (Y, Z értéke 1 és 255 közötti, vagy "nouns" aliasz)

A szövegek 255 bájtosak lehetnek, és minden szobának saját 32 szövege lehet, melyeket a say / sayv / sayc utasításokkal lehet kiiratni.

Az 1-es számú szoba szkriptjei speciálisak abból a szempontból, hogy minden más szobában is elérhetőek. Emiatt ide érdemes egy "Vége a játéknak" szobát rakni, aminek a logikája csak egy jmp 0-ás resetet tartalmaz, így nincs benne további parancsbekérés.

Szkriptek

Bármelyik navigációs vagy igés parancs utánni JSON érték lehet egy nem nulla szám, ami egy szobaszám:

"north": 12,

Vagy lehet sztring, ami egy "rooms" aliasz:

"north": "padlás",

De ha egy sztringtömb, akkor az egy utasításokat tartalmazó szkript:

"north": [ "jmp 12" ],

Ezek befolyásolják a játék állapotát, szöveget jelenítenek meg, stb. Az utasítások paraméterei számok, de a megfelelő helyeken "rooms", "vars", stb. aliaszok használhatók.

A rendelkezésre álló utasítások:

  • end: szkript vége
  • and: az utótagja a következő utasítás feltételéhez adódik logikai ÉS kapcsolattal
  • or: az utótagja a következő utasítás feltételéhez adódik logikai VAGY kapcsolattal
  • bgm X: háttérzene lejátszása (X értéke 0 és 7 közötti)
  • sfx X: hangeffekt lejátszása (X értéke 0 és 63 közötti)
  • jmp X: X szobába lép (X értéke 0 és 254 közötti)
  • jmpv (X): mint a jmp, de a szobát az X változóból veszi
  • call X: meghívja az 1-es szoba X szkriptjét (X értéke 1 és 64 közötti)
  • callv (X): mint a call, de a szkript számát az X változóból veszi
  • give X: hozzáadja az X főnevet a leltárhoz (X értéke 1 és 254 közötti)
  • take X: kiveszi az X főnevet a leltárból
  • say X: az X szöveg megjelenítése (X értéke 1 és 32 közötti)
  • sayv (X) Y: az X változó értéke + Y szöveg megjelenítése
  • sayc X Y: vagy az X (hamis), vagy az Y (igaz) szöveg megjelenítése kondíciótól függően
  • add (X) Y: az X változó növelése Y-al (X és Y értéke 1 és 255 közötti)
  • addv (X) (Y): az X változó növelése Y változó értékével
  • sub (X) Y: az X változó csökkentése Y-al (X és Y értéke 1 és 255 közötti)
  • subv (X) (Y): az X változó csökkentése Y változó értékével
  • set (X) Y: az X változó értékét Y-ra állítja (Y értéke 0 és 255 közötti)
  • rnd (X) Y: mint a set, de egy 0 és Y közötti véletlenszámot rak X-be
  • mov (X) (Y): az Y változó értékét X változóba másolja

Ezek az utasítások mind elláthatók a következő utótagok egyikével:

  • nincs utótag: feltétel nélkül végrehajtódik
  • if (V) = N: csak ha a V változó értéke N
  • if (V) != N: csak ha a V változó értéke nem N
  • if (V) <= N: csak ha a V változó értéke kissebb vagy egyenlő, mint N
  • if (V) < N: csak ha a V változó értéke kissebb, mint N
  • if (V) > N: csak ha a V változó értéke nagyobb, mint N
  • has N: csak ha az N főnév a leltárban van
  • not N: csak ha az N főnév nincs a leltárban

Különleges eset, ha a (V) 250 vagy nagyobb, ilyenkor az adott navigációs irányt használja: 250 (vagy north, észak), 251 (vagy west, nyugat), 252 (vagy east, kelet), 253 (vagy south, dél), 254 (vagy up, fel), 255 (vagy down, le). Ha például azt a feltételt szeretnénk, hogy északra járható-e a szoba, az if north != 0. Ezek az állapotindexek a leltár bitmaszkját tárolják, amit a has illetve not feltételekkel kell elérni, így nincs ütközés.

A 0-ás szobára ugrás vár egy billentyűleütésre, majd újraindítja a játékot és a 0-ás helyett a megadott induló szobára ugrik (ez csak kifejezetten jmp utasításnak adható meg, mert a 0 szám nem használható, mint cél szobaszám).

Alapesetben egy szobaösszeköttetéshez szobaszámot (vagy "rooms" aliaszt) adunk meg, de ez feltétel nélkül átengedi a játékost az egyik szobából a másikba. Például ha van egy "kulcs felvéve" jelző a 7-es állapotban, és a 11-es szobában pedig van egy ajtó az északi irányban a 12-es szoba felé, és azt akarjuk, hogy csak akkor legyen járható, ha a játékos rendelkezik a kulccsal, akkor szkriptelt navigációra van szükség.

"11": {
  "text0": [ "Az ajtó zárva." ],
  "north": [ "jmp 12 if (7) = 1", "say 1" ]
}

Ilyenkor a north mezőben szám helyett egy sztringtömben a jmp 12 if (7) = 1 utasítást adjuk meg. Ez csak abban az esetben ugrik a 12-es szobába, ha a 7-es állapot értéke 1, egyébként marad a 11-esben. Ilyenkor mondhatjuk azt is, hogy "Az ajtó zárva" a say 1 utasítással (ha korábban a 12-es szobára ugrottunk, akkor ez már nem hajtódik végre). A szobaszám helyett használható "rooms" aliasz, az állapot index (változó) helyén pedig "vars" aliasz, például jmp padlás if kulcs = 1. Bonyolultabb összefüggés is megadható az and / or utasításokkal, amennyiben a befolyásolandó utasítás elé tesszük őket. Például hogy csak éjjel lehessen átmenni, és csak ha lámpája is van a játékosnak, az [ "and if éjjel = 1", "and has lámpa", "jmp padlás if kulcs = 1" ].

Egy másik példa, ami véletlenszerűen ugrik a 100 és 109 közötti szoba valamelyikére:

[ "rnd (1) 10",   /* 0 és 9 közötti véletlenszám az 1-es állapotba */
  "add (1) 100",  /* hozzáadunk 100-at így az most 100 és 109 közötti */
  "jmpv (1)" ]    /* az állapotban tárolt szobaszámra ugrás */

A kiírás is jöhet változóból, például ha a halál okát a 9-es állapotban tároljuk, ami 0 és 2 közötti, akkor:

"text0": [
  "Meghaltál, ennek oka:",  /* 1-es szöveg */
  "megfulladtál",           /* 2-es szöveg */
  "éhenhaltál",             /* 3-as szöveg */
  "bedarált a hegyirém"     /* 4-es szöveg */
],
"logic": [ "say 1", "sayv (9) 2" ]

Itt a say előbb kiírja az 1-es szöveget, majd a sayv veszi a 9-es állapot értékét, hozzáad 2-őt, és az annyadik szöveget írja ki a 2-es és 4-es közötti szövegek közül.

Ugyancsak hasznos a feltételes szövegkiírás, ami a kondíciótól függően vagy egy hamis, vagy egy igaz szöveget ír ki. Például:

"text0": [
  "Nincs nálad kulcs.",     /* 1-es szöveg */
  "Kinyitottad a ládát."    /* 2-es szöveg */
],
"nyit láda": [ "sayc 1 2 has kulcs", "set (10) 1 has kulcs" ]

Amennyiben a játékosnál nincs kulcs, úgy a sayc az 1-es, ha van, akkor meg a 2-es szöveget írja ki. Aztán beállítunk egy "láda nyitva" jelzőt a set-el, de csak akkor, ha volt kulcs a játékosnál. (Hogy a parancs így megadható legyen, ahhoz kell egy nyit "verbs" aliasz és egy láda "nouns" aliasz is. Mégegyszer, az aliaszok csak a JSON-ben használatosak és függetlenek a lefordítható szavaktól, amit a játékosok a játék közben gépelnek be.)

Minta játékok

Minta MEG-4 Kalandjátékok a meg4_advgame repóban találhatók.