LINK href="stylusvkhr.css" rel=STYLESHEET>


TÁBLAJÁTÉKOS:

Zillions progi-suli

Hát! Alig kezdek beindulni, máris igazat kell adnom az észrevételnek:
"Ha ilyen lassan haladunk, mikor fogunk saját progit írni?"
Felhasználva, hogy már van néhány egyszerűbb magyar progi a Zillire
gyorsabban haladhatunk az Zilli-nyelv megtanulásában,
ha az azok még működő lerövidítését próbáljuk meg értelmezni.
Előbb-utóbb sor fog kerülni mindegyik utasításra...

4. A tologatós amőba
A játék lényege, hogy a játékosok a tábla széléről befelé töltögetik a táblát. A tábla valamelyik szélső mezőjére -kivéve a sarkokat- teszik le a golyójukat, majd ugyanabban a lépésben egy pozícióval beljebb tolják.

Ezzel persze a már táblán lévő, a letett melletti golyó (golyósor) is egy pozícióval beljebb kerül. A tábla széle tehát körben mindig üresen marad. Ha egy sor megtelt, akkor abba már több (újabb golyó) nem tolható be, ilyen esetben pedig már a szélre való lerakás is tilos. A partit az nyeri, akinek előbb jön össze nyerő a négyese -éppúgy, mint az AMŐBA-ban-.
A lentebb mutatott két (hosszab és rövidebb) ZRF megértése betekintést ad abba, hogyan magyarázhatjuk meg a Zilli-nek ezeket a (lerakást is és mozgatást is tartalmazó) lépéseket.

Emlékeztetőül, mindkét zrf-ben megtalálható öt "alapblokk":

  • általános pl.: a játék neve, kétszemélyes, lépéskényszeres, játékosok sorrendje, hanghatások, leírások, helpek, stb.
  • táblakép, mezőszámozás, mezők "szomszédjai"...

  • bábuk neve, képe, lépéslehetőségei

  • kezdőállás

  • nyerő-, ill. vesztő (döntetlen) helyzetek

    Ezt az öt blokkot vezeti fel a (game megnyitás, az öt blokk végét pedig a megnyitott zárójel ) bezárása jelzi.
    Ez ötös "főcsoport" előtt a többször használt programsorokat (define ... ) formába zárva, az ötös egység után pedig a változatokat jellemző eltéréseket (variant ... ) formába zárva szokás rendszerezni.
  • Szokás? Úgy tűnik az eddig elkészült progik többsége ezt a struktúrát követi.
    Egyébként nincs sorrendi probléma! Az ábrán keretezett blokkok sorrendjét teszőlegesen összekeverve is képes megérteni a ZRF-et feldolgozó/végrehajtó Zillions.exe progi. Ne feledjük! A zrf logikailag nem jelenthet többet, mint a Zillions.exe beállítási- és "input"-adatait. Az exe sok-sok alapértelmezett (automatikusan felvett) beállítással dolgozik, ezeket írja felül, illetve ezeket egészíti ki a zrf. Érdemibb dolog feltehetően csak akkor indul el az exe-vel, ha már az összes ilyen beállítási "input" rendelkezésére áll, ezeket pedig sorrendiség nélkül is értelmezni tudja. A "szokást" mégis javasolt betartani azért, hogy magunk is és mások is könnyebben eligazodjunk egy-egy kész zrf piszkálásakor.
    Ebből viszont az következik, hogy a zrf fenti szokás szerint leírt utasításlistájának sorfolytonos értelmezése csak a Games blokkon belül követi az információk logikusan egymásra épülő sorrendjét.

    Egy ismeretlen zrf tartalmának értelmezését a (games ... ) blokkban kell kezdeni.
    Az alábbi zrf-listák olvasási/értelmezési sorrendjét a magyarázó szöveg számozása jelzi.
    Induljunk el az 1. től!

    A ZRF-eket is és a képeket is megtalálod a kitömörített munka 4 könyvtár-ban.
    (Hálóról nem indul, de letölthető: munka4.zip (20 kB))


    ;***********************************************
    ; tologatos AMŐBA: négy a nyerő 7x7
    ;(direkt címzésű mozgatás)
    ;lásd a munka4/TOL_SULI02.ZRF
    ;***********************************************

    (Ide a 9-re utolsóként!!! Kezdeni az 1.től!!!)
    9.. A Zillions.exe nem értelmezi a ";" után írtakat egészen az adott sor végéig. Ennek funkciója, hogy magyarázó szövegeket írhassunk a zrf-be, netán (pl. az egyes blokkokat a kilistázáskor szemléletesen elkülönítő jelzéseket helyezhessünk el akár az értelmezett sorok végére, akár az értelmezett sorok közé.


    (define def1l (verify (in-zone? keretl) ) (verify empty?) n

    (if empty? s add-partial else n
    (if empty? s s add-partial else n
    (if empty? s s s add-partial else n
    (if empty? s s s s add-partial else n
    (if empty? s s s s s add-partial else n
    (if empty? s s s s s s add-partial else n
    (if empty? s s s s s s s add-partial ) ) ) ) ) ) )
    )
    (define def1f (verify (in-zone? keretf) ) (verify empty?) s (if empty? n add-partial else s
    (if empty? n n add-partial else s
    (if empty? n n n add-partial else s
    (if empty? n n n n add-partial else s
    (if empty? n n n n n add-partial else s
    (if empty? n n n n n n add-partial else s
    (if empty? n n n n n n n add-partial ) ) ) ) ) ) ) )
    )
    (define def1b (verify (in-zone? keretb) ) (verify empty?) e (if empty? w add-partial else e
    (if empty? w w add-partial else e
    (if empty? w w w add-partial else e
    (if empty? w w w w add-partial else e
    (if empty? w w w w w add-partial else e
    (if empty? w w w w w w add-partial else e
    (if empty? w w w w w w w add-partial ) ) ) ) ) ) ) )
    )
    (define def1j (verify (in-zone? keretj) ) (verify empty?) w
    (if empty? e add-partial else w
    (if empty? e e add-partial else w
    (if empty? e e e add-partial else w
    (if empty? e e e e add-partial else w
    (if empty? e e e e e add-partial else w
    (if empty? e e e e e e add-partial else w
    (if empty? e e e e e e e add-partial ) ) ) ) ) ) ) )
    )

    4. "def1l", "def1f", "def1b", def1j" (láthatóan szinte ugyanolyan) négy "define", melyeket egyenként hív meg a zrf piece blokkjának drops utasítása. Mit "ért meg" ezekből a Zilli? Vegyük sorra pl. a "def1l" nevű utasításait!
    Vizsgáld át (verify) a mezőket a táblán és a továbbiakban vesd el mindazokat, amelyek nem a "keretl" nevű zónában vannak (in-zone?) és nem üresek (empty?)!
    A megmaradó mezők közül sorra mindegyik mezőről lépj felfelé egyet (n) és mindegyik esetben végezd el a következőket!
    Ha üres (if empty?) a mező, akkor lépj vissza (s) és azt a mezőt, ahol állsz írd be azok közé (add), amik közül az adott lépés majd szabadon kiválasztható!
    Fontos megjegyzés: a "-partial" azt jelzi, hogy ennek a lépésnek megtétele után még más is következhet, azaz a nyerőhelyzet vizsgálatát későbbre halasztja. Ez két okból is fontos:
    a./ Egyrészt nem állítja le a partit, ha egy részlépés közben nyerőhelyzetet észlel.
    b./ Másrészt (és erről nem szabad megfeledkezni) az ellenlépés keresésekor, ezen részlépések eredményének értékelő figyelembevétele is elmarad.
    Mi történik tehát ezekben az "if"-sorozatokban? A tábla alsó sorának mindegyikéből (kivéve a sarkokat) külön-külön újra kezdve, elindul felfelé és egyenként megvizsgálja, hogy ahol áll, az üres-e. Ha így talál egy üres mezőt, akkor visszamegy az indulási mezőre és annak pozíció-azonosítóját hozzáadja az adott lépésben választhatók közé.
    Nézzük pl. a "def1l" utolsó if-sorát! Amikor ezt vizsgálja, akkor az előző hat mezőn a korábbi vizsgálatokkor mindig talált valamilyen bábut (az "else"-k ágán jutott ide). Ha a hetedik üres, akkor héttel ( s s s s s s s ) visszalépve, újra az induló mezőn van, amit hozzáad a lehetséges lépésekhez. Ha a hetedik sem üres, akkor abba az oszlopba már nem enged lerakni.
    Vegyük észre azt, hogy a fentiek a tábla összes mezőjének értékelésével választják ki, mint lépéslehetőségeket, a fenti táblakép alsó nyílsorával jelzettek közül azokat, amelyek felett legalább egy üres hely van (ami ugye kell a betoláshoz).


    (define def2b

    ( w
    (if (in-zone? bal) (go from)
    (while not-empty? cascade from w to) add
    ) )
    )
    (define def2j
    ( e
    (if (in-zone? jobb) (go from)
    (while not-empty? cascade from e to) add
    ) )
    )
    (define def2l
    ( s
    (if (in-zone? fent) (go from)
    (while not-empty? cascade from s to) add
    ) )
    )
    (define def2f
    ( n
    (if (in-zone? lent) (go from)
    (while not-empty? cascade from n to) add
    ) )
    )

    5. Itt is négy nagyon azonosnak tűnő define blokk van, amiket a piece blokk move utasítása hív be. A lerakáskor megismertek alapján, az a várakozásunk, hogy ezeknek a kimenetén is megjelenik a (szabályokat betartó) összes lépéslehetőség. Így igaz, de fontos észrevenni azt a különbséget, hogy a mozgatás (move) elsődlegesen a már táblán lévő bábuhoz kapcsolható és ezért nincs szükség a tábla összes mezőjének értékelésére. Ezt "tudja" is a Zilli, mert a move "értelmezése" mindig a táblán lévő bábuk helyzetéből indul.
    Nézzük pl. a legutolsót, a def2f-et! Mit érthet ezen a Zilli?
    Vedd sorra a soron következő játékos táblán lévő bábuit és az alábbiakat mindegyikkel csináld végig.
    Lépj fel a bábuval szomszédos mezőre (n) Ha most a "lent" nevű zónán állsz, akkor jegyezd meg mi volt ott a rálépés előtt (go from)???
    Innen már gőzőm nincs, hogyan gondolkodik a Zilli... A "cascade" utasítást kellene alaposabban megismerni, hogyan működik együtt a "while" utasítással. A "while" az utána megadott feltétel teljesüléséig folyamatosan végrehajtja a feltétel után megadott utasítást.
    Ha már megértettem, majd igyekszem pótolni, addig is legyen elég a kísérletezéshez az, hogy: szándék és működés szerint a def2f kiválasztja mindazokat a sortolási lehetőségeket, amelyeknél az alsó nyílon lévő golyó, a vele közvetlenül érintkező felette lévőket egy pozícióval eltolva, maga is feljebb kerül. a 6.-nál folytatódik !!!


    (game

    (title "tologatós AMŐBA: négy a nyerő 7x7")
    (players White Black)
    (turn-order White Black )
    (pass-turn false)
    (animate-drops false)

    1. Az általános blokk tartalmával foglalkoztunk a 2.progisuliban .

    Az itt/most még nem ismert utasítás azt tiltja meg (false=hamis), hogy a Zillions.exe minden újonnan lerakandó bábut (az alaphelyzetében értelmezett) felülről lefelé csúsztatott animációval hozza a táblára. Vajh, melyik lehet?


    (board

    (image "images\Tolos\tolos7x7.bmp")
    (grid
    (start-rectangle 15 15 43 43 )
    (dimensions
    ("a/b/c/d/e/f/g/h/i" (28 0) )
    ("9/8/7/6/5/4/3/2/1" (0 28) )
    )
    (directions (e 1 0) (ne 1 -1) (nw -1 -1) (s 0 1) (n 0 -1) (w -1 0) )
    )
    (zone (name bal) (players White Black )
    (positions h2 h3 h4 h5 h6 h7 h8)
    )
    (zone (name jobb) (players White Black)
    (positions b2 b3 b4 b5 b6 b7 b8)
    )
    (zone (name fent) (players White Black)
    (positions b8 c8 d8 e8 f8 g8 h8)
    )
    (zone (name lent) (players White Black)
    (positions b2 c2 d2 e2 f2 g2 h2)
    )
    (zone (name keretj) (players White Black )
    (positions i2 i3 i4 i5 i6 i7 i8)
    )
    (zone (name keretb) (players White Black)
    (positions a2 a3 a4 a5 a6 a7 a8)
    )
    (zone (name keretf) (players White Black)
    (positions b9 c9 d9 e9 f9 g9 h9)
    )
    (zone (name keretl) (players White Black)
    (positions b1 c1 d1 e1 f1 g1 h1)
    )
    )

    2. A tábla képének, a mezők kiosztásának, a mezők számozásának értelmezésével részletesen foglalkoztunk a 3. progisuliban

    Ehhez azt is meg kell még adni, hogy milyen irányokra (directions...) fogunk majd a zrf-ben hivatkozni, pontosabban: egy-egy mezőről milyen irányokban juthatunk el egy másik mezőre. Itt, most hat irány van megadva: "n", "ne"... nevekkel és " 0 ,-1 " , " 1 , 1 " pozíciókkal azonosítva.
    A Zillions.exe a tábla mezőit a sorok és az oszlopok "grid"-ben megadott osztása szerint már ismeri. Kétdimenziós táblánál, az egymástól zárójelezéssel elválasztott iránymeghatározásokban az elso szám pozitív értéke a jobbra eső mezőre, a másik szám pozitív értéke a lefelé eső mezőre mutat. (Pl.: a " 1, -1 ", "egyet jobbra, egyet fel", az adott mezőtől átlósan felfelé eső szomszédra irányít. A könnyű megjegyezhetőség céljából, többnyire az égtájak kezdőbetűit javasolt irányazonosítónak alkalmazni: n-nord Észak, s-süd Dél, e-east Kelet, w-west Nyugat...)

    Meglehetősen hosszú a zone-azonosítók sora, de értelmezésük kézenfekvő: megadják egy-egy valamilyen célból azonosnak tekinthető mezők pozícióit és a csoportoknak (mint zónáknak) a későbbi hivatkozások egyértelműsítése céljából neveket adnak. Egyszersmind arról is rendelkezik ez a zónadefiniálás, hogy az adott zóna fehér és fekete játékosra egyaránt értelmezhető. Pl: a "bal" elnevezésű zóna a 9x9-es tábla jobb oszlopának, de a sarkokat nem tartalmazó mezőit jelenti és az erre majd valahol megadottak mindkét játékosra vonatkoznak.)


    (piece (name golyo)

    (image White "images\Tolos\WDisk.bmp" Black "images\Tolos\BDisk.bmp")
    (drops ( (def1l)) ((def1f)) ((def1j)) ((def1b)) )
    (moves (def2b)(def2j)(def2l)(def2f) )
    )

    3. Lehetnek "golyo" nevű bábuk. Ha fehéré, akkor a megadott könytár WDisk.bmp-ben (ha feketéé, akkor BDisk.bmp-ben) megadott képpel kerülhet a tábla valamelyik mezőjére.
    Vagy lerakással (drops), vagy a táblán való elmozgatással (move) változtathatja helyét a (még mindig a "golyo" nevű) bábu.
    A lerakás is és a mozgatás is 4-4 féle, a define-k között "def1l", "def2l"... nevű utasítás- lista szerint történhet. !!!Érdekes, hogy a dropsnál dupla zárójelezést kell alkalmazni!!! a 4. alatt folytatódik !!!

    (board-setup (White (golyo off 99))(Black (golyo off 99)))

    6. Nyitáskor, mindkét játékosnak 99-99 db golyója van. (Ebben a játékban a darabszámnak nincsen szerepe, de ha egy "lerakásosban" bármikor elfogy a golyó a Zilli lépésképtelenséget jelez.)


    (win-condition (White Black)

    (or (relative-config golyo n golyo n golyo n golyo )
    (relative-config golyo e golyo e golyo e golyo)
    (relative-config golyo ne golyo ne golyo ne golyo)
    (relative-config golyo nw golyo nw golyo nw golyo)
    )
    )

    7. Ha fehérnek vagy feketének, bármelyik befejezett lépése után (White Black),
    bárhol a táblán vagy n, vagy e, vagy ne, vagy nw irányban 5 db golyója van, akkor nyert és vége van a partinak.
    A relatív-config jelzi, hogy a bábuknak egymáshoz viszonyított helyzete dönti el a partit. (Más játékokban az absolut-config arra mutat, hogy a bábuknak a tábla valamely mezőihez viszonyított helyzete a döntő.)


    )

    8. Games vége (a variantok nélküli zrf vége).


    A következő zrf-lista az előzővel teljesen azonos eredményre vezet.
    Ugyanarra a játékra "tanítja meg" a Zillit, mint az előző.
    Rövidsége a define-k parametrizálásának köszönhető. Miután a fentihez képest egyetlen új utasítást sem használ, nagyon jó gyakorlatnak ígérkezik, ha a fent részletezett zrf-et

    próbáljuk meg saját magunk lerövidíteni !

    Amit tudni kell hozzá, az kézenfekvő igényként felmerül a fenti zrf-lista ismétlődéseinél: ha a define-k behívásakor megadhatnánk, hogy az s/n, n/s, e/w, w/e iránypárosok közül melyik kettőt használja, akkor a zónák összevontabb kialakításával, a 4 db define helyett elegendő lenne 1 db-ot megírni. (Ez persze később majd csak programmozói elegancia kérdése lesz, hiszen sokkal munkásabb, mint négyszer lecopyzni és átírni a változásokat. De most a gyakorláshoz feltétlenül nagyon hasznos.)
    A Zillions.exe a "define"-ben található $1, $2, $3, ... jeleket olyan paraméter-változóknak tekinti, amelyek a behíváskor kapnak értéket.

    A CD-ről telepített Birodalomban, egyszerűsített formában, az alább listázott TOL_SULI01.ZRF, piszkálható munkakönyvtárban, csak a működéshez feltétlen szükséges utasításokat tartalmazza...
    A zrf-listák közül nagyon ajánlom még értelmezésre Salvi Peti első progiját: HG_Japan.zrf Angoltudás hiányában, magam is ebből indultam el.
    Sok sikert kívánok mindegyikhez... (Nagylaci)

    ;*************************************************************************************************
    ; tologatos AMŐBA: négy a nyerő 7x7 (direkt címzésű mozgatás) TOL_SULI01.ZRF
    ;*************************************************************************************************
    (define lerak
    (if (in-zone? keret) $1
    (if ( and empty? (not-in-zone? keret )( not-in-zone? sarok)on-board?)
    $2 add-partial else $1
    (if ( and empty? (not-in-zone? keret )( not-in-zone? sarok)on-board?)
    $2 $2 add-partial else $1
    (if ( and empty? (not-in-zone? keret )( not-in-zone? sarok)on-board?)
    $2 $2 $2 add-partial else $1
    (if ( and empty? (not-in-zone? keret )( not-in-zone? sarok)on-board?)
    $2 $2 $2 $2 add-partial else $1
    (if ( and empty? (not-in-zone? keret )( not-in-zone? sarok)on-board?)
    $2 $2 $2 $2 $2 add-partial else $1
    (if ( and empty? (not-in-zone? keret )( not-in-zone? sarok)on-board?)
    $2 $2 $2 $2 $2 $2 add-partial else $1
    (if ( and empty? (not-in-zone? keret )( not-in-zone? sarok)on-board?)
    $2 $2 $2 $2 $2 $2 $2 add-partial ) ) ) ) ) ) ) )
    )
    (define eltol ($1 $2
    (if ( in-zone? keret ) $1
    (if ( and ( not-in-zone? keret )on-board? (not-in-zone? sarok) (go from)
    (while not-empty? cascade from $1 to) add ) ) )
    )
    (game
    (title "tologatós AMŐBA: négy a nyerő 7x7")
    (players White Black)
    (turn-order White Black )
    (pass-turn false)
    (animate-drops false)
    (board
    (image "images\Tolos\tolos7x7.bmp")
    (grid
    (start-rectangle 15 15 43 43 )
    (dimensions
    ("a/b/c/d/e/f/g/h/i" (28 0) )
    ("9/8/7/6/5/4/3/2/1" (0 28) )
    )
    (directions (e 1 0) (ne 1 -1) (nw -1 -1) (s 0 1) (n 0 -1) (w -1 0) )
    )
    (zone (name keret) (players White Black)
    (positions b1 c1 d1 e1 f1 g1 h1 b9 c9 d9 e9 f9 g9 h9
    a2 a3 a4 a5 a6 a7 a8 i2 i3 i4 i5 i6 i7 i8 )
    )
    (zone (name sarok) (players White Black)
    (positions a1 a9 i9 i1)
    )
    )
    (piece (name golyo)
    (image White "images\Tolos\WDisk.bmp" Black "images\Tolos\BDisk.bmp")
    (drops
    ((lerak n s)) ((lerak s n)) ((lerak w e)) ((lerak e w))
    )
    (moves
    (eltol w e)(eltol e w)(eltol s n)(eltol n s)
    )
    )
    (board-setup (White (golyo off 99))(Black (golyo off 99)))
    (win-condition (White Black)
    (or (relative-config golyo n golyo n golyo n golyo )
    (relative-config golyo e golyo e golyo e golyo)
    (relative-config golyo ne golyo ne golyo ne golyo)
    (relative-config golyo nw golyo nw golyo nw golyo)
    )
    )
    )

    (folyt.)