LINK href="stylusvkhr.css" rel=STYLESHEET>
TÁBLAJÁTÉKOS:

Zillions progi-suli

Kb. 20 órám van a Labirintus-zrf-ben.
Most hozzáteszem még azt a 2-3-at, melyet arra szánok,
hogy összefoglaljam tapasztalataimat...

6. A "DROPS"-utasításra kiváltott mozgások

A gurigázós labirintus lényege, hogy egy labirintuspályát tartalmazó játékmezõre golyókat rakunk, majd a pálya eldöntögetésének sorozatával, egy elõre meghatározott célhelyzetbe hozzuk a golyókat. Egy-egy "lépésként" kiválasztott irányban lejtõsnek tekintve a labirintuspályát, az azon lévõ golyók nyílirányban ütközésig elgurulnak.

Az alapfeladvány kezdõállását mutatja az ábra. Cél: a két golyó helycseréje.
A játék akkor mûködik komfortosan a Zilli-vel, ha egy-egy (kiválasztott nyílra történõ) kattintás egyszersmind automatikusan kiváltja mindkét golyó elmozdulását. Erre olyan megoldás a legelõnyõsebb, mely több golyó esetére is alkalmazható.

Három logikai blokkot kell megértetni a Zillivel:

a./ Engedjen kattintani egy nyílra.
b./ Találja meg a táblán a golyókat.
c./ Gurítsa el õket a választott irányban.

Ezek sorbavételéhez már tekintsük ismertnek a táblát, az e, w, s, n irányokkal együtt és azt, hogy a tábla mezõire: FREE(üres)-t, BRIKS(fal)-t, RED(piros) golyót, GREEN(zöld) golyót, _e / _w / _s / _n (jobb/bal/le/fel) nyilakat, mint bábukat helyezhetünk el.
(board (image "Images\Labirintus2\Blank.bmp") ;üres tábla, amire tetszõleges pálya építhetõ
(grid (start-rectangle 15 15 30 30)
(dimensions
("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/u/v/y/t/w" (15 0)) ; oszlopok balról jobbra
("16/15/14/13/12/11/10/9/8/7/6/5/4/3/2/1" (0 15)) ; sorok felülrõl lefelé
)
(directions (n 0 -1) (e 1 0) (s 0 1) (w -1 0))
)
(kill-positions ;a nyilak helye miatt 3-al szélesebbre vett tábla nem használt mezõi
y1 y3 y4 y5 y6 y7 y8 y9 y10 y11 y12 y13 y14 y15 y16
t2 t4 t5 t6 t7 t8 t9 t10 t11 t12 t13 t14 t15 t16
w1 w3 w4 w5 w6 w7 w8 w9 w10 w11 w12 w13 w14 w15 w16)
) ;end board

(board-setup
(Solo ; minden bábut a "Solo" nevû játékos mozgathat ... FREE/BRIKS... ;beleértve a labirintus, itt most nem részletezett, felépítését is.
(GREEN k9)(RED j8) (_n t3 off 100)(_s t1 off 100)(_e w2 off 100)(_w y2 off 100)
)
) ;end board-setup

a./ ha a nyilakat hordozó bábuk (board-setup)-ban megadott helyét a bábuleírásoknál (drops...)-ban megadjuk (lásd alább), akkor bármelyik nyílra víve az egér mutatóját, "lépni enged" a Zilli, de a rákattintásra semmi nem történik.
Ehhez persze, a zrf. általános blokkjában le kell tiltani az automatikus drops-animációt: (animate-drops false)
(Különben, minden rákattintáskor, felülrõl-lefelé be fog kúszni a "nyíl"-képét formázó bábu.)

Megjegyzendõ: Gyakori hiba, hogy megfeledkezünk a lerakható bábuk induló készletérõl. Ezt, most, a (board-setup)-ban off 100-zal, mindegyik nyílnál 100 db-ra adtuk meg. (Ha nem lennének a táblán kívül nyíl-bábuk, akkor lépésképtelen helyzetet jelezne a Zilli.)
(piece (image Solo "Images\Labirintus2\s.bmp") (name _s) ; felfelé mutató nyíl
(drops (t1 add))
)
(piece (image Solo "Images\Labirintus2\n.bmp") (name _n) ; lefelé mutató nyíl
(drops (t3 add))
)
(piece (image Solo "Images\Labirintus2\w.bmp") (name _w) ; balra mutató nyíl
(drops (y2 add))
)
(piece (image Solo "Images\Labirintus2\e.bmp") (name _e) ; jobbra mutató nyíl
(drops (w2 add))
)

c./ és b./ A Zilli "tudja" hol vannak a táblán a golyók. Ha pl.(moves e add) utasítással mozgatnánk, akkor a golyóra kattintáskor azonnal el is mozgatná a jobb oldali szomszédos mezõre.

Itt azonban, a lépés a fenti drops-lerakással történik és nem kívánunk újabb klikket felhasználni a golyók mozgatásához. A lerakási utasításban kell rendelkeznünk arról, hogy mielõtt letenné a nyilat, elõtte mozgassa el a golyókat... Ennek, mind a négy irányban hasonló megoldása közül nézzük a lefelé (s) irányt:

(piece (image Solo "Images\Labirintus2\s.bmp") (name _s)
(drops ( (holvan1) back ;a (define holvan1....)-ben (mark)-al ráálltunk a piros golyóra
(change-type FREE) ;a golyót üres bábura cseréljük
s (while (piece? FREE) s) ;lefelé (s) átlépjük az üres bábukat tartalmazó mezõket
n (change-type RED) ;egyet visszalépve (n), az üres bábut a piros golyóra cseréljük
(holvan2) back ;a (define holvan2....)-ben megkeresett zöld golyóra állunk rá
(change-type FREE) ;a golyót üres bábura cseréljük
s (while (piece? FREE) s) ;lefelé (s) átlépjük az üres bábukat tartalmazó mezõket
n (change-type GREEN) ;egyet visszalépve (n), az üres bábut a zöld golyóra cseréljük
t1 add ;végül, a t1-re "lerakjuk" a lefelé mutató nyilat.
)
)
)

Miután a fentit négyszer kellene megírni, (és mert a továbbgondolkodást is egyszerûsíteni fogja) fogalmazzuk át mindezt define-be rendszerezve:

(piece (image Solo "Images\Labirintus2\s.bmp") (name _s)
(drops ((gurul1 s n) (gurul2 s n) ;a elgurítjuk lefelé a piros(1) és a zöld(2) golyókat és
(t1 add) ; a t1-re "lerakjuk" a felfelé mutató nyilat.
)
)
)
(piece (image Solo "Images\Labirintus2\s.bmp") (name _s)
(drops ((gurul1 n s) (gurul2 n s) ;a elgurítjuk felfelé a piros(1) és a zöld(2) golyókat és
(t3 add) ; a t3-re "lerakjuk" a felfelé mutató nyilat.
)
)
)
(piece (image Solo "Images\Labirintus2\s.bmp") (name _s)
(drops ((gurul1 e w) (gurul2 e w) ;a elgurítjuk jobbra a piros(1) és a zöld(2) golyókat és
(w2 add) ; a w2-re "lerakjuk" a felfelé mutató nyilat.
)
)
)
(piece (image Solo "Images\Labirintus2\s.bmp") (name _s)
(drops ((gurul1 w e) (gurul2 w e) ;a elgurítjuk balra a piros(1) és a zöld(2) golyókat és
(y2 add) ; a y2-re "lerakjuk" a felfelé mutató nyilat.
)
)
)
;*********************************************************************
(define gurul1 (holvan1) back ;a (define holvan1....)-ben (mark)-al ráálltunk a piros golyóra
(if (piece? RED) ;ha nincs piros golyó a táblán, akkor a (mark)-on egy másik golyó van!
(change-type FREE) ;a golyót üres bábura cseréljük
$1 (while (piece? FREE) $1) ;az adott irányban ($1) átlépjük az üres-bábus mezõket
$2 (change-type PIROS) ;egyet visszalépve($2), az üres bábut a piros golyóra cseréljük
) ;end if
) ;end define gurul1

(define gurul2 (holvan2) back ;a (define holvan2....)-ben megkeresett zöld golyóra állunk rá
(if (piece? GREEN) ;ha nincs zöld golyó a táblán, akkor a (mark)-on egy másik golyó van!
(change-type FREE) ;a golyót üres bábura cseréljük
$1 (while (piece? FREE) $1) ;az adott irányban ($1) átlépjük az üres-bábus mezõket
$2 (change-type ZOLD) ;egyet visszalépve, az üres bábut a zöld golyóra cseréljük
) ;end if
) ;end define gurul2

;*********************************************************************
(define holvan1
;soronként letapogatjuk a táblát, ha piros golyót látunk, akkor annak a helyét megjegyezzük (mark)
a2 (while (on-board? e) e (if (piece? RED) mark) )
a3 (while (on-board? e) e (if (piece? RED) mark) )
a4 (while (on-board? e) e (if (piece? RED) mark) )
a5 (while (on-board? e) e (if (piece? RED) mark) )
a6 (while (on-board? e) e (if (piece? RED) mark) )
a7 (while (on-board? e) e (if (piece? RED) mark) )
a8 (while (on-board? e) e (if (piece? RED) mark) )
a9 (while (on-board? e) e (if (piece? RED) mark) )
a10 (while (on-board? e) e (if (piece? RED) mark) )
a11 (while (on-board? e) e (if (piece? RED) mark) )
a12 (while (on-board? e) e (if (piece? RED) mark) )
a13 (while (on-board? e) e (if (piece? RED) mark) )
a14 (while (on-board? e) e (if (piece? RED) mark) )
a15 (while (on-board? e) e (if (piece? RED) mark) )
)

(define holvan2
;soronként letapogatjuk a táblát, ha zöld golyót látunk, akkor annak a helyét megjegyezzük (mark)
a2 (while (on-board? e) e (if (piece? GREEN) mark) )
a3 (while (on-board? e) e (if (piece? GREEN) mark) )
a4 (while (on-board? e) e (if (piece? GREEN) mark) )
a5 (while (on-board? e) e (if (piece? GREEN) mark) )
a6 (while (on-board? e) e (if (piece? GREEN) mark) )
a7 (while (on-board? e) e (if (piece? GREEN) mark) )
a8 (while (on-board? e) e (if (piece? GREEN) mark) )
a9 (while (on-board? e) e (if (piece? GREEN) mark) )
a10 (while (on-board? e) e (if (piece? GREEN) mark) )
a11 (while (on-board? e) e (if (piece? GREEN) mark) )
a12 (while (on-board? e) e (if (piece? GREEN) mark) )
a13 (while (on-board? e) e (if (piece? GREEN) mark) )
a14 (while (on-board? e) e (if (piece? GREEN) mark) )
a15 (while (on-board? e) e (if (piece? GREEN) mark) )
)

Eddig nem vettük figyelembe azokat a helyzeteket, amikor a gurítás irányába esõ üres pálya-soron van mindkét golyó. Fenti megoldással, ilyen esetekben az egyik golyó csak a másik indulási helyéig fog "elgurulni". Az elgurításnál ugyanis, csak az üres helyeken haladt át a golyó. Ha a fal elõtt találkozik egy másik golyóval, akkor az mellett fog megállni.
Egyszerûnek tûnik az a megoldás, hogy ilyenkor: az éppen gurított golyó "lépjen" át az útjába esõ golyókon és majd a falra érkezve, egyet visszalépve, még annyival lépjen vissza a "lerakás" elõtt, ahány golyó közben az útjába esett.

Ezzel együtt, még egy hiba-lehetõséget is le kell lekezelnünk.
Gondoljuk át! Egy adott golyó gurítása úgy történik, hogy: indulási helyére, egy üres bábut teszünk, majd, az (a golyóátlépéseket is beszámítva adódó) érkezési mezõre lerakjuk.
Akkor van hiba, ha ezt követõen (persze ugyanebben a lépésben) egy olyan golyót fogunk gurítani, amelyiknek az indulási mezõje éppen a korábban elgurított golyó érkezési mezõjével azonos. Ekkor ugyanis, az utóbbi golyó törlési parancsa, a már korábban helyesen lerakottat, fogja levenni a tábláról.

Megoldás:
Meg kell jegyezni az adott lépés mindegyik lerakásának helyét. (Ezek hibátlanok.) Nem szabad (nem is szükséges) törölni a mozgatott golyó indulási képét akkor, ha azt már felülírta egy korábban lerakott golyó.
A gond az, hogy a Zilli game részében behívott define-blokkjai egymástól teljesen függetlenek. Csak az egymást hívó (egymásba ágyazott) define-blokkok veszik figyelembe a másikban bekövetkezett változást. Konkrétan: a (define gurul2...) nem érzékeli a (define gurul1...) okozta változásokat.(Nem vizsgálhatjuk a gurul2-ben azt, hogy az elõtte behívott gurul1-ben mi történt. Mindegyik a nulla állapotból indul, aztán persze az eredmény mindig az elõbb behívott felüírásával adódik ki.)
Ezért, a (define gurul...) blokkokból kiemeltük az induló állapot törlését (change-type FREE) és áttettük egy újabb (define virtolv...) blokkba. Ez utóbbi pedig figyeli, a mindegyik (define gurul...)-ból adatot kapó (define virtir...) -ban beállított pozíciójelzõket.
Mindegyik (define gurul...) a lerakáskor behívja a (define virtir...)-t és abban megcímkézi a lerakás helyét. A (define gurul...)-okba behívott (define virtolv...) akkor fog csak törölni, ha a törlendõ mezõ nincs címkézve, azaz nem olyan mezõ, amire már az adott lépésben lerakott golyó került.)

Megjegyzés: az alábbi lista a zöld golyó elgurítása $1 irányban, úgy hogy:
max. 9 db golyó lehet még a legközelebbi falig történõ elgurulás útjában.

(define virtir
;az aktuális mezõt (ahol akkor áll, amikor a virtir-t behívja) megcimkézi
(set-position-flag enyem true)
)

(define virtolv
; ha az aktuális mezõ nem címkézett, akkor a tartalmát üres bábu-ra cseréli (törli a golyót)
(if (not-position-flag? enyem) (change-type FREE))
)

(define gurul2 (holvan2) back (if (piece? GREEN) ; a zöld golyóra áll, (kilép a (gurul2)-bõl, ha nincs)
(virtolv) $1(while (piece? FREE) $1 ) ; törli (nem törli, ha címkézett) és átlépi az üres mezõket
(if (piece? BRICKS) $2 (virtir) (change-type GREEN) else ; ha falon van, mellé a zöldet,címkéz, kilép
$1(while (piece? FREE) $1) ;átlép egy golyót (csak az lehet) és az azt követõ üres helyeket
(if (piece? BRICKS) ; ha falon áll, akkor
$2 $2 (virtir) (change-type GREEN) ; kettõt visszalép, címkéz, lerak, kilép
else $1(while (piece? FREE) $1) ; különben, átlépi a második golyót és az üreseket...
(if (piece? BRICKS)
$2 $2 $2 (virtir) (change-type GREEN)
else $1(while (piece? FREE) $1) ; a harmadik átlépett golyó...
(if (piece? BRICKS)
$2 $2 $2 $2 (virtir) (change-type GREEN)
else $1(while (piece? FREE) $1) ; a negyedik átlépett golyó...
(if (piece? BRICKS)
$2 $2 $2 $2 $2 (virtir) (change-type GREEN)
else $1(while (piece? FREE) $1) ; az ötödik átlépett golyó...
(if (piece? BRICKS)
$2 $2 $2 $2 $2 $2 (virtir) (change-type GREEN)
else $1(while (piece? FREE) $1) ; a hatodik átlépett golyó...
(if (piece? BRICKS)
$2 $2 $2 $2 $2 $2 $2 (virtir) (change-type GREEN)
else $1(while (piece? FREE) $1) ; a hetedik átlépett golyó...
(if (piece? BRICKS)
$2 $2 $2 $2 $2 $2 $2 $2 (virtir) (change-type GREEN)
else $1(while (piece? FREE) $1) ; a nyolcadik átlépett golyó...
(if (piece? BRICKS)
$2 $2 $2 $2 $2 $2 $2 $2 $2 (virtir) (change-type GREEN)
else $1(while (piece? FREE) $1) ; a kilencedik átlépett golyó...
$2 $2 $2 $2 $2 $2 $2 $2 $2 $2 (virtir) (change-type GREEN)
) ) ) ) ) ) ) ) ) ) ; az (if...-ek )- endjei
) ; end (define gurul2...

**********************************************

(folyt.)