Star Wars Galactic Battlegrounds szkriptek/A szkriptnyelv parancsai

A szkriptnyelv elemei

szerkesztés

A Genie AI-szkriptjei szöveges fájlok, amelyek különféle parancsokból állnak. Parancsból kétfélét fogok megkülönböztetni:

  1. Segédparancsok (metaszabályok), amelyek az AI-szkript értelmezőprogramjának „járulékos” működését vezérlik, nem pedig magát a játékost; ide tartoznak a következők: a kommentelő operátor (;), a konstansdefiniálás ( (defconst szöveges azonosító számérték) ), a szkriptbeágyazás operátora (load), a feltételes vezérlés operátorai (#load-if-defined ... #else ... #end-if), valamint a logikai operátorok ( not(), or(... ...), and(... ...) ); és az aritmetikai összehasonlító operátorok (kisebb-nagyobb-egyenlő).
  2. Szabályok, ezek végzik a játékos érdemi vezérlését, róluk később. A szabályok többsége leginkább a Horn-klózokra, ill. általában az ún. logikai programozási nyelvek parancsaira hasonlít (már akinek ez mond valamit): mindenesetre, feltételekből és következményekből állnak.

Mit írhatunk egy Genie AI szkriptbe? Lássuk;

  1. Kommentelhetünk, vagyis az AI-szkript-értelmező számára figyelembe nem vett sorokat írhatunk, megjegyzéseket csak a magunk vagy más szkriptelőtársak számára;
  2. Konstansokat definiálhatunk, érthetőbben, kiválasztva egy természetes számot (a felső határ 32 000 körül van, a C++ programnyelv ugyanis nagyjából a -32 000 ... +32 000 tartományban kezeli az egész számokat - aki tudja, pontosítsa), annak szöveges nevet adhatunk. Ez így talán nem látszik túl nagy lehetőségnek, de - ld. lentebb - sok mindenre használható.
  3. Számváltozókat definiálhatunk. Egy változónak nemnegatív egész értéket adhatunk, ezt az értéket meg is változtathatjuk, az értéket egy parancsba beolvastathatjuk.
  4. Lehetőség van bizonyos szabályok ún. feltételes végrehajtására. Mi szükség van erre, ha a szabályok amúgy is feltételekhez kötöttek? A feltételes betöltés másféle értelemben vett feltételekhez, konkrétan a játék beállítási paramétereihez való igazíthatóságot biztosítja. Elegánsabbá, áttekinthetőbbé és egyszerűbben megfogalmazhatóvá teheti a szkriptet, olyan lehetőséget teremtve, amelyet máshogy körülményesebben lehetne megoldani. Sőt, néhány olyan beállításra is tekintettel van, amit máshogy nem lehet megfogalmazni.
  5. A tulajdonképpeni magva, lényege a szkriptelésnek, hogy szabályokat definiálhatunk. A szabályok parancsok, amiket a CP igyekszik majd végrehajtani. Egy szabály lényege szerint két részből áll: van egy sereg feltétel (tények, facts), ha ezek teljesülnek, akkor egy sereg parancs (actions) végrehajtódik. A tényeket, feltételeket leíró részben használhatunk logikai operátorokat: és (and), vagy (or) és nem (not).
  6. A szkript végrehajtásának tetszőleges fázisában betölthetünk egy másod- vagy alszkriptet az AI-szkriptünkbe . A szkriptek egymásba ágyazhatóak. Ez lehetővé teszi pl., hogy egy nagyon hosszú szkriptet modulárissá alakítsunk, kisebb részekből összerakva.
  7. Egyéb lehetőségek: lehetőség van néhány beágyazott szkript közötti véletlen választásra is.

Adattípusok

szerkesztés

E szakasz az AI-szkriptírás szempontjából nem olyan lényeges, pusztán a mélyebb elméleti megértést szolgálja. Akit nem érdekel, ugorja át nyugodtan.

A Genie AI-szkriptnyelvében kétféle fő adattípust különböztetünk meg (ha nagyon akarunk):

  1. Sztring (egyszerű szöveg): A sztringek háromféle célt szolgálhatnak: a fájlnevek azonosítását, a chatelést és a kommentelést. A sztring tehát, hozzávetőlegesen, a „szkriptnyelven kívüli” tartalmak azonosítására. Egy sztring arról ismerhető meg, hogy vagy a ; szimbólum után következik, és a sorvégig (enter karakterig) tart; vagy angol idézőjelek, a " ... " szimbólumok közé van zárva.
  2. Szimbólum: Bármely karaktersorozat, amely nyomtatható ASCII karakterekből áll, de nem tartalmaz szóközt és idézőjeleket, és két ún. határoló karakter közé esik, szimbólum. Határoló jelek: 1). szóköz; 2). tab; 3). kocsivissza; (ez Windows-okban ált. egy enter) 4). sorvég (ez Windows-okban ált. szintén enter); 5). Kerek nyitó zárójel; 6). Kerek csukó zárójel. A szimbólumok értelmezése kézszenzitív, vagyis két szimbólumként értelmezett szöveg, amely azonos betűkből áll, csak az egyikben valamelyik betű nagy, a másikban kicsi, két különböző szimbólumnak számít. A szimbólumok a szkriptnyelv parancsai, vagy azok elemei, tehát valamilyen tág értelemben a „szkriptnyelven belüli” tartalmak azonosítói.

A szimbólumok többféle tovább csoportosíthatóak, akárcsak bármelyik közismert programozási nyelv esetében. Vannak pl. beépített (szűkebb értelemben a szkriptnyelven belüli) és felhasználó által definiált szimbólumok. Mindkét csoport szimbólumai „adatszerkezeti”, logikai-szemantikai szempontból tovább csoportosíthatóak: főként konstansokra, változókra és parancsokra. Erről később.

Tehát ha egy változót elnevezünk goal-T1Carbon-nak, és valahol goal-t1carbon-ként hivatkozunk rá, a program hibaüzenetet ad, mert a kis t és nagy T betűket eltérőeknek minősíti, és azt hiszi, újra akarunk definiálni egy konstanst (ami tilos). [mj 1]

A legelső parancs, amit a szkriptnyelvből megismerünk, legyen a kommentelés, vagyis a megjegyzések elhelyezése. Legyen azért, mert ez okozhatja a legkevesebb kárt; no meg, mert ez a legegyszerűbb.

Íme: nyissunk egy új sort, és a sor legelejére írjunk egy pontosvesszőt, majd hagyjunk szünetet. Amíg nem ütünk entert, az ez utáni szöveget az AI szkriptünk értelmezőprogramja egyszerűen figyelmen kívül fogja hagyni. Példa:

 
; Ez a sor, megjegyzés csak szöveg és nem AI parancs, mert pontosvesszővel kezdted.

; Ez úgyszintén.

A kommentelés egyáltalán nem haszontalan eszköz. Lehetőség van magyarázatokat fűzni a parancsokhoz. Ha pl. egy hónappal a készítése után nem vagy megelégedve az AI szkripteddel, és meg szeretnél változtatni valamit, akkor könnyebben megtalálod, ha a szkriptedet megjegyzésekkel láttad el. Az esetleg több száz soros, elég lélektelen formális nyelven írt AI szkriptet már csak a benne való eligazodás miatt is célszerű legalább nagy vonalakban kommentezni (pl. fejezetekre osztani, techlevel-1 viselkedés, techlevel-2 viselkedés stb.). Ezt, ha jól tudom, a programozásmódszertanban dokumentálásnak hívják. A bonyolultabb szkripteket célszerű tehát „dokumentálni”, és párszor még látható lesz, hogy nem csak a most említett okból.

Konstansok

szerkesztés

„A beépített” számkonstansok és azonosítóik

szerkesztés

A Genie szkriptnyelv két alapvető szerepet tölt be: létrehozza a véletlen térképeket, és szabályozza a CP-k viselkedését.

Mi csak a második lehetőséggel foglalkozunk, de a konstansok miatt kénytelenek vagyunk kicsit a szkriptnyelv utóbbi lehetőséget csak távolabbról érintő alapfogalmaival is foglalkozni.

A térképeken alapvetően kétféle dolog kaphat helyet.

  1. Az egyik és elsődleges dolog a geográfiai viszonyok szimulációja. Nevezzük ezeket terepelemeknek. Terepelemből háromféle van: 1). talaj (terrain) - ezek lényegében képfájlok, amik füvet/jeget/vizet stb. utánoznak; 2). domborzat (elevation) - ez olyan grafikai elem, amely a talajhoz hozzáadva a talaj emelkedésének/süllyedésének érzetét kelti; 3). szikla (cliff) - ezek sziklákat utánzó grafikus elemek. A SWGB-ban a talajok „kétrétegűsége” miatt még ennél is bonyolultabb a helyzet, de mindez nekünk most nem lényeges.
  2. Minden más, ami akár közvetlenül, akár közvetve a térképre kerülhet, az tereptárgynak, vagyis objektumnak minősül. Objektum lehet egy épület, egy egység, egy vadállat, egy díszítőelem, de objektumként viselkednek a romok, a holttestek, a lövedékek stb. is.

A Genie motor (s többek közt, a gamedata.drs fájl) mármost sok terepelemet és minden tereptárgyat egy számmal azonosít. Ezek nagy részét a gamedata.drs fájl listázza is (egyébként, több szkript-tutorial-író tanúsága szerint, közel sem az összeset - felületesen elég nehéz ezt eldönteni, mert a lista össze-vissza van, nem pedig a növekvő számazonosítók szerint). Néhány ezek közül, csak mutatóba:

  • 16: űr (talajféleség)
  • 41 grass4 (sárga síktalaj)
  • 50 : működő farm
  • 109: működő központ
  • 621: épülőben lévő központ
  • 1117: vörös szénszikla
  • 764: gungan bombázó (1. fázis)
  • 785: gungan bombázó (2. fázis, nehézbombázó)
  • 833: bantha

És így tovább. Ezeket a számokat a továbbiakban beépített numerikus aktortípus-azonosítóknak (BNAA) nevezzük. A gamedata.drs ezekhez a BNAA-khoz alfabetikus szavakat rendel, pl. a 833-as számhoz a „bantha” szót.

A (defconst) parancs

szerkesztés

A defconst parancs két dologra jó: A) definiál egy „még nem létező” számkonstanst (azaz elnevez egy még nem használt, nem elnevezett számot szöveggel), vagy pedig B) más azonosítót ad egy már létező számkonstansnak - akár előzőleg a felhasználó definiálta, akár a fentebb leírt módon a fejlesztők építették a nyelvbe. Nem képes azonban arra, hogy egy már definiált konstansnak új értéket adjon - hisz különben a konstans nem is konstans lenne, hanem változó. Tehát tartsuk észben, hogy a parancs használata nem értékadás egy valahogy elnevezett változónak, hanem nagyjából épp ellenkezőleg: névadás egy változatlan számnak. A defconst parancs használata rendkívül egyszerű:

(defconst szöveg egész-szám)

A szöveg paraméter értéke valamilyen, nyomtatható karakterekből álló szöveg. Egyetlen megkötést ismerek: nem kezdődhet számmal. Az egész-szám paraméter értéke olyan egész szám, amely a C++ nevű programnyelvben megengedett (kb. -32 000-től kb. +32 000-ig).

Lássunk két-három példát!

1. A gamedata.drs-ben az 56-os objektum egy halászó robot, szöveges azonosítója UNIT-FISHER1; az 57-es objektum egy másik halászó robot, szöveges azonosítója UNIT-FISHER-2. Tegyük fel, hogy szeretnénk magyarul hivatkozni rájuk, vagy hogy más okból elégedetlenek vagyunk ezekkel a szöveges azonosítókkal (például szeretnénk szemléletesebb nevet nekik, mert nem tudjuk megjegyezni, melyik melyik, vagy pedig nem akarjuk őket csupa nagybetűvel írni). Nosza, rendeljünk a két BNAA-hoz magyar szöveget, írjuk a szkript fájlba (mondjuk az elejére):

(defconst Halász1 56)
(defconst Halász2 57)

Ezentúl a további parancsokban mindenhol, ahol a UNIT-FISHER1-re lenne hivatkozás, azt kicserélhetjük Halász1-re. Mindez - ahogyan az előbb említettük - nem azt jelenti, hogy az „UNIT-FISHER1” értéket „lecseréltük” a „Halász1” értékre, a továbbiakban mindkét név is használható akár. Pusztán annyi történt, hogy az 56-os azonosítónak most már nem egy, hanem két másik elnevezése is lesz. Egyébként a szöveges azonosítók helyett a bnaa-k, vagyis a számok is használhatóak lennének minden további tevékenység nélkül a szkriptekben; csak az még áttekinthetetlenebbé tenné azokat. Ismételjük meg: a szkriptnyelv nagyon formális és lélektelen, a hosszú szkriptek áttekinthetetlenné válhatnak; vagyis fontos eligazodni benne. Ehhez az objektumok jól motivált elnevezései hozzásegíthetnek.

2. Most lássuk a másik fajta használatot!


(defconst easy-t1-workerhigh 32)

Emberi nyelven: „a 32-es szám ezentúl legyen a könnyű játékmód 1. technológiai szintjének munkásszáma, vagyis könnyű módban, a tech-level-1 szinten a játékosnak 32 munkás kívánatos”.

Tartsuk észben, hogy a defconst parancs csak nevet ad egy számnak, vagyis ez a parancs csak úgy önmagában (sajnos) NEM fogja azt eredményezni, hogy a CP könnyű módban a tech-level-1 alatt valóban készít 32 munkást.

Egy számnak lehet különböző neve(ke)t adni. Pl. lehetséges:


(defconst easy-t1-workerhigh 32)
(defconst easy-t2-workerhigh 32)

A konstansnak új értéket adni azonban nem lehetséges, tehát „Error in line 2: Constant already defined.” hibaüzenethez vezet a következő AI szkriptfájl [mj 2]:


(defconst easy-t1-workerhigh 32)
(defconst easy-t1-workerhigh 33)

A defconst parancs kétértelműségének összeegyeztethetőségről

szerkesztés

Éles szemű-eszű ember észrevehette, hogy a defconst parancs két használata, úgy tűnhet, ütközik [mj 3]. Ha pl. azt szeretném, hogy a 32-es bnaa-jú objektum neve ne BLDG-FARM, hanem csak farm, tehát:


(defconst farm 50)

viszont azt is szeretném, hogy használhassak ugyanakkor egy „t2-civilian-population” nevű konstanst, aminek értéke véletlenül szintén 50, tehát írom:


(defconst t2-farmhigh 50)

akkor nem fog-e mindez ütközéshez vezetni? Nem az történt-e, hogy átdefiniáltam a „farm” szöveget „t2-farmhigh”-á, és ezentúl az első szöveget már nem használhatom? Szerencsére nem. A defconst parancsok ilyen értelemben nem írják felül egymást, hiszen, mint mondtuk, itt nem injektív hozzárendelésről van szó. Már csak azért sem, mert a „farm” nevet teljesen máshol fogom használni, mint a „t2-civilian-population” nevet. A szkriptértelmező alprogram különbséget tud tenni a kétféle használat között. Például legyen a szkriptem ez:


(defconst farm 50)
(defconst t2-civilian-population 50)

(defrule
 (current-time == 120)
 (building-type-count farm >= t2-farmhigh)
=>
 (build farm)
)

Az ötödik sorban a (building-type-count épület >= szám) parancsban az épület argumentum helyére csak érvényes épületnév jöhet. Az értelmezőprogram tehát ellenőrzi, a „farm” szóhoz tartozik-e valamilyen épület? Megkeresi a Gamedata.drs fájlban a „farm” név bnaa-ját; természetesen nem fogja találni, mert ott a farmot nem „farmnak” hívják, hanem így: BLDG-FARM. Ezután megnézi, a lokális szkriptfájlban, a Testguy.per-ben van-e épület a „farm” szóhoz rendelve. És valóban, megtalálja, hogy a farm szóhoz az 50-es szám van rendelve, természetes, hogy ezt az 50-es objektum, amely valóban épület, azonosítójaként kezeli. Viszont a „>=” relációs jel után értelmetlen dolog épületet keresni, oda csak szám jöhet. Tehát a „t2-farmhigh” konstansról nem fogja azt feltételezni, hogy az egy objektum lenne. Ki van ez találva. Látható: az sem fog gondot okozni az értelmezőprogramnak, ha egy bnaa-hoz több nevet rendelek, pl. a banthát (Azzaz a bnaa 833-as objektumot) elkeresztelem „büdösbanthának” és „kövérbantának” is egyszerre. Ha ezeket a neveket adekvátan használom, azaz, csak egységekre vonatkozó parancsokban használom őket, akkor ez nem okoz zavart az értelmező alprogram számára. Szintaktikai zavart egyébként sem, legfeljebb az AI nem azt fogja csinálni, amit szeretnék.

Egyetlen kivétel van, amit a program nem fogad el: ha egy számnak egy másik számmal akarunk nevet adni. Pl. a (defconst 54 55) nem hajtódik végre megfelelően, ezért kerüljük az ilyesmit. A defconst első paramétere nemcsak nem lehet szám, de olyan szöveg sem, amely számmal kezdődik. Hibaüzenetet nem ad, de nem is fog az 54-es objektum helyett pl. 55-öst képezni.

Beépített szöveges azonosítók, avagy játékparaméterek

szerkesztés

A Genie AI szkriptnyelvében nemcsak beépített és definiálható számkonstansok vannak, hanem szöveges jellegű konstansok és változók is.

E „foglalt sztringek” főképp egy funkciót látnak el: akkor kapnak értéket, ha már elindult a játék, és értékük a játék megfelelő beállítása lesz. Mindezek miatt játékparamétereknek neveztem el őket.

E játékparamétereket az online útmutatókban néha beépített szövegkonstansoknak is nevezik. Ezzel nem igazán vagyok megelégedve, a játékparaméterek egyik része kétségkívül konstans, másik része azonban szerintem sokkal inkább változónak tekintendő. Lássuk a részleteket!

A játékparaméterek két csoportra oszlanak: egy részük a a feltételes végrehajtás parancsának fejrészében alkalmazható, ezeket ld. ott. Ezek olyan szavak, mint REBEL, TINY-MAP, DIFFICULTY-HARD, kétségkívül semmi másnak nem tekinthetőek, mint sztringkonstansnak.

Más, itt tárgyalandó részük azonban a defrule parancsban használható, és értékük játékról játékra és játékosról játékosra változhat. Emiatt igazából szöveges értékű változók. Mármost azonban, ha egy játék elindult, akkor onnantól kezdve a játék végéig az értékük rögzül, és talán innen a félreértés, hogy konstansok.

A két játékparaméter-család között van némi átfedés, de azért nem ugyanarról a dologról van szó.

A másodikként említett, inkább változószerű család tagjai nem pusztán a szűkebb értelemben vett játékbeállításra vonatkoznak, hanem egy részük civilizációfüggő. Ezek a civ-paraméterek. Néhány AI szkripter szerint utóbbiak megbízhatatlanul, vagy nem működnek.


A defrule parancsban is (elvileg) használható paraméterek és értékeik a következők:

  • Játékparaméterek
    • my-player-number: Értéke adott játékban mindig a játékos saját sorszáma. Minden játékosnak, 1-től legfeljebb 8-ig, van egy sorszáma. A gaia nevű rejtett játékosnak 0 a sorszáma. Hogy ez a paraméter képes-e ilyen értékkel is visszatérni, azt nem teszteltem.
    • my-civ: Értéke adott játékban mindig a játékos civilizációtípusa. Értékei: rebel, gungans, wookiees, naboo, empire, federation.
  • Civ-paraméterek:
    • my-unique-unit: Értéke elvileg a játékos sajátegysége, Balbarian (ld. források) szerint ez nem igazán működik. Persze ez megoldható úgy is, hogy megkeressük a gamedata.drs fájlban az egység konstansát (bnaa), és azt használjuk, vagy azokhoz írunk feltételes végrehajtási parancsokat.
    • my-unique-unit-upgrade: Értéke elvileg a játékos elit sajátegységét kikutatató technológia neve, Balbarian szerint nem működik.
    • my-elite-unique-unit: Értéke elvileg a játékos elit sajátegysége, Balbarian feltételezi, hogy ez sem működik.
    • my-unique-unit-line: Értéke elvileg a játékos sajátegysége vagy elit sajátegysége, attól függően, hogy melyik van neki. Balbarian szerint ez szerepel a sztenderd AI szkriptben, így feltételezi, hogy működik.
    • my-unique-research : Értéke elvileg, legalábbis az AoK-ben, a játékos sajáttechnológiája. Mármost ebből a SWGB-ban nem feltétlenül csak egy van. Balbarian tesztjei szerint a wukik és a szövetségiek esetében részlegesen működik, 1-1 (erődbeli? - megj. tőlem) sajáttechnológiára hivatkozik.

A legtöbb útmutatóban nincs minden paraméter felsorolva. Pl. a Reveal Map beállításhoz tartozik-e beépített paraméter? Kérdéses, hogy ezeket csak figyelmen kívül hagyták-e az útmutatókészítők, vagy nem is léteznek? Nekem személy szerint az a benyomásom (próbálkozások és utánakeresés után), hogy pl. az ALLTECHS beállításhoz nincs beépített paraméter.

Változók: a goal parancs(ok)

szerkesztés

A Genie szkriptnyelvében a felhasználók által is definiálható változókat goal-oknak hívják. Kétféle parancs vonatkozik rájuk: az értékadó és az értékellenőrző.

Értékadás

szerkesztés

Az értékadó parancs a következőképp néz ki:


(set-goal numerikusazonosító érték)

Például:


(set-goal 2 3)

kiolvasva: „állítsd a szkripted másodiknak nevezett változójának értékét 3-ra!”. A változókat, közvetlen módon, csak számokkal lehet elnevezni. A gamedata.drs fájl, ahol szöveges azonosítójú goal-ok is vannak, ne tévesszen meg senkit: a lokális, felhasználói szkriptfájlokban nincs ilyen lehetőség, a szöveges azonosítójú goal-okra a hibaellenőrző alprogram hibaüzenettel reagál. Ez a a korlátozás azonban a defconst parancs használatával megkerülhető, vagyis mégis csak van lehetőség, igaz, közvetett úton, egy változó szöveges elnevezésére is, de ehhez külön „szótár” kell egy sor defconst parancsból, a részletek lentebb.

Értékellenőrzés

szerkesztés

Az értékellenőrzés még egyszerűbb:


(goal numerikusazonosító érték)

Például:


(goal 2 3)

kiolvasva: „igaz-e, hogy a másodiknak nevezett változó értéke három?” avagy „amennyiben a másodiknak nevezett változó értéke három, ...”.

Az egyszerű szintaktika ára, hogy a szkriptfájlokbeli változók használata nem túl gazdag pl. egy magas szintű programozási nyelv lehetőségeihez képest. A változók főleg egyszerű feltételes és számláló ciklusok megvalósításához használhatóak.

Alkalmazás a feltételrendszerek egyszerű megnevezésére

szerkesztés

Egy igen gyakori használati mód, amikor számos parancsot akarunk kiadni, amennyiben bizonyos hosszabb feltételrendszer teljesül. Pl. ha 1) van 500 szenünk, 2) 1000 orénk, 3) a techlevel-3-ban vagyunk, de 4) még nem telt el a szintből 2 perc, és 5) az ellenséges bázisban a felderítőnk már látott 10 repülőgépet, és 6) a városunk épp nincs támadás alatt, és 7) már megépült az egyik erődünk, akkor ebben a helyzetben A) szeretnénk építeni egy légvédelmi tornyot, B) szeretnénk kiképezni 20 légvédelmis gyalogost és C) szeretnénk gyártani két légvédelmi mobilt.

Nos, ezt egy parancsba biztosan nem tudjuk belefoglalni, mert a húsz légvédelmis gyártása, ha egyenként oldjuk meg, akkor túl hosszú szabályt eredményezne, a hibaellenőrző alprogram hibát jelezne. Arra törekszünk tehát, hogy összefoglaljuk valahogy ezt a helyzetet. Definiálunk egy új változót, mondjuk a goal 4-et („(set-goal 4 2)”), amelynek értéke 0 lesz („set-goal 4 0”), ha a helyzet nem áll fennt, és 1 („set-goal 4 1”), ha a helyzet fennáll. A további szabályokban, ahol e helyzet fennállása vagy fenn nem állása képezi a döntés alapját, nem kell a hosszadalmasan leírható 7 feltételből álló rendszert belefoglalnunk a szabályokba, csak ennyit írunk:


(defrule
(goal 4 1)
=>
... parancsok ...
)

Az is gyakran előfordul, hogy van egy nagyon gyakran használt (bár nem feltétlenül hosszú) feltételrendszerünk, amelyhez bizonyos parancsokban járulékos feltételek is adódnak, de mások és mások, így nem lehet ezeket a szabályokat egy szabályban összefoglalni. Sokszor az ilyen esetekben is célszerű az állandóan fellépő feltételrendszert egy változó egy v. több értékében összefoglalni.

Tehát az egyik dolog, bár nem az egyetlen, amire a változók használhatóak: a túl hosszú vagy túl gyakori feltételrendszerek tömörítése, rövid elnevezése.

A defconst használata változóknak való névadásra

szerkesztés

Nem árt megismerkedni azzal a lehetőséggel, hogy hogyan vezethetünk be szöveges nevű változókat. Ez ismét olyan dolog, ami nem a CP-t érinti, hanem csak a szkriptfájl dokumentációját és (ezáltal) a szkript tervezését és javítását könnyíti.

Sokak szerint (bevallom, közéjük tartozom) kicsit idegesítő, hogy a változónevek számok. Észben kell tartani, hogy melyik változót milyen szerepkörre rendeltünk, hogy pl. a negyvenes számú változó csak egy ciklusszámláló segédváltozó-e, vagy pedig egy kulcsfontosságú helyzet (pl. egy támadás alatt álló város megmentésének) feltételrendszerét rögzíti-e. Lehet a szkriptfájl elején egy szótárszerű kommentszakaszt létrehozni, hogy pl.

 ; goal 1 - szénszintmérő változó  ; goal 2 - élelemszintmérő változó  ; goal 3 - novaszintmérő változó  ; ...  ; goal 40 - ciklusszámláló segédváltozó nova adóztatáshoz  ; goal 41 - ciklusszámláló segédváltozó ore adóztatáshoz  ; ...  ; goal 221 - értéke 1, ha a város félig elpusztult, de újjáépíthető; értéke 2, ha minden elveszett; értéke 0, ha nincs ilyen probléma  ; ...  ; goal 234 - ha valamelyik ellenfélnek túl erős a repülőarmadája  ; és így tovább ...;.

de hát ezt vagy észben tartja az ember (általában nem), vagy pedig írás közben mindig előre kell ugrani a szótárhoz, megnézni, hányadik változót kell definiálni éppen, csak hát utána elég nehéz visszakeresni a többezer soros .txt fájl közepén, hol tartottunk. És minek is, nem lenne-e jobb, ha a változók nevében benne lenne a funkciójuk?

Ha pl. szöveges nevet és szöveges értékeket szeretnénk adni az első számú változónak, akkor a fájl elejére tegyünk egy defconst parancsokból álló ilyesféle „szótárat”:


 ; a goal 1 neve és értékei
 (defconst goal-SZÉNMÉRŐ 1)
 (defconst SEMMI-szén 0)
; Sürgősen szenet kell bányászni, és felhagyni a fogyasztással
 (defconst KEVÉS-szén 1)
; Sürgősen szenet kell bányászni, és csak a legszükségesebb feladatokkal fogyasztani
 (defconst ELÉG-szén 2)
; Korlátozni lehet a szénbányászatot, és átlagos ütembe folytatni a munkát
 (defconst SOK-szén 3)
; Építhető pár plusz (nem létfontosságú) épület és plusz támadó/védő egység, kis ajándékok adhatóak a szövetségeseknek
 (defconst RENGETEG-szén 4)
; Folytatni lehet az építkezést, a szövetségeseket is meg lehet tömni szénnel

Ezek után már pl. (goal 1 2) helyett nyugodtan írhatjuk azt, (goal goal-SZÉNMÉRŐ ELÉG-szén). Ugyanazt fogja jelenteni a két feltétel. A szabályokban pedig beállíthatjuk, hogy mondjuk ELÉG-szén értékű akkor legyen a szenünk, ha 500 és 700 között van:


(defrule
 (carbon-amount >= 500 )
 (carbon-amount <= 700)
=>
 (set-goal goal-SZÉNMÉRŐ ELÉG-szén)
)

Nem kötelező ugyan a goal-oknak szöveges nevet adni, de foglaljuk össze, miért is jó:

  1. Szemléletesebb, könnyebben megjegyezhető és motiváltabb nevekkel gyorsulhat a munkánk (nem kell mindig keresegélni, mire szolgált a 30.-as számú goal).
  2. Könnyebb utólag beilleszteni goal-okat egy szkriptbe. Amikor rájövünk, hogy hoppá, a szkript elején szükségünk lenne még egy goal-ra, akkor mondjuk az ötödik goal-tól kezdve át kell nevezni az összeset. Ha ehelyett szöveges azonosítókat adtunk neki, akkor csak a defconst parancsokból álló szótárat kell egy helyen módosítani. Illusztráció:
Van egy goal 1, 30 parancs használja.
Van egy goal 2, az előzőek közül 15 parancs használja, és még 5.
Van egy goal 3, amit az előző 15 közül 2 parancs használ, az előző öt közül 2, és még 10.

Ha mármost a goal 2 és a goal 3 közé egy új goal-t szeretnénk illeszteni, finomítva mondjuk a goal-ok által leírt feltételrendszereket, akkor a goal 3-t használó összes (14) parancs összes olyan helyén, ahol ez a változó előfordul, átnevezést kell végrehajtani goal-4-re, aztán beilleszthető már az új goal-3 változó.

De ha egy ilyen szótárunk van:

(defconst Valami 1)
(defconst Izé 2)
(defconst Mégmásis 3),
+ parancsok

vagyis elneveztük a goal-1-et Valaminek stb., akkor elég csak ezt a háromsoros szótárat módosítani egy új goal beillesztésekor, hiszen a parancsok nem használják a numerikus csak a szöveges azonosítókat. Csak annyi a dolgunk, hogy a 2 sor után beillesztjük a következő sort:

(defconst Újabb 3)

valamint a következő sorokatt így módosítjuk:

(defconst Mégmásis 4)
... stb.

Ez természetesen jóval áttekinthetőbb és rövidebb munka, gyorsabb végrehajtással és kevesebb hibalehetőséggel.

Néhány más parancs

szerkesztés

Load-if(-not): feltételes (nem-)végrehajtás

szerkesztés

A load -if parancsba ágyazott szabályok csak bizonyos beépített feltételek esetében hajtódnak végre. Itt konkrétabban arról van szó, hogy ezt a parancsot a játékbeállítások figyelembevételére találták ki. A játékkészítők alkottak néhány foglalt szót, pl. REBEL („lázadó”), MOTHERLODE („anyatelér”), vagy EASIEST („legkönyebb”), amelyek leírják a játéktérkép-fajtákat és a játék egyéb beállításait. A különféle útmutatókban ezeket rendszerkonstansnak, rendszer-definiálta szimbólumoknak vagy foglalt szavaknak nevezik, mi egyszerűen játékparaméternek.

Nem csak szabályok (vagyis a defrule parancs), hanem a defconst és a többi parancs is végrehajtható feltételesen. Egy feltételes defconst parancs pl. azt jelenti, hogy REBEL-ként játszva a t1-carbon értéke lehet húsz, míg EMPIRE-ként játszva, lehet harminc; bár egy azonosítóhoz több számérték tartozik, de ezek feltételesen töltődnek be, nem egyszerre, tehát a hibakereső alporgram nem fog („constant already defined") hibaüzenetet adni (ez egyébként az egyetlen olyan eset, amikor eltűri a konstans átdefiniálását más számértékre). Sőt, a feltételes végrehajtások maguk is egymásba ágyazhatóak, egészen 50 szint mélységig.

Többféle szintaktikával lehet használni.

Egyszerű load-if változat:


#load-if-defined játékparaméter
parancsok
#end-if

Ágaztatott load-if változat:


#load-if-defined játékparaméter
parancsok
#else
szabályok
#end-if

Amennyiben olyan játékbeállításokkal játszunk, amelyek valamelyikére teljesül a szabály „fejében” foglalt játékparaméter - pl. a REBEL beépített azonosító van oda írva, és a CP épp valóban lázadó civre van állítva - akkor végrehajtódnak a fejben foglalt parancsok, egyébként nem. A második változat hasonló, csak ott az „else” rész után is lehetnek szabályok, amik pont akkor hajtódnak végre, ha a játékparaméter értéke nem teljesül.

Load-if-not
szerkesztés


#load-if-not-defined játékparaméter
parancsok
#end-if

Ágaztatott load-if-not változat:


#load-if-not-defined játékparaméter
parancsok
#else
parancsok
#end-if

A load-if parancshoz képest épp ellenkezőleg működik: amennyiben a játékparaméter nem teljesül, akkor hajtódik végre az első csokor szabály, míg az #else rész utániak nem fognak végrehajtódni.

A feltételes végrehajtásban alkalmazható játékparaméterek
szerkesztés

A következő játékparaméterek (nagybetűvel írandóak, a zárójeles rész csak magyarázat) használhatóak:

  1. Civilizációra vonatkozó értékek
    1. GAIA (vagy player# 0) - gaia (vadállatok, természeti tárgyak stb.)
    2. REBEL (lázadó)
    3. WOOKIEES (wukik - figyeljünk a helyesírásra: dupla wé, dupla ó, dupla e)
    4. NABOO (naboo-k)
    5. GUNGANS (gunganek)
    6. EMPIRE (birodalmi)
    7. FEDERATION (kereskedelmi szövetség)
    8. REPUBLIC (csak a Clone Campaigns-ban)
    9. CONFEDERACY (csak a Clone Campaigns-ban)
  2. A játéktípusra vonatkozó értékek:
    1. DEATH-MATCH (a földdel egyenlővé kell tenni az ellenségeket, extra sok indító erőforrás, így a gyűjtögetés másodrendű: aki nem harcol elég gyorsan, az annál gyorsabban pusztul)
    2. TERMINATE (az AoK-beli regicide megfelelője: meg kell ölni az ellenséges parancsnokokat)
    3. KING-OF-THE-HILL („commander-of-the base”: el kell foglalni és meg kell védeni a térkép közepén lévő parancsnoki központot)
    4. MONUMENT-RACE (nincs harc, minél gyorsaban emlékművet kell építeni)
    5. DEFEND-MONUMENT (az egyik játékos emlékművel indul, a többieknek időre le kell rombolni)
  3. Erőforráskonfiguráció-paraméter értékei:
    1. LOW-RESOURCES-START (alacsony kezdeti erőforráskészletek)
    2. MEDIUM-RESOURCES-START (átlagos ~)
    3. HIGH-RESOURCES-START (magas ~)
  4. Térképméret értékei:
    1. TINY-MAP (epszilon köb méretű)
    2. SMALL-MAP (epszilon négyzet méretű
    3. MEDIUM-MAP (epszilon méretű)
    4. NORMAL-MAP (nagyon-nagyon kicsi)
    5. LARGE-MAP (kisebb méretű)
    6. GIANT-MAP (alig elfogadható méretű)
  5. Térképtípus értékei:
    1. WATER-MASS-MAP
    2. LAND-SATELLITES-MAP
    3. SPACE-SATELLITES-MAP
    4. PLANETS-AND-MOONS-MAP
    5. SEARCH-AND-DESTROY-MAP
    6. TEAM-LAND-SATELLITES-MAP
    7. TEAM-SPACE-SATELLITES-MAP
    8. STAR-WARS-WORLD-KASHYYYK-MAP
    9. STAR-WARS-WORLD-ENDOR-MAP
    10. STAR-WARS-WORLD-GEDDES-MAP
    11. STAR-WARS-WORLD-AEREEN-MAP
    12. STAR-WARS-WORLD-KESSEL-MAP
    13. STAR-WARS-WORLD-TATOOINE-MAP
    14. STAR-WARS-WORLD-TATOOINE-NEW-MAP
    15. STAR-WARS-WORLD-YAVIN-MAP
    16. SEA-MAP
    17. SHORELINE-MAP
    18. LAND-MASS-MAP
    19. SPACE-MASS-MAP
    20. NOVA-LAKE-MAP
    21. LARGE-SEA-MAP
    22. STAR-WARS-WORLD-KRANT-MAP
    23. STAR-WARS-WORLD-HOTH-MAP
    24. STAR-WARS-WORLD-HANOON-MAP
    25. STAR-WARS-WORLD-REYTHA-MAP
    26. STAR-WARS-WORLD-DAGOBAH-MAP
    27. STAR-WARS-WORLD-ZALORIIS-MAP
    28. STAR-WARS-WORLD-NABOO-MAP
    29. STAR-WARS-WORLD-SARAPIN-MAP
    30. STAR-WARS-WORLD-EREDENN-MAP
    31. STAR-WARS-WORLD-GEONOSIS-MAP
    32. STAR-WARS-WORLD-MOSESPA-MAP
    33. CUSTOM-MAP
    34. RAIDERS-MAP
    35. RIVERS-MAP
    36. SWAMP-MAP
    37. TUNDRA-MAP
    38. DESERT-MAP
    39. ARENA-MAP
    40. FOREST-MAP
    41. FORTRESS-MAP
    42. ICE-LAKE-MAP
    43. NOVA-ASSAULT-MAP
    44. PRECIPICE-MAP
    45. FLATS-MAP
    46. MOTHERLODE-MAP
    47. SAVANNAH-MAP
  6. Győzelmifeltétel-konfigurációk paraméterének értékei
    1. VICTORY-STANDARD (conquest vagy monunemt közül bármelyik)
    2. VICTORY-CONQUEST (porig rombolni az ellenfeleket)
    3. VICTORY-TIME-LIMIT (meghatározott idő alatt a legjobb pontstatisztikát csinálni)
    4. VICTORY-SCORE (a legjobb pontstatisztikát csinálni)
    5. VICTORY-CUSTOM (egyéni beállítások)
  7. Nehézségi fokozatok értékei
    1. DIFFICULTY-EASIEST
    2. DIFFICULTY-EASY
    3. DIFFICULTY-MODERATE
    4. DIFFICULTY-HARD
    5. DIFFICULTY-HARDEST
  8. Poplimit beállítások
    1. POPULATION-CAP-25
    2. POPULATION-CAP-50
    3. POPULATION-CAP-75
    4. POPULATION-CAP-100
    5. POPULATION-CAP-125
    6. POPULATION-CAP-150
    7. POPULATION-CAP-175
    8. POPULATION-CAP-200
    9. POPULATION-CAP-225
    10. POPULATION-CAP-250
  9. Játéksebesség beállítások
    1. GAME-SPEED-LOCKED
  10. Játékoselhelyezési beállítások
    1. TEAMS-LOCKED („rögzített” csapatok: a szövetségesek nem a térképen össze-vissza kezdenek, hanem egymás szomszédságában)

A load parancs

szerkesztés

E parancs képessé tesz egy szkriptet arra, hogy megszakítsa a futást, betöltsön egy másik szkriptet egy másik fájlból, majd annak befejeztével folytassa az anyaszkript futtatását.

Szintaktikája - mondanom sem kell - egyszerű:


(load "fájlnév")

A fájlnév egy olyan per fájl neve kell hogy legyen, a kiterjesztése nélkül, amely vagy a SWGB mappa\Game\AI mappában található, vagy pedig annak egy almappájában - ez utóbbi esetben azonban meg kell adni az almappát is. Például:

-) Ha a Testguy.per fájl elérési útja C:\Window\Lucas_Arts\SWGB\Game\AI\Testguy.per, akkor a parancs így fog kinézni:


(load "Testguy")

-) Ha a Testguy.per fájl elérési útja C:\Window\Lucas_Arts\SWGB\Game\AI\Modules\Testguy.per, akkor a parancsot a következőképp kell alkalmazni:


(load "Modules\Testguy")

Jótanácsok és megjegyzések:

  1. Ne felejtsd el a fájlnevet idézőjelek közé tenni!!
  2. Ha a fájlnév szóközt tartalmaz, az a parancsban _ jellel helyettesítendő. Pl. a Gode Takrab.per fájlra így kell hivatkozni: "Gode_Takrab".
  3. A fájl bármely helyén lehet, két szabály között(!), alkalmazni;
  4. Nem teszteltem, hogy kézszenzitív-e. Tanácsos a nagybetű-kisbetű megkülönböztetésre odafigyelni;
  5. A fájlbetöltések is egymásba ágyazhatóak, 10 szint mélységig. Tehát ha betöltök az anyaszkriptbe egy leányszkriptfájlt, abban lehetnek betöltőparancsok, amelyekben betöltenek unokaszkripteket, azokban is lehetnek újabb betöltőparancsok ... egészen a tizedik nemzedékig.
  6. Be lehet ágyazni a load-if típusú parancsokba.
  7. Sajnos, nem lehet defrule parancsba ágyazni.
  8. Sajnos, fogalmam sincs, hogy lehetséges-e a sztenderd szkriptet betölteni, vagyis hirtelen arra kérni a CP-t, hogy most kezdjen el a gamedata.drs-beli alapértelmezett viselkedés szerint játszani. Jelenlegi ismereteim szerint erre nincs mód. Ha üres nevet (nincs hozzá fájl) vagy szintaktikai hibás parancsot töltünk be, akkor a CP sajnos nem az alapértelmezéshez tér vissza, hanem kizárólag széngyűjtést fog végezni.

A load-random parancs

szerkesztés

A load-random parancs néhány megadott fájl közül véletlenszerűen kiválaszt egyet, és azt betölti.

Használata:


(load-random esély1 "fájlnév1" esély2 "fájlnév2" ... esélyn "fájlnévn" "mégegyfájlnév")


Az esély x.-ek helyébe egyszerűen egész számokat kell írnunk, melyek összege kisebb száznál (vagy egyenlő vele); ez az a valószínűség lesz (százalékban megadva), amely eséllyel a fájlnév x. betöltődik. A legutolsó fájlnév akkor töltődik be, ha a többi nem, akkora eséllyel, amekkorát a többiek esélyei hagytak neki (a többi összegét kivonjuk százból).

Például:


(load-random 10 "AngryEmpire" 20 "ShyEmpire" ... 40 "T-2Gunga" "FedTrader")

esetén 10% eséllyel töltődik be az AngryEmpire.per fájl, 20% eséllyel a ShyEmpire.per; 40% eséllyel a T-2Gunga.per fájl, és 100%-(10%+20%+40%)=30% eséllyel a FedTrader.per fájl.

A fájlnevekre, elérési utakra vonatkozóan ugyanaz érvényes, mint amit a load parancs esetén mondtunk.

Az utolsó fájl megadása egyébként nem kötelező, el is maradhat. Ekkor a sztenderd AI töltődik be, vagy semmi, és csak szenet fog gyűjtögetni. Jó kérdés.

Az is lehetséges, hogy csak az utolsó fájlt adjuk meg, vagyis egyetlen fájlt esélyek nélkül. Ennek nagyjából ugyanaz a hatása, mint a load parancsnak, csak - Balbarian szerint - sokkal jobban megterheli a számítógép erőforrásait, lassabb lesz.

Egyszóval elmaradhat az esélymegadásos rész, de elmaradhat az esélymegadás nélküli fájl is. Amit ne felejtsünk el továbbra sem, hogy nem maradhat el az idézőjel a fájlnevek körül!

Szabályok: a defrule parancs

szerkesztés

A parancsnak kétféle nagyon eltérő használata is van. Az egyszerűbb szintaktikájú változat a kevésbé használt vagy kevésbé finom szabályzást lehetővé tévő: amennyiben a feltételek teljesülnek, úgy a parancs alapértelmezésben vég nélkül végrehajtódik, újra és újra. Ezt nyílt végrehajtású, röviden nyílt szabálydefiniálásnak nevezzük.

Egy (alig valamivel) bonyolultabb szintaktikájú változat, amelyet talán többször használunk, vagy legalábbis ami az akcióknak a szituációhoz való finomabb hangolását lehetővé teszi, a vég nélkül folytatódó parancs egyszerivé tétele. Ez úgy érhető el, hogy egy speciális, (disable-self) azonosítójú akcióval zárjuk le az akciók sorát. Az ilyen akcióval záródó szabályt zárt végrehajtású, röviden zárt szabálydefiniálásnak fogom hívni.

A defrule parancs egyszerű vagy nyílt végrehajtású használata

szerkesztés

Végre rátérhetünk a szkriptírás lelkét képező szabályok alkotására, vagyis a defrule parancsra. A szabályok két fő részből állnak: fejrész avagy feltételek (facts), és lábrész avagy akciók (actions).

Szintaktikája a következő:


(defrule tények => akciók )

Vagyis minden defrule parancs zárójeltől zárójelig tart, a tények és akciók között pedig a kondicionális avagy implikáció nevű logikai művelet egyezményes jele, egy nyilacska áll. A nyilacska egy egyenlőségjelből és egy balra nyitott kacsacsőrből van összetéve.

Ezt a parancsot az áttekinthetőség kedvéért enterekkel gyakran sorokra daraboljuk, így:


(defrule
 (tény 1)
 (tény 2)
 ...
 (tény n.)
=>
 (akció 1)
 (akció 2)
 ...
 (akció m.)
)

A tényeket és akciókat is zárójelbe kell tenni; hogy előttük és utánuk hány szóköz vagy tabulátor áll, az lényegtelen.

A sor - itt jegyezzük meg - entertől enterig tart. Ennek a hibakeresésben van jelentősége. Tehát a fenti szabályt egy sorba is írhatjuk, meg több sorba is, és ekkor a hibakereső más-más sort jelöl meg hibásként, ha talál hibát (a sor tehát ilyen értelemben a szkriptnyelven kívüli fogalom, az értelmezőprogram számára nincs jelentősége).

Egy egyszerű példa:


(defrule
 (game-time >= 600)
 (current-age == tech-level-2)
=>
 (chat-to-all "Ez a techlevel-2")
)

Ez a szabály azt fogja eredményezni, hogy ha a játékidő elérte a tizedik percet (600 mp.), és még az is igaz, hogy a játékos már kikutatta a tech-level-2-t (a kutatás már befejeződött, nem csak folyamatban van), akkor a képernyőre ki fogja írni a hatvanadik perc környékétől - folyamatosan, kb. fél másodpercenként - hogy „ez a techlevel-2”. A kiírás késhet egy kicsit, ha abban a pillanatban mondjuk épp a többi játékos is megereszt hasonló chat-üzenetet, de nem túl sokat, mondjuk négy másodpercet.

A defrule parancs zárt végrehajtású változata

szerkesztés

Szinte ugyanazt elmondhatjuk, amit már a fenti szakaszban is mondtunk, casak az egyetlen különbség, hogy a parancs egyszer hajtódik végre, aztán az értelmező alprogram elfelejti, hogy valaha is volt ilyen szabály. Vagy talán: dehogyis felejti el, hanem holta napjáig emlékszik rá, hogy már végrehajtotta egyszer ... ugyan melyik szkriptíró, az Ensemble Studios munkatársain kívül, látott is bele valaha igazán egy értelmező alprogram lelkébe? ... Menjünk tovább: a zárt defrule parancs, ahogy mondtuk, különös módon ugyanolyan, mint a nyílt, csak tartalmaz egy plusz akciót, a lezárást, amely a (disable-self) nevet viseli. Szintaktikája a következő:


(defrule tények => akciók (disable-self) )

Vagyis minden defrule parancs zárójeltől zárójelig tart, a tények és akciók között pedig a kondicionális avagy implikáció nevű logikai művelet egyezményes jele, egy nyilacska áll. A nyilacska egy egyenlőségjelből és egy balra nyitott kacsacsőrből van összetéve.

Ezt a parancsot az áttekinthetőség kedvéért enterekkel gyakran sorokra daraboljuk, így:


(defrule
 (tény 1)
 (tény 2)
 ...
 (tény n.)
=>
 (akció 1)
 (akció 2)
 ...
 (akció m.)
 (disable-self)
)

A tényeket és akciókat is, még mindig, zárójelbe kell tenni; hogy előttük és utánuk hány szóköz vagy tabulátor áll, az továbbra is lényegtelen. A sor entertől enterig tart, stb. stb.

Egy egyszerű példa:


(defrule
 (game-time >= 600)
 (current-age == tech-level-2)
=>
 (chat-to-all "Ez a techlevel-2")
 (disable-self)
)

Ez a szabály azt fogja eredményezni, hogy ha a játékidő elérte a tizedik percet, és még az is igaz, hogy a játékos már kikutatta a tech-level-2-t (a kutatás már befejeződött, nem csak folyamatban van), akkor a képernyőre ki fogja írni a hatvanadik perc környékén - immár nem folyamatosan, kb. fél másodpercenként, hanem csak egyszer, hogy „Ez a techlevel-2”. A kiírás késhet egy kicsit, ha abban a pillanatban mondjuk épp a többi játékos is megereszt hasonló chat-üzenetet, de nem túl sokat, mondjuk négy másodpercet.

Lehet, hogy a feltételek még fél óra múlva is teljesülnek, akár folyamatosan, akár megszakítva. Ez nem számít: ha azt akarjuk, hogy még egyszer megismétlődjenek az akciók, akkor még egyszer bele kell írnunk a szabályt a szkriptbe.

Most már csak azzal kell tisztába jönnünk, mik a lehetséges feltételek és mik a lehetséges akciók, és kezdődhet is a munka.

A két használat eltérő funkciója

szerkesztés

Ugye nem szeretnénk, hogy CP-nk azzal pazarolja a drága novát, hogy kétszáz Jedi-templommal beépíti a térképet? Az ellenségek nem is hagynák neki, ez nem okos viselkedés. Tehát ennek megakadályozására kell a (disable-self) parancs. Különben már az első kapott parancsot vég nélkül ismételné, a többire sem ideje, sem erőforrása nem jutna.

Amikor úgy építkezünk, hogy egy épületből elég egy-kettő, vagy olyan drága, hogy csak ennyi telik ki, vagy az épületnek nagyon fontos stratégiai funkciója van (pl. erőd, második parancsnoki központ, őrtorony), vagy amikor választani kell az egységek fejlesztése és bizonyos kulcsfontosságú védőegységek számának növelése között, az ilyen parancsok időzítésére zárt végrehajtású szabályokat szoktunk használni, mégpedig alaposan megrágott és oda-vissza átgondolt, húsz állapotváltozóval szabályzott feltételekkel. Ez a zárt aktorgenerálás.

Vannak azonban könnyen elpusztuló épületek, melyeket egy bizonyos szintet elérve már nem nagy megrázkódtatás újjáépíteni, és szükség van rájuk. Ilyenek pl. a házak. Az egyszerűbb szerkesztésű CP-k esetében az ilyen épületek pótlása gyakran nyílt végrehajtású szabályokkal történik: „Ha a házak száma kisebb harmincnál, építs új házat.” Az ilyen nyílt, disable-self akcióval le nem zárt parancsot a CP egészen addig fogja ismételten végrehajtani, mígnem a házak száma eléri a harmincat. Ha egy ház elpusztul, és képes pótolni (van szén és van egy szabad munkás), akkor automatikusan pótolja. Ez a nyílt aktorgenerálás.

Parancselemek és a defrule-ra vonatkozó korlátozások

szerkesztés

A defrule parancs nagyon összetetté válhat, hiszen elemeiként logikai operátorokkal összekapcsolt tények, és számtalan féle akció (amik önmagukban is összetettek) felléphetnek.

Az akciókat, tényeket és logikai operátorokat ("or", "not", "and", valamint - az AoK szkriptnyelvben használható még, de az SWGB esetében nem teszteltem - "nor" és "nand") a szabályok elemeinek nevezzük.

Az Age of Kingsben egy szabály 16 elemet tartalmazhatott maximum, ennél hosszabb szabályra az értelmezőprogram hibaüzenetet adott. Ha a load-if parancsot nem használta egy szkript, akkor maximum 999 defrule parancs használata volt lehetséges. Egyébként a goal-ok száma is korlátozva volt 40-reAoK Heaven AI Scripting FAQ.

A SWGB szkriptnyelvében a korlátozások kicsit kevésbé szigorúbbak.

Hivatkozások

szerkesztés

Megjegyzések

szerkesztés
  1. Ez a felosztás, bár kétségtelenül használható, meglehetősen durva, ami nagyon sok jelenséget egy kalap alá vesz. Az értelmező alprogram szempontjából kétségtelenül elfogadható, hogy pusztán ez a két típus van. Az AI-szkripter azonban e nyelv megtanulásakor azzal szembesül, hogy azok a jelenségek valóságdarabok), amelyeket a nyelv sztringjeivel és szimbólumaival megnevez, a játék, a játékos, a szkripter szempontjából teljesen máshogy csoportosíthatóak értelmes rendszerré. A csoportosítást elvégezni azonban csak akkor érdemes, ha már az egész nyelvvel, minden foglalt szavával megismerkedtünk.
  2. Matematikai nyelven szólva: a "neveim -> számaim" hozzárendelés tehát függvény kell, hogy legyen, de fordítva ez nem szükséges, a függvénynek nem kell injektívnek lennie.
  3. Ez a szakasz pusztán, vagy főleg, egyik fentebbi mondatunknak, „Egy számnak lehet különböző neveket adni.”, kívánja magyarázatát nyújtani - bővebbre, mélyebbre, vagy pusztán csak hosszabbra.