• Nenhum resultado encontrado

În jocul cu vaporaşe doi “combatanŃi maritimi” se confruntă pe un “câmp de luptă”, fiecare încercând să “scufunde” vasele celuilalt. Fiecare partener are în faŃă două suprafeŃe de joc, una pe care sunt marcate vasele lui şi cealaltă pe care marchează cunoaşterea lui asupra zonei în care îşi ascunde adversarul vasele sale.

Fiecare suprafaŃă de joc este o tablă de 10x10 pătrăŃele, vaporaşele pot avea mărimi variind între 2 şi 4 pătrăŃele şi forme date de orice configuraŃie de pătrăŃele adiacente. Pentru scufundarea unui vaporaş de mărime n sunt necesare tot atâtea lovituri în exact pătrăŃelele pe care acesta le ocupă.

În general, într-o partidă de vaporaşe, un jucător întâi “bombardează” după un plan oarecare (care poate fi şi aleator) caroiajul adversarului, până ce o lovitură nimereşte un vas al acestuia. Urmează un set de lovituri aplicate în vecinătatea celei norocoase, până la scufundarea Ńintei.

Sunt multe moduri prin care un program care joacă vaporaşe cu un partener uman poate fi făcut mai performant: maniera de scanare a terenului până la descoperirea poziŃiei unei Ńinte, maniera de atac dintre prima lovitură aplicată unei Ńinte şi scufundarea completă a acesteia, învăŃarea preferinŃelor adversarului în privinŃa plasării vapoarelor şi a formelor acestora în vederea măririi şanselor de câştig în partide viitoare (lovirea cu precădere în poziŃii care amintesc de forme ce par astfel a fi cele mai vulnerabile) etc.

În cele ce urmează ne vom preocupa de realizarea strategiilor pentru aruncarea bombelor în cele două situaŃii de luptă: găsirea Ńintelor şi scufundarea lor după o lovitură iniŃială. Fiecare regulă va descrie operaŃiile de efectuat când o anumită situaŃie este întâlnită pe teren.

Într-un joc de vaporaşe, în fazele de localizare a Ńintelor preferăm să plasăm loviturile cât mai uniform în spaŃiul de joc, astfel încât densitatea loviturilor să crească relativ constant pe întreaga suprafaŃă. Pentru recunoaşterea suprafeŃelor goale putem aplica familii de şabloane planare cu care să descoperim oricare dintre configuraŃiile următoare de zone libere (număr linii ∗ număr coloane): 5x5, 3x3, 2x3, 3x2, 1x3 şi 3x1:

Primul şablon, de exemplu, pune în evidenŃă o zonă liberă de 5x5 celule, care, pe o tablă iniŃială 10x10, poate fi instanŃiată în 36 de moduri. Pentru

Confruntări de şabloane în plan 181

exemplificare, partea stângă a unei reguli care tentează descoperirea unei zone 2x3, poate fi scrisă astfel:

(defrule EU-la-joc-alege-zona-libera-2x3-1 (declare (salience 8))

...

(TU-T ?lin1 $?beg1 0 0 0 $?end1) (TU-T ?lin2&:(= ?lin2 (+ 1 ?lin1))

$?beg2&:(= (length$ $?beg2) (length$ $?beg1)) 0 0 0 $?end2)

=>

...

)

Într-o astfel de descriere zona de luptă a adversarului este reprezentată printr-o mulŃime de 10 fapte liniare de forma:

(TU-T <nr-linie> <p1> <p2> <p3> <p4> <p5> <p6> <p7> <p8>

<p9> <p10>)

în care <p1> ... <p10> reprezintă cele 10 poziŃii ale liniei <nr-linie>, fiecare putând fi notată cu 0, dacă poziŃia nu este atinsă, sau cu numărul vaporului în cauză, atunci când se confirmă că lovitura a atins un vapor.

O dată descoperită o astfel de zonă, o regulă decide aplicarea unei lovituri într-o poziŃie care se află fie în mijlocul zonei goale, fie foarte aproape de mijloc (pătrăŃelele gri de mai jos):

Ca urmare, opt reguli, iar nu şase, descriu acŃiunile ce trebuie efectuate la descoperirea zonelor goale. Pentru exemplificare, printre alte lucruri, regula care mai sus a fost prezentată pentru partea stângă ar putea conŃine în partea dreaptă şi următoarele:

(defrule EU-la-joc-alege-zona-libera-3x2-1 ...

(TU-T ?lin1 $?beg1 0 0 0 $?end1) (TU-T ?lin2&:(= ?lin2 (+ 1 ?lin1))

Programarea bazată pe reguli 182

$?beg2&:(= (length$ $?beg2) (length$ $?beg1)) 0 0 0 $?end2)

=>

...

(printout t “Lovesc in patratul: (“ ?lin2 “,”

(+ 1 (length$ $?beg2))

“)!. Comunica rezultatul!” crlf) )

Aşa cum ştim, prioritatea declarată a regulilor este importantă în stabilirea ordinii în care zonele goale vor fi lovite. Este uşor de văzut că numărul de instanŃieri pe tabla de joc ale unui şablon este cu atât mai mare cu cât el încearcă descoperirea unor zone mai mici. Lăsarea ordinii de aplicare a regulilor în voia strategiei de rezoluŃie a conflictelor cu care rulează sistemul poate rezulta într-o aglomerare a loviturilor în anumite zone ce sunt puse în evidenŃă de şabloane care cercetează suprafeŃe mici. Cum suprafaŃa “acoperită” de un şablon reflectă în proporŃie inversă densitatea de aplicare a loviturilor (1/25 – pentru şablon-ul 5x5, 1/9 pentru şablon-ul 3x3 ş.a.m.d. 1/3 pentru cel 1x3 sau 3x1) şi cum ne preocupă să realizăm o acoperire a zonei de luptă, uniformă în densitatea loviturilor, care să varieze dinspre densităŃi mici spre cele mari, ordinea de aplicare a regulilor trebuie să fie: mai întâi cele cu şabloane corespunzând suprafeŃelor mari şi apoi cele cu şabloane corespunzând suprafeŃelor mici. Cum nu avem nici un motiv pentru care să preferăm configuraŃia 2x3 înaintea celei 3x2, sau a configuraŃiei 1x3 înaintea celei 3x1, declaraŃiile de prioritate vor trebui să repartizeze regulile pe şase niveluri.

(defrule EU-la-joc-alege-zona-libera-5x5 (declare (salience 10))

...

(TU-T ?lin1 $?beg1 0 0 0 0 0 $?end1)

(TU-T ?lin2&:(= ?lin2 (+ 1 ?lin1)) $?beg2&:(= (length$

$?beg2) (length$ $?beg1)) 0 0 0 0 0 $?end2)

(TU-T ?lin3&:(= ?lin3 (+ 2 ?lin1)) $?beg3&:(= (length$

$?beg3) (length$ $?beg1)) 0 0 0 0 0 $?end3)

(TU-T ?lin4&:(= ?lin4 (+ 3 ?lin1)) $?beg4&:(= (length$

$?beg4) (length$ $?beg1)) 0 0 0 0 0 $?end4)

(TU-T ?lin5&:(= ?lin5 (+ 4 ?lin1)) $?beg5&:(= (length$

$?beg5) (length$ $?beg1)) 0 0 0 0 0 $?end5) =>

...

(printout t “Lovesc in patratul: (“ ?lin3 “,” (+ 3 (length$ $?beg3)) “)!. Comunica rezultatul!” crlf)

)

(defrule EU-la-joc-alege-zona-libera-3x3

Confruntări de şabloane în plan 183

(declare (salience 9)) ...

(TU-T ?lin1 $?beg1 0 0 0 $?end1)

(TU-T ?lin2&:(= ?lin2 (+ 1 ?lin1)) $?beg2&:(= (length$

$?beg2) (length$ $?beg1)) 0 0 0 $?end2)

(TU-T ?lin3&:(= ?lin3 (+ 2 ?lin1)) $?beg3&:(= (length$

$?beg3) (length$ $?beg1)) 0 0 0 $?end3) =>

...

(printout t “Lovesc in patratul: (“ ?lin2 “,” (+ 2 (length$ $?beg2)) “)!. Comunica rezultatul!” crlf)

)

(defrule EU-la-joc-alege-zona-libera-2x3-1 (declare (salience 8))

...

(TU-T ?lin1 $?beg1 0 0 0 $?end1)

(TU-T ?lin2&:(= ?lin2 (+ 1 ?lin1)) $?beg2&:(= (length$

$?beg2) (length$ $?beg1)) 0 0 0 $?end2) =>

...

(printout t “Lovesc in patratul: (“ ?lin2 “,” (+ 2 (length$ $?beg2)) “)!. Comunica rezultatul!” crlf)

)

(defrule EU-la-joc-alege-zona-libera-2x3-2 (declare (salience 8))

...

(TU-T ?lin1 $?beg1 0 0 0 $?end1)

(TU-T ?lin2&:(= ?lin2 (+ 1 ?lin1)) $?beg2&:(= (length$

$?beg2) (length$ $?beg1)) 0 0 0 $?end2) =>

...

(printout t “Lovesc in patratul: (“ ?lin1 “,” (+ 2 (length$ $?beg1)) “)!. Comunica rezultatul!” crlf)

)

(defrule EU-la-joc-alege-zona-libera-3x2-1 (declare (salience 8))

...

(TU-T ?lin1 $?beg1 0 0 $?end1)

(TU-T ?lin2&:(= ?lin2 (+ 1 ?lin1)) $?beg2&:(= (length$

$?beg2) (length$ $?beg1)) 0 0 $?end2)

(TU-T ?lin3&:(= ?lin3 (+ 2 ?lin1)) $?beg3&:(= (length$

$?beg3) (length$ $?beg1)) 0 0 $?end3) =>

...

Programarea bazată pe reguli 184

(printout t “Lovesc in patratul: (“ ?lin2 “,” (+ 1 (length$ $?beg2)) “)!. Comunica rezultatul!” crlf)

)

(defrule EU-la-joc-alege-zona-libera-3x2-2 (declare (salience 8))

...

(TU-T ?lin1 $?beg1 0 0 $?end1)

(TU-T ?lin2&:(= ?lin2 (+ 1 ?lin1)) $?beg2&:(= (length$

$?beg2) (length$ $?beg1)) 0 0 $?end2)

(TU-T ?lin3&:(= ?lin3 (+ 2 ?lin1)) $?beg3&:(= (length$

$?beg3) (length$ $?beg1)) 0 0 $?end3) =>

...

(printout t “Lovesc in patratul: (“ ?lin2 “,” (+ 2 (length$ $?beg2)) “)!. Comunica rezultatul!” crlf)

)

(defrule EU-la-joc-alege-zona-libera-1x3 (declare (salience 7))

...

(TU-T ?lin $?beg 0 0 0 $?end) =>

...

(printout t “Lovesc in patratul: (“ ?lin “,” (+ 2 (length$ $?beg)) “)!. Comunica rezultatul!” crlf)

)

(defrule EU-la-joc-alege-zona-libera-3x1 (declare (salience 7))

...

(TU-T ?lin1 $?beg1 0 $?end1)

(TU-T ?lin2&:(= ?lin2 (+ 1 ?lin1)) $?beg2&:(= (length$

$?beg2) (length$ $?beg1)) 0 $?end2)

(TU-T ?lin3&:(= ?lin3 (+ 2 ?lin1)) $?beg3&:(= (length$

$?beg3) (length$ $?beg1)) 0 $?end3) =>

...

(printout t “Lovesc in patratul: (“ ?lin2 “,” (+ 1 (length$ $?beg1)) “)!. Comunica rezultatul!” crlf)

)

Cel de al doilea motiv pentru care, în jocul de vaporaşe, am fi interesaŃi de dispunerea elementelor în plan este legat de strategia de joc pe care o adoptăm pentru scufundarea unui vapor o dată realizată o primă lovitură. Vom implementa o

Confruntări de şabloane în plan 185

“strategie de luptă” prin care se lovesc cu prioritate pătrăŃele aflate în imediata apropiere a unor lovituri deja aplicate unui vapor ce este încă nescufundat.

Astfel, presupunând că un fapt de forma (TU-V-lovite <nr-vapor>

<nr-lovituri-primite>) memorează pentru fiecare vapor al adversarului ce a primit cel puŃin o lovitură numărul de lovituri primite, iar (tip-V <nr- vapor> <gabarit>) reŃine pentru fiecare vapor, indiferent de jucător, din câte pătrăŃele este format, atunci decizia de lovire în poziŃia p a tablei adversarului este dată de conjuncŃia de condiŃii:

- vaporul n are lovite un număr de poziŃii mai mare decât zero dar mai mic decât numărul de poziŃii al tipului respectiv de vapor;

- poziŃia p se află în vecinătatea unei poziŃii lovite în vaporul n.

Prima dintre cele două condiŃii poate fi realizată de secvenŃa următoarelor două şabloane:

(TU-V-lovite ?nr-V ?lov)

(tip-V ?nr-V ?tip-V&:(< ?lov ?tip-V))

iar cea de a doua condiŃie, de diferite combinaŃii de şabloane ce cercetează dispuneri planare în jurul unei poziŃii atinse în vaporul astfel depistat. În reprezentările de mai jos, cu s-a notat poziŃia veche şi cu cea nouă. În şabloane, se cercetează ca în poziŃia nouă să existe un 0.

(TU-T ?lin $?beg ?nr-V 0 $?end)

(TU-T ?lin $?beg 0 ?nr-V $?end) (TU-T ?lin1 $?beg1 ?nr-V $?end1) (TU-T ?lin2&:(= ?lin2 (+ 1 ?lin1))

$?beg2&:(= (length$ $?beg2)(+ 1 (length$ $?beg1))) 0 $?end)

(TU-T ?lin1 $?beg1 ?nr-V $?end1) (TU-T ?lin2&:(= ?lin2 (+ 1 ?lin1))

$?beg2&:(= (length$ $?beg2)(length$ $?beg1)) 0 $?end)

(TU-T ?lin1 $?beg1 ?nr-V $?end1) (TU-T ?lin2&:(= ?lin2 (+ 1 ?lin1))

$?beg2&:(= (length$ $?beg2)(- (length$ $?beg1) 1)) 0 $?end)

Programarea bazată pe reguli 186

(TU-T ?lin1 $?beg1 ?nr-V $?end1) (TU-T ?lin2&:(= ?lin2 (- ?lin1 1))

$?beg2&:(= (length$ $?beg2)(- (length$ $?beg1) 1)) 0 $?end)

(TU-T ?lin1 $?beg1 ?nr-V $?end1) (TU-T ?lin2&:(= ?lin2 (- ?lin1 1))

$?beg2&:(= (length$ $?beg2)(length$ $?beg1)) 0

$?end)

(TU-T ?lin1 $?beg1 ?nr-V $?end1) (TU-T ?lin2&:(= ?lin2 (- ?lin1 1))

$?beg2&:(= (length$ $?beg2)(+ 1 (length$ $?beg1))) 0 $?end)

Capitolul 14

O problem ă de c ă utare