SlideShare a Scribd company logo
Univerzitet u Nišu
Elektronski fakultet
Katedra za računarstvo
DIPLOMSKI RAD
TEORIJSKE I PRAKTIČNE OSNOVE REALIZACIJE LOGIČKE IGRE
„4-U-NIZU“ NA PERSONALNIM RAČUNARIMA
Zadatak: Proučiti i opisati teorijske i praktične metode realizacije logičke igre „4-u-nizu“. U
teorijskom delu rada opisati osnovne algoritme (MinMax, Alfa-Beta) koji će biti iskorišćeni
za implementaciju. U praktičnom delu rada realizovati kompletnu aplikaciju.
Komisija: Student:
Predsednik komisije Saša Stojković, 11332
1.____________________ Datum prijave rada
Član komisije ____________________
2.____________________ Datum predaje rada
Član komisije ____________________
3.____________________ Datum odbrane rada
____________________
2
3
Sadržaj:
1. Uvod........................................................................................................4
2. Teorija igara............................................................................................5
2.1. Osnovni pojmovi teorije igara ............................................................5
2.2. Logička igra „4 u nizu“ .....................................................................7
3. Osnovni pojmovi veštačke inteligencije .....................................................9
4. Implementacija igre “4 u nizu”...............................................................18
4.1. Univerzalna platforma za logičke igre...............................................18
4.1.1. Book..........................................................................................18
4.1.2. Evaluation .................................................................................19
4.1.3. Players ......................................................................................22
4.1.4. Table.........................................................................................31
4.1.5. Tree...........................................................................................33
4.1.6. Table game................................................................................34
4.1.7. Paralelizacija.............................................................................36
4.1.8. Problem sinhronizacije rekurentnih taskova ................................37
4.2. Implementacija igre „4 u nizu“ ........................................................44
4.2.1. Tabla igre (implementacija ITable).............................................44
4.2.2. Logika igre (implementacija ITableGame) ..................................46
4.2.3. Transpoziciona tabela (implementacija ITransTable) ..................47
4.2.4. Evaluatori (implementacija IEvaluation).....................................48
4.3. Implementacija korisničkog interfejsa igre........................................49
4.3.1. Konfiguracioni prozor ................................................................49
4.3.2. Situacije.....................................................................................50
4.3.3. Glavni prozor.............................................................................52
4.3.4. Log............................................................................................61
5. Zaključak...............................................................................................64
6. Literatura..............................................................................................65
7. Lista slika..............................................................................................66
8. Lista tabela............................................................................................67
4
1.Uvod
Današnje aplikacije sve više zahtevaju upotrebu specijalizovanih algoritama koji se inače
tradicionalno primenjuju u oblasti veštačke inteligencije u cilju rešenja nekih praktičnih
problema.
Sa razvojem računarskog hardvera rastu i zahtevi vezani za mogućnosti softvera. Jedan od
novijih problema koji se javlja jeste i problem automatske klasifikacije podataka ili
profilisano traženje (korisnicima više nije dovoljno prosto poređenje teksta već se zahteva i
semantička analiza traženog uzorka i rezultata traženja), itd.
Sposobnost rešavanja ovih i sličnih problema vezuje se za čoveka i njegovu inteligenciju,
odnosno sposobnost da rešava složene zadatke. Međutim, u eri savremenih računara koji su
sposobni da obavljaju ogroman broj operacija u sekundi, korisnici očekuju da ne moraju sami
rešavati te zadatke, imajući u vidu da su ti zadaci za njih same trivijalni. Rešenje za ovakve
probleme nudi nam veštačka inteligencija.
Nekada je veštačka inteligencija imala za cilj rešavanje uskog kruga problema, međutim,
vremenom se rešenja koja su u toj oblasti pronađena sve više koriste u projektovanju
aplikacija koje se svakodnevno koriste. Neke od njih koristimo svakodnevno, a ni ne
primećujemo da se iza njih nalazi „veštačka inteligencija“, npr. svakodnevno koristimo web
pretraživače, a najveći web pretraživač Google već neko vreme koristi tehnike veštačke
inteligencije kako bi efikasnije obavljao proces pretraživanja i sortiranja rezultata korisnika.
Takođe, mnogi rečnici i alati za prevođenje sa različitih jezika koriste tehnike veštačke
inteligencije kako bi poboljšali kvalitet svoje obrade.
Razlog autora da se bavi ovom temom ogleda se u samoj želji da se što bolje upozna sa
tehnikama veštačke inteligencije radi njihove primene u praktičnim problemima.
Tema diplomskog rada je implementacija igre “4 u nizu” i predstavljanje algoritama veštačke
inteligencije koje je neophodno koristiti u realizaciji. U radu će biti opisani i praktično
realizovni neki od najpoznatijih algoritama iz oblasti algoritma traženja, jedne od oblasti
veštačke inteligencije.
Takođe, u teorijskom delu biće objašnjeni osnovni pojmovi iz oblasti teorije igara koji će biti
korišćeni u ovom radu.
U praktičnom delu rada biće realizovana kompletna aplikacija u kojoj će biti primenjeni svi
algoritmi i tehnike koji budu opisani u teorijskom delu rada. Rad će biti realizovan
korišćenjem razvojnog okruženja „Microsoft Visual Studio 2010“, a kao osnova za razvoj
biće iskorišćen „Microsoft .NET Framework 4.0“. Aplikacija je realizovana u programskom
jeziku C#.
5
2.Teorija igara
Teorija igara je naučna oblast koja ima svoje korene još u 17. veku. Ova teorija je u osnovi
povezana sa matematičkom teorijom verovatnoće, ali se kasnije razvila u potpuno samostalnu
teoriju koja obuhvata tretiranje ne samo logičkih igara već i brojnih problema koji su u vezi
sa ekonomskim, vojnim i sociološkim fenomenima [1].
2.1. Osnovni pojmovi teorije igara
Prema interesima igrača koji učestvuju u igri postoje nekoliko klasa igara koje se mogu
izdvojiti [1]:
- Kooperativne igre - (cooperative games) je klasa igara kod kojih igrači imaju
zajednički interes.
- Nekooperativne igre (non-cooporatve games) - U mnogim igrama su interesi igrača u
potpunosti suprotni. „4 u nizu“ i šah su dobar primer za takvu situaciju. Igre tog tipa
se u teoriji igara nazivaju nekoperativne igre sa nultim sumiranjem (zero-sum non-
cooperative games). Pojam nultog sumiranja objašnjava vrednovanje (evaluaciju)
svakog poteza za oba igrača, odnosno pošto su im interesi suprotni, isti potez za
jednog igrača ima pozitivnu vrednost, a za drugog negativnu te je njihov zbir nula.
- Igre sa kombinovanim motivima (mixed-motive game) – Ukoliko igrači imaju
elemente i kooperativnosti i nekooperativnosti istovremeno, igre se mogu svrstati u
ovu klasu. Primer bi mogao biti jedan fudbalski tim (svaki igrač želi da postigne go-
individualni motiv, ali je glavni motiv pobeda tima).
Igre se takođe mogu klasifikovati [1]:
- Igre veštine (games of skill) - U ovu grupu spadaju igre koje igra jedan igrač koji ima
potpunu kontrolu nad svim mogućim ishodima.
- Igre šansi (games of chance) – U ovu grupu spadaju igre koje jedan igrač igra protiv
prirode. Definicija prirode kao drugog igrača omogućava nešto viši nivo tretiranja
ovih igara u odnosu na igru veštine. Osnovna karakteristika je da igrač ne može da
konroliše sve moguće ishode u igri, već da može da prilikom građenja strategije ima u
vidu samo verovatnoće nekih ishoda. U literaturi se ove igre nazivaju takođe i igrom
rizika.
Unutar ove grupe moguće je podeliti tipove igara na još dve podgrupe:
o ako su poznate verovatnoće pojedinih mogućih ishoda u okviru prirodnih
zakona (involving risk games)
o ako su mogući ishodi i verovatnoće u potpunosti nepoznati.
U prvom slučaju moguće je izgraditi prilaz u biranju mogućih poteza na osnovu
opadajućeg predviđenog niza verovatnoća, dok je u drugom slučaju ukupni ishod i
njegove verovatnoće apsolutno nepoznat.
6
- Igre strategije (games of strategy) – Uključuju dva ili više igrača, bez uključivanja
prirode, od kojih svaki ima delimičnu kontrolu nad mogućim ishodima. Pošto svaki
igrač poseduje autonomnost u odlučivanju, verovatnoće ishoda ili donošenja odluka
drugih igrača su potpuno nepoznate svakom igraču. Ova grupa igara se takođe deli na
dve podgrupe – igre sa dva ili više igrača. Unutar svake podgrupe postoji još tri
podgrupe igara u zavisnosti od toga u kakvom je odnosu funkcija isplativosti jednog
igrača u odnosu na ostale: Ako su interesi igrača u potpunosti koincidentni, ako su u
potpunosti suprotni ili ako su delimično koincidentni, a delimično suprotni.
o Igre strategije dva ili više igrača u kojima su interesi igrača koincidentni se
nazivaju kooperativne igre strategije.
o Igre u kojima su interesi igrača u potpunosti suprotni se nazivaju igre
strategije sa nultim sumiranjem (zero-sum games of strategy).
o Igre koje nisu u potpunosti kooperativne ili suprotne se nazivaju igre strategije
sa kombinovanim motivima (mixed-motive games of strategy).
U nastavku će biti navedene neke osnovne definicije iz teorije igara sa akcentom na njihovu
primenu u igri “4 u nizu” [1].
Definicija 1 - Igra je formalni opis strateške situacije.
Definicija 2 - Igrač je entitet koji učestvuje u igri i donosi samostalne odluke.
Definicija 3 - Funkcija isplativosti (pay-off function) koja je sinonim za evaluacionu funkciju
predstavlja numerički opis značajnosti nekog ishoda za nekog od igrača.
Definicija 4 - Igra sa nultim sumiranjem (zero-sum game) podrazumeva tip igre gde je suma
svih ishoda za sve igrače nula. Kod igara u kojima su interesi igrača suprotni, kao što je to
slučaj u igri „4 u nizu“, funkcije isplativosti imaju suprotan predznak. Ako neka pozicija koja
je rezultat igre ima vrednost +E za crvenog, to istovremeno znači da ona ima vrednost -E za
plavog.
Definicija 5 - Igra sa potpunim informacijama (perfect information game) znači da u svakom
momentu samo jedan igrač može da povuče potez. Svaki igrač poseduje sve inforamcije o
svim mogućnostima koje može da odigra drugi igrač računajući i informacije o funkciji
isplativosti.
Definicija 6 - Ekstenzivna forma igre (extensive game form) je stablo koje predstavlja tok
odigravanja igre. Stablo se generiše na osnovu naizmeničnog redosleda odigravanja poteza. U
svakoj tački u stablu svaki igrač poseduje perfektnu informaciju (prema definiciji 5).
Definicija 7 - Strategija je jedna od više mogućih akcija (poteza) nekog igrača. U
ekstenzivnoj formi igre, strategija je kompletan plan izbora mogućnosti za svaku tačku (čvor)
odlučivanja za svakog od igrača.
Definicija 8 - Matrica isplativosti je analogija funkciji isplativosti. Vrednost isplativosti za
svakog igrača je predstavljena odgovarajućom matricom umesto jedinstvenom numeričkom
vrednošću.
Definicija 9 - Racionalnost je osnovna pretpostavka u teoriji igara i podrazumeva da svaki
igrač igra sa ciljem da izvrši maksimizaciju svoje funkcije isplativosti.
7
Definicija 10 - Konačna igra je tip igre koja svakom igraču dozvoljava samo konačan broj
poteza i ograničenu mogućnost izbora u svakom potezu.
Definicija 11 - Kombinaciona igra predstavlja igru za dva igrača sa potpunim informacijama
i strogo definisanim pravilima po kojima se generišu potezi. Skup pozicija je definisan
pravilima igre i konačan je. Terminalna pozicija se definiše kao ona pozicija u kojoj strana
koja je na potezu nema više legalnih poteza na raspolaganju.
Definicija 12 - Nepristrasnom igrom (impartial game) se smatra ona igra za dva igrača kod
koje je skup poteza podudaran za bilo koju stranu koja je na potezu u istoj poziciji. Ako je taj
skup poteza različit igra se smatra tipom partizan.
Definicija 13 - Normalna definicija kraja igre podrazumeva da u terminalnoj poziciji igrač
koji je na potezu dobija. U suprotnom igra je tipa misere.
Definicija 14 - Igra je konačna ako se završava u končanom broju poteza.
2.2. Logička igra „4 u nizu“
Igra “4 u nizu” je logička igra za dva igrača. Prema podelama opisanim u poglavlju „Osnovni
pojmovi teorije igara“ ova igra se može svrstati u Nekooperativne igre prema prvoj podeli,
odnosno Nekooperativne igre strategije sa nultim sumiranjem po drugoj podeli. Takođe,
važe i sledeće tvrdnje:
- „4 u nizu“ je strateška igra u kojoj učestvuju dva igrača čiji se potezi smenjuju
naizmenično. Igrači se označavaju pojmovima plavi i crveni. Podrazumeva se da
igrači igraju racionalno (definicija 9).
- „4 u nizu“ je igra sa perfektnim informacijama (definicija 5) i nultim sumiranjem
(definicija 4).
- „4 u nizu“ je kombinaciona igra (definicija 11) tipa partizan (definicija 12). Broj
mogućih legalnih poteza u svakoj poziciji je konačan i može biti različit za svakog od
igrača.
- „4 u nizu“ ima tri moguće vrednosti funkcije isplativosti: pobedu crvenog, pobedu
plavog i nerešen rezultat.
- Partija se uvek završava u konačnom broju poteza (definicija 10) bez obzira na
strategije igrača.
- Funkcija isplativosti u „4 u nizu“ se može definisati matricom isplativosti:
Crveni igrač
Pobeda Nerešeno Poraz
Plavi igrač Pobeda - - 1, -1
Nerešeno - 0,0 -
Poraz -1, 1 - -
Tabela 1 Matrica ispravnosti za igru „4 u nizu“
8
Imajući u vidu gore navedene definicije, na igru „4 u nizu“ može se primeniti osnovna
minimaks teorema:
Za svaku konačnu igru sa potpuno definisanim informacijama u kojoj učestvuju dva
igrača i koja ima nultu sumu može se definisati optimalna strategija igre.
Pod datim uslovima može se definisati sledeća jednakost [1]:
𝑀𝐴𝑋 𝑋 𝑀𝐼𝑁 𝑌 𝑋 𝑇
𝐴𝑌 = 𝑀𝐼𝑁 𝑌 𝑀𝐴𝑋 𝑋 𝑋 𝑇
𝐴𝑌 = 𝑣
Gde je:
V - vrednost igre (evalucacija),
A - matrica isplativosti (tabela 1),
X,Y – matrica rešenja.
Logički gledano, ova teorema definiše postupak nalaženja najboljeg nastavka za igrača A koji
istovremeno predstavlja maksimalnu vrednost mogućih nastavaka koji su mu na
raspolaganju. Igrač B, koji igra protiv igrača A nastoji da maksimizuje svoju funkciju
isplativosti, odnosno da minimizuje funkciju isplativosti igrača A [1].
Nekoliko reči o samoj igri i pravilima. Igra se na tabli koja je podeljena u 42 polja (6 redova i
7 kolona). Igra je poteznog tipa (igrači se smenjuju naizmenično posle svakog odigranog
poteza). U svakom potezu igrač koji igra ubacuje novu figuricu na tablu u jedno od 42 polja
(pomeranje već ubačenih figura nije dozvoljeno).
Polje na koje se figurica ubacuje mora biti slobodno (na njemu se ne nalazi figurica) i mora
biti iznad nekog već zauzetog polja ili na dnu tabele (u prvom redu). Nakon postavljanja u
slobodno polje, figurica se ne pomera do kraja partije.
Cilj igre jeste dobiti najmanje 4 svoje figurice u nizu (izmedju njih se ne sme nalaziti nijedna
protivnička figurica). Figurice mogu biti u nizu horizontalno, vertikalno i dijagonalno.
Slika 1 Izgled table za igranje u igri “4 u nizu”
9
3.Osnovni pojmovi veštačke inteligencije
Veštačka inteligencija kao pojam pripisuje se sistemima i računarskim programima sa
sposobnostima realizovanja složenih zadataka, odnosno sposobnostima simulacije ljudskog
razmišljanja.
Kada govorimo o veštačkoj inteligenciji u oblasti računarskih igara govorimo o težnji da
računarski program donosi odluke na način na koji bi to čovek uradio, odnosno o simulaciji
težnje za pobedom u partiji.
U okviru veštačke inteligencije kao nauke tokom vremena razvile su se razne grane, svaka
izučavajući određeni problem ili određeni pravac istraživanja (neuronske mreže, expertni
sistemi, logičko zaključivanje, mašinsko učenje, algoritmi pretrage, itd.). Nisu sve tehnike
veštačke inteligencije primenljive na sve probleme niti su podjednako efikasne u rešavanju
svih problema.
U igrama kao što je “4 u nizu” primenjuju se algoritmi za rešavanje problema, odnosno
algoritmi traženja.
Kad se govori o pretraživanju, misli se na “pretraživanje” mogućih poteza (elementi skupa
legalnih poteza) za svakog igrača. Legalni potez je svaki potez koji igrač može odigrati
(poštujući pravila igre) kada je na redu da igra.
Pojednostavljeno, ovo znači da algoritmi traženja izdvajaju-nalaze, najbolji potez u datoj
situaciji uzimajući u obzir sve parametre igre. Kada kažemo najbolji potez, mislimo na potez
koji pruža najviše šanse za pobedu. Da bi algoritam traženja bio u stanju da oceni koji je
potez najbolji, neophodno je da izvrši ocenjivanje, tj. evaluaciju svakog poteza. Ovaj zadatak
obavlja deo programa koji se naziva evaluator (ili evaluaciona funkcija) [4][5].
On ne mora biti odvojen od ostatka programa, ali će radi pojednostavljenja objašnjenja to biti
pretpostavljeno u daljem tekstu. Evaluator ima ulogu da na što svrsishodniji način
uporedivim vrednostima opiše svaki potez (čvor stabla igre – definicija 6 iz teorije igara).
Ovo znači da vrednosti poteza koje je opisao evaluator moraju biti međusobno uporedive,
kako bi se znalo koji je bolji, a koji gori.
Kako bi “taktička” situacija u partiji mogla da bude sagledana u potpunosti, evaluator mora
uzeti u obzir i eventualne poteze protivnika, odnosno, ne samo da mora da pronađe najbolji
potez za trenutnog igrača, već mora pronaći i najbolji potez za njegovog suparnika kako bi
mogao da donese ispravnu odluku i pravilno oceni (evaulira) potez. Neophodno je da
algoritam traženja gleda unapred.
Broj koraka unapred koji algoritam traženja uzima u obzir pri izvršenju naziva se dubina
traženja. Ukoliko se zahteva samo traženje najboljeg poteza za trenutnog igrača, to je dubina
1. Ukoliko se zahteva i nalaženje najboljeg koraka protivnika nakon toga, to je dubina 2.
Dubina traženja ograničena je samo brojem raspoloživih poteza za igrače (može se generisati
sve dok se igra ne završi – pobedom jednog od igrača ili nerešenim rezultatom – što u slučaju
igre “4 u nizu” znači da više nema praznih polja na table). Maksimalna dubina stabla za igru
“4 u nizu” je jednaka broju polja, odnosno 42 nivoa.
10
Nivoi se mogu naizmenično smenjivati dok ne bude ispunjen neki od navedenih uslova za
kraj igre. Naizmenično smenjivanje se vrši zato što igrači igraju naizmenično, svaki potez
jednog igrača praćen je potezom drugog igrača.
U praktičnim realizacijama algoritama za traženje, kao model partije koji algoritam pretražuje
koristi se struktura podataka stablo.
Slika 2 Struktura podataka – Stablo
Stablo je nelinearna struktura podataka koja se sastoji od proizvoljnog broja čvorova. Svaki
čvor može biti u relaciji sa proizvoljnim brojem drugih čvorova koji se nazivaju njegovim
potomcima, a sam taj čvor može biti potomak nekog drugog čvora.
Samo jedan čvor nema prethodnika (roditelja) i on se naziva koren stabla.
Najniži u hijerarhiji stabla su listovi (nazivaju se još i terminalnim čvorovima) i oni nemaju
potomke.
Jedan čvor ne sme biti potomak više od jednog čvora (u suprotnom imamo strukturu podataka
koja se zove graf). Terminalni nodovi (listovi) predstavljaju kraj igre, odnosno najveću
dozvoljenu dubinu stabla (u slučaju da nemamo celo stablo).
Horizont je dubina do koje je praktično moguće pretražiti stablo odlučivanja (stablo igre). Iz
više praktičnih razloga nije moguće pretražiti celo stablo kada je ono veliko (zahtevaju se
značajni resursi za obradu). Pošto se praktično pretražuje samo deo stabla do određene dubine
(horizonta) moguće je doći do pogrešnog zaključka ukoliko je uticajni potez odmah iza
horizonta. U tom slučaju, smatra se da je odluka pod uticajem efekta horizonta.
Na slici 3 prikazano je stablo igre za deo partije igre „Iks Oks“. Kao što se na slici može
videti, svaki potez predstavljen je jednim čvorom stabla. Iz tog čvora dalje se granaju
potomci tog čvora – potezi koji logički slede taj potez. Na svakom nivou stabla nalaze se
potezi iste „boje“, odnosno potezi istog igrača.
Koren stabla je trenutno stanje partije. Na redu da igra je igrač „X“. On može odigrati na
neke od tri raspoložive pozicije i to je na stablu predstavljeno sa tri potomka korenog čvora.
Nakon toga, na redu da igra je igrač „Oks“, koji za svaki od mogućih poteza igrača „Iks“ ima
svoje dve mogućnosti, jer gde god da „Iks“ odigra ostaju prazna dva polja na tabli s obzirom
na to da nijedan od tih poteza ne vodi kraju igre. Na ovom nivou već postoje terminalni
čvorovi, odnosno čvorovi koji se više ne granaju, jer označavaju potez u kome se igra
završava (pobedom ili nerešenim rezultatom). Kao što se na slici vidi, „Oks“ ima dva poteza
kojima završava partiju. Međutim, postoje i tri poteza koji vode daljem produžavanju igre.
Objašnjeni princip koristi se tokom generisanja celog stabla. Ako je u korenu stabla prazna
tabla, znači da je to početak partije. Stablo igre trebalo bi da iscrpe sve moguće poteze i
11
predstavi ih u sebi – to bi bilo kompletno stablo igre. Ukoliko to nije slučaj, već se stablo
generiše do određenog nivoa, onda imamo horizont (ta dubina predstavlja horizont). Nakon
kreiranja stabla ,celog ili delimičnog, potrebno je primeniti neki od algoritama traženja kako
bi se među svim raspoloživim potezima odabrao najbolji.
Algoritmi traženja dele se na slepe (neinformisane) i heurističke (informisane) algoritme.
Slepi algoritmi pretražuju celo stablo i garantuju najbolje rešenje – ukoliko se izvrše nad
celim stablom, odnosno najbolje rešenje do zadate dubine – ako se izvrše nad unapred
zadatim podstablom. Najpoznatiji slepi algoritam je MinMax.
Heuristički ili informisani algoritmi traže optimalno, a ne najbolje rešenje, jer traženje
najboljeg rešenja može trajati dugo. Neki od heurističkih algoritama su A*, First-Best (prvi
najbolji-još se naziva i “pohlepni algoritam”) itd.
Slika 3 Stablo igre
Pohlepnim algoritmom nazivamo algoritam iz kategorije heurističkih algoritama koji teži
neposrednom povećanju vrednosti neke ciljne funkcije, odnosno algoritam koji bira lokalno
optimalne akcije. Lokalna optimalnost znači da algoritam ne može da proceni dugoročni
kvalitet izabranih akcija, odnosno koliko te akcije doprinose ostvarenju konačnog cilja, već
da bira akciju koja se na osnovu znanja dostupnog u trentuku izbora procenjuje kao najbolja
među raspoloz¡ivim akcijama. Ovakvi algoritmi su često značajno jednostavniji za
formulaciju od algoritama koji garantuju optimalnost procesa rešavanja. Takođe, često daju
praktično prihvatjiva rešenja, iako često neoptimalna [2].
MinMax spada u grupu “slepih” odnosno neinformisanih algoritama traženja. Algoritam
zahteva da se najpre kreira stablo igre. Stablo ne mora da bude kompletno, već može biti
kreirano do određene dubine. Nakon kreiranja stable, vrši se evaluacija (ocenjivanje)
12
terminalnih čvorova (listova) stabla. Terminalni čvorovi ne moraju da budu na istoj dubini. U
slučaju da neki čvor predstavlja kraj igre (nemoguće dalje grananje) on je takođe terminalni
čvor [2][3].
Na slici 4. je prikazan deo partije u igri “Iks Oks” (objašnjenje MinMax algoritma).
Nakon ocenjivanja terminalnih čvorova, primenjuje se MinMax algoritam. MinMax
algoritam se sastoji u tome što se unutrašnji čvorovi stabla evaluiraju (vrednuju, dobijaju
vrednost) na osnovu vrednosti svojih potomaka.
Svi čvorovi stabla proglašavaju se za maksimizirajuće i minimizirajuće, naizmenično. Koren
stabla je maksimizirajući čvor, njegovi potomci minimizirajući, njihovi potomci opet
maksimizirajući i tako naizmenično do listova. Ako je čvor maksimizirajući, njegova
vrednost se određuje kao maksimum vrednosti njegovih potomaka, a ako je minimizirajuću,
kao minimum vrednosti njegovih potomaka. Na ovaj način odrede se vrednosti svih čvorova
u stablu.
Slika 4 Algoritam MinMax – igra “Iks-Oks”
Ovaj algoritam zapravo realno odslikava proces donošenja odluke kada čovek igra igru.
Evaluacija se vrši od listova prema korenu stabla, ali za objašnjenje logike krećemo od
korena ka listovim stabla.
U korenu stabla treba da se nađe potez koji taj igrač treba da odigra. Taj potez predstavlja
najbolji potez u analiziranom stablu (ili delu stabla). Svaki igrač teži da odigra najbolji potez
koji mu je na raspolaganju. Algoritam MinMax omogućava da najbolji potez “ispliva” do
korena stabla.
13
Međutim, protivnik teži da odigra najbolji potez za sebe, a to je ujedno i najgori potez za
trenutnog igrača. Upravo ovu situaciju simulira MinMax algoritam. Nivoi Max teže da
maksimiziraju vrednost poteza za trenutnog igrača dok nivoi Min teže da ih minimizuju.
Ocenjivanje za oba igrača vrši se istom funkcijom evaluacije, ali se za protivničkog igrača
uzima predznak minus.
Jedan od problema koji se javlja kod MinMax algoritma jeste pojava da kad se na svim
terminalnim čvorovima detektuje negativna vrednost (protivnik pobeđuje u svakom slučaju),
MinMax nema mogućnost da izabere adekvatan potez, jer su svi potezi jednake, negativne
vrednosti. Posledica ovoga je da se odabere prvi potez iz liste legalnih i time se stvara utisak
kao da je računar predao partiju ili da evaluacija nije dobra. Algoritam pretpostavlja da greške
neće biti napravljene, on vidi potez koji vodi pobedi i kad čovek to previđa.
Slika 5 Pogrešan potez zbog nesavršenosti u funkciji evaluacije
Ovo se može rešiti poboljšavanjem funkcije evaluacije. Ista pojava može se zapaziti kod
potomaka sa istom, pozitivnom vrednošću (slika 5). Tada se takođe bira prvi potez i ako on
može imati veću dubinu od nekog drugog. Naime, kao što se može videti na slici 5, plavi
igrač umesto da odigra na polje (4,2) i time završi partiju pobedom, bira potez koji je
evaluiran ranije (redosled evaluacije poteza). Odabrani potez zapravo ima istu vrednost
(sigurno vodi pobedi, crveni ni u kom slučaju nema šansu da pobedi) kao i potez za pobedu u
jednom potezu. Rešenje za ovaj problem je takođe u poboljšanju evaluacionih funkcija.
U oba slučaja korekcija evaluacione funkcije je minimalna – evaluaciona funkcija
jednostavno mora uzeti u obzir dubinu na kojoj se nalazi odabrani terminalni čvor.
U slučaju jednakih pozitivnih ishoda neophodno je od vrednosti čvora oduzeti dubinu kako bi
dublji čvorovi imali manju vrednost i na taj način bili diskriminisani u odnosu na čvorove
bliže korenu stabla (čvorovi sa manjom dubinom), jer oni brže vode pobedi.
U slučaju da svi čvorovi imaju jednaku negativnu vrednost, vrednostima čvorova je
neophodno dodati brojnu vrednost njihove dubine – time se dublji čvorovi favorizuju jer vode
14
porazu, ali najdužim putem i time mogu iskoristiti potencijalne greške protivnika za koje je
sam algoritam pretpostavio da ih neće biti.
MinMax ima exponencijalnu zavisnost vremena izvršenja od dubine stable traženja i to je
najveći ograničavajući faktor u njegovoj primeni. Međutim moguća su heuristička
poboljšanja MinMax algoritma u cilju efikasnijeg izvršenja. Takva poboljšanja su npr. Alfa-
Beta odsecanje, Killer move – killer heuristic (heuristika ubice), transpozicione tabele i
drugo.
Alfa-Beta odsecanje je tehnika koja ne menja kvalitet MinMax algoritma, tj. potez koji bi bio
odabran od strane MinMax-a biće odabran i od strane Alfa-Beta algoritma. Dobitak od
primene Alfa-Beta algoritma jeste u efikasnosti, odnosno omogućava da se ne analizira celo
stablo igre, već omogućava “odsecanje” dela stabla – odsečeni deo se ne analizira. Najveći
dobitak od Alfa-Beta algoritma jeste u slučaju da se najbolji/najgori potez analizira prvi (ili
među prvima) pri obilasku stabla po dubini. Na taj način, samo je taj čvor evaluiran, ostatak
je “odsečen” [2][3].
Slika 6 Primer Alfa-Beta odsecanja
Suština Alfa Beta odsecanja jeste logika iza samog MinMax algoritma. Neki potezi
jednostavno nikada neće biti odigrani zbog pozicije na kojoj se nalaze. Poboljšanje koje
ugrađuje Alfa-Beta odnosi se na uštedu vremena, odnosno odsečeni čvorovi se ne obrađuju, a
samim tim proces traženja poteza može biti značajno skraćen.
Uzmimo primer sa slike 6. Imajući u vidu da crveni čvorovi minimizuju (biraju minimum), a
zeleni maksimizuju (biraju maksimum), nakon evaluacije vrednosti -4, nema potrebe nastaviti
sa evaluacijom ostatka tog podstabla (pošto njegov roditelj vrši minimizaciju, veće vrednosti
sigurno neće uticati na roditelja, a s obzirom na to da koren vrši maksimizaciju, vrednost -1 je
već odabrana kao maksimum).
Algoritam se implementira kao rekurzivna procedura, pri svakom pozivu prosleđuje se
trenutna vrednost za Alfa (maksimum) i Beta (minimum). Implementacija Alfa Beta
algoritma biće data kasnije u delu koji opisuje praktičnu realizaciju.
Dobitak od Alfa Beta algoritma može biti značajan, naročito u slučaju velikog broja
terminalnih čvorova (veće dubine) i složenih (skupih, dugotrajnih) funkcija evaluacije.
Ukoliko se pravilno primeni, Alfa Beta omogućava ubrzavanje traženja kao i povećanje
dubine.
15
Slika 7 Alfa-Beta odsecanje – objašnjenje
Adaptivno povećanje dubine [2][3] je tehnika za povećanje performansi MinMax algoritma u
toku same partije. Pošto je inicijalno stablo traženja veliko, nije moguće pretražiti ga za
kratko vreme. Ova tehnika se sastoji u tome da se na početku partije koriste manje dubine
traženja, a kako partija odmiče, dubina se povećava sve do nekog trenutka u partiji kad
postaje neograničena. S obzirom na to da se broj raspoloživih poteza smanjio, manje je i
stablo te je moguće pretražiti ga brže u realnom vremenu.
Sortiranje legalnih poteza [2][3] je tehnika koja povećava performanse Alfa-Beta algoritma.
Alfa-Beta algoritam daje najbolje performanse ako se najbolji potez pretraži prvi – onda je
odsecanje najveće (nema nepotrebne evaluacije). Da bi se ovo postiglo, potrebno je da
generator poteza vrati legalne poteze u niz poređane u opadajućem redosledu po izgledima da
su najbolji, odnosno prvi treba da bude potez sa najvećim izgledima da je najbolji, pa onaj sa
manjim i tako redom. Sortiranje poteza može se obaviti po više kriterijuma (više kriterijuma
može se koristiti pri oceni da li potez ima izgleda da je najbolji). Najčešće se koristi
ocenjivanje uz pomoć transpozicione tabele (ulazi iz prethodne iteracije) ili evaluaciona
tabela.
Evaluaciona tabela [3] je tehnika koja omogućava da se samim pozicijama na tabeli dodeli
određena vrednost. Samim svojim položajem, neke pozicije su bolje od drugih. Pri ovome se
u obzir ne uzimaju pozicije ostalih figura iste boje. Koja god figura da se nađe na određenom
polju uzima tu vrednost kao početnu. Na slici 8 prikazane su vrednosti polja za igru „4 u
nizu“. Kao što se na slici vidi, favorizuju se polja u centru tabele, odnosno igrač treba da teži
da ovlada sredinom tabele. Dodeljene vrednosti su male, jer evaluaciona tabela ne treba da
ima prasudan uticaj na evaluaciju. Ona treba samo da se iskoristi kako bi u slučaju veoma
bliske/jednake evaluacije dva polja odabralo ono koje je bolje pozicionirano.
16
Slika 8 Vrednosti polja u evaluacionoj tabeli za igru „4 u nizu“
Transpoziciona tabela [3], tj. upotreba transpozicione tabele je još jedna od tehnika koja se
može upotrebiti radi poboljšavanja performanisi MinMax algoritma. Ideja iza ove tehnike je
sledeća: najbolji potez u jednoj grani stabla može istovremeno biti i najbolji u drugoj grani,
odnosno potez koji vodi do pobede u jednoj situaciji može takođe voditi do pobede u drugoj.
Ako se takav potez evaulira jednom, nema potrebe da se evaulira ponovo, pošto je to isti
potez.
U primeru na slici 9. prikazana je situacija u kojoj primena transpozicione tabele poboljšava
performanse (štedi evaluaciju jednog čvora) za igru šah.
Slika 9 Primer situacije u kojima primena transpozicione tabele donosi korist
Kao što se može uočiti sa slike, u prikazanoj situaciji, skakač može doći na ciljno polje preko
dva polja. Odakle god da dođe, krajnji potez je isti. U stablu igre ova situacija biće prikazana
kao dve grane stabla, obe sa po terminalnim čvorom identičnog sadržaja. U ovoj i sličnim
situacijama transpoziciona tabela omogućava da se takva situacija ne evaluira dva puta, već
samo jednom.
Transpoziciona tabela sa prvenstveno implementira kao heš tabela čija heš funkcija treba da
detektuje situacije kao na slici 9 preslikavajući tablu igre u indeks za pristup memorijskoj
17
lokaciji. Obe situacije sa slike 9 morale bi heš funkcijom biti preslikane u istu memorijsku
lokaciju.
Inkrementalno povećanje dubine stabla [3](Iterative Deeping) je tehnika koja poboljšava
performanse MinMax algoritma, a primenjuje se u situacijama kada je potrebno odabrati
najbolji potez u nekom ograničenom vremenskom intervalu. U realnim uslovima, tokom
testiranja, neophodno je da program uvek ima spreman potez za igru. To nije moguće dobiti
sa fiksnom dubinom stabla, jer dok se ne završi proces analize stabla nije moguće utvrditi
koji je potez najbolji.
Tehnika inkrementalnog povećanja dubine pruža mogućnost da se odabere najbolji potez u do
tada kreiranom stablu. Tehnika se implementira kroz niz iteracija sa sve većom i većom
dubinom (počevši od dubine 1) i pamćenjem do tada evaluiranih vrednosti u transpozicionoj
tabeli. Zahvaljujući tome što se prethodno izračunate vrednosti pamte u transpozicionoj tabeli
njih je moguće koristiti u narednim iteracijama. Iteriranje se prekida kada istekne zadati
period vremena (timeout), ili nastupi neka druga akcija (pošto se implementacija svodi na
proveru vrednosti kontrolne promenljive pre ulaska u narednu iteraciju; tu promenljivu može
postaviti ona akcija koju korisnik želi, to nije od važnosti).
Knjiga otvaranja i Knjiga završnica predstavljaju heurističke tehnike za unapređenje
MinMax algoritma na početku i kraju partije. Ideja knjige otvaranja je u tome da se na
samom početku partije ne troše resursi računara na izračunavanje poteza, jer je verovatnoća
pobede najmanja, a skup legalnih poteza najveći. U takvoj situaciji može se pribeći izboru
nekog od kvalitetnih poteza koji su ranije pripremljeni (smešteni u knjigu otvaranja).
Knjiga završnica primenjuje se u kompleksnim situacijama u završnici igre (kao što je mat u
šahu).
Killer heuristics - ideja je sledeća: ukoliko je u jednoj grani stabla na dubini d najbolji potez
W, ima izgleda da je on najbolji (ako je legalan) i u drugim granama stabla na istoj dubini.
Ilustrujmo to na primeru šaha: neka igraču koji je na redu preti mat u sledećem potezu i neka
nijedan njegov potez ne može da otkloni tu pretnju. Pretraživanjem stabla, u čvoru u kojem je
na potezu protivnik, otkriva se matni potez i on postaje killer potez (za dubinu 1). Pri daljem
pretraživanju stabla, na dubini 1 najpre se ispituje taj potez i kako on vodi pobedi protivnika,
alfa odsecanje čini nepotrebnim dalje ispitivanje poteza u tom čvoru. Time se broj čvorova
stabla ,koje u ovakvoj situaciji treba ispitati, drastično smanjuje [2][3].
18
4.Implementacija igre “4 u nizu”
Pri implementaciji igre „4 u nizu“ korišćen je modularni pristup, odnosno, igra nije razvijena
kao jedinstveno rešenje, već kao skup celina povezanih u jedinstvenu aplikaciju. Svaka od tih
celina može biti zamenjena-izmenjena nezavisno od ostalih samo pridržavajući se interfejsa
za komunikaciju sa ostalim delovima aplikacije (modulima).
Moduli koji čine aplikaciju su:
- Univerzalna platforma za logičke igre
- Jezgro sistema – implementaciono zavisni delovi univerzalne platforme
- GUI (grafički korisnički interfejs)
U implementaciji igre iskorišćen je algoritam MinMax kao osnova sistema za odlučivanje.
Kao što je ranije navedeno, MinMax spada u slepe algoritme traženja, a kao heuristička
poboljšanja ugrađena su Knjiga otvaranja, Alfa Beta odsecanje, Evaluaciona tabela,
Sortiranje poteza, Inkrementalno povećanje dubina, Adaptivno podešavanje dubine i
Transpoziciona tabela.
4.1. Univerzalna platforma za logičke igre
Jedan od ciljeva ovog rada jeste i implementacija univerzalne platforme za logičke igre,
odnosno univerzalne osnove koja bi mogla da se koristi ne samo za igru „4 u nizu“, već i za
druge igre koje se igraju na tabli.
Platforma je implementirana u okviru TableGameBase projekta u solution-u. Sam projekat
podeljen je na više celina pomoću direktorijuma koji ujedno odslikavaju i podelu projekta na
funkcionalne celine.
Projekat se sastoji iz sledećih funkcionalnih celina:
- Book (deo koji zaokružuje funkcionalnosti vezane za knjigu otvaranja i završnica
- Evaluation (deo koji omogućava implementaciju funkcija evaluacije i pomoćne
mehanizme uključene u proces evaluacije)
- Players (funkcionalnosti koje omogućavaju manipulisanje igračima, kako za čoveka
tako i za simuliranog protivnika (AI).
- Table (model tabele na kojoj se igra)
- Tree (logička celina koja sadrži klase i funkcionalnosti koje manipulišu stablom
traženja – stablom igre)
- ITableGame (glavni interfejs za implementaciju igre, svaka igra koja bi koristila
platformu za igre, mora implementirati ovaj interfejs i povezati ga sa korisničkim
interfejsom (UI kontrolama, prozorima, dugmićima i akcijama)
4.1.1. Book
U igri “4 u nizu” implementirana je knjiga otvaranja. Kada se uključi ovo poboljšanje prva tri
poteza biraju se iz internog skupa poteza. Potezi koji su na raspolaganju grupisani su oko
središnjeg dela table, jer ti potezi pružaju najveće mogućnosti za pobedu – mogu biti
kombinovani sa najvećim brojem drugih poteza.
19
Listing 1. prikazuje implementaciju klase koja reprezentuje jedan ulaz u knjizi otvaranja.
Atribut ListID predstavlja identifikator liste poteza, odnosno taj parametar treba da sugeriše
kada treba (kada je pogodno) upotrebiti poteze iz atributa Moves. Sami potezi smešteni su u
atributu Moves.
Listing 1 Klasa koja prectavlja jedan ulaz u knjigu otvaranja/zatvaranja
U implementaciji igre, kao identifikator poteza, iskorišćen je redni broj poteza. U knjigu
otvaranja dodate su 3 liste poteza, po jedna za svaki od tri početna poteza. Za prvi potez, bira
se potez iz liste sa identifikatorom 1, za drugi potez iz liste sa identifikatorom 2 i tako redom.
Ovo je najjednostavniji način upotrebe knjige otvaranja (zapravo i vrlo primitivan), ali je cilj
implementacije zapravo bio da se implementira mehanizam koji univerzalan i može se lako
poboljšati.
U samoj realizaciji nije bilo posebne implementacije ove funkcionalnosti, već je zadržana ova
najosnovnija iz univerzalne platforme.
4.1.2. Evaluation
U implementaciji igre “4 u nizu” realizovana su tri “evaluatora”. Evaluatori su klase koje
implementiraju interfejs IEvaluation koji je prikazan na listingu 2.
Listing 2 Interfejs evaluatora
Sama evaluacija u igrama može biti realizovana i samo jednom funkcijom koja će brojnom
vredniošću opisati neki potez, međutim, korišćenje interfejsa, a iz toga sledi i klasa koje ga
implementiraju, omogućava laku promenu funkcije evaluacije odnosno implementaciju više
različitih funkcija evaluacije i njihovo testiranje bez potrebe da se menja kod.
Modularnost je omogućena upravo ovim pristupom. Veoma lako se može modul evaluacije
zameniti bez potrebe da se menja ostatak projekta.
Atribut MaxPoints označava maksimalnu numeričku vrednost koja može biti dodeljena
potezu (na koju potez može biti evaluiran). Ova konstanta se koristi pri inicijalizaciji
promenljivih (npr. kod Alfa-Beta alfa se inicijalizuje na –MaxPoints, a beta na MaxPoints) i
pri ispitivanju uslova.
20
Metoda Evaluate je glavna metoda evaluatora i ona neposredno vrši ocenjivanje (evaluaciju)
poteza (čvorova u stablu traženja). Način ocenjivanja zavisi od implementacije, odnosno
svaki evaluator koji implementira ovaj interfejs može primeniti različitu tehniku.
Metode NewEvalObject, NewMax i NewMin su metode koje kreiraju nove vrednosti i odmah
ih inicijalizuju na neku specifičnu vrednost. NewEvalObject kreira novi objekat i ne
inicijalizuje numeričke vrednosti. NewMax i NewMin kreiraju instance objekta koji opisuje
vrednost poteza (specifičan objekat za svaki evaluator), i inicijalizuju ga na maksimum,
odnosno minimum (korišćenjem MaxPoints atributa).
Pri evaluaciji ponekad nije dovoljno potez opisati samo jednom vrednošću. Ponekad se javlja
potreba da se potez opiše sa više atributa. Najbolji način da se ovo postigne je korišćenjem
objekata koji imaju potrebne atribute za opis poteza. Evaluator onda ima zadatak da te
atribute postavi na određenu (ocenjenu) vrednost.
Dakle, ocenjivanje poteza se ne vrši korišćenjem jedne brojne vrednosti, već složenim
objektom koji ocenjuje više parametara. Međutim, broj parametara može biti različit od
evaluatora do evaluatora (neki evaluatori mogu ocenjivati samo pobedu, drugi mogu uzimati
u obzir i raspored figura itd.).
Zbog toga, klasa koja opisuje poteze nije strogo definisana, već je apstraktna. To je IVal
klasa (listing 3).
Pri evaluaciji poteza takođe je moguće uzeti u obzir samu poziciju polja, bez posmatranja
konteksta, odnosno samim tim što je potez tu gde je, on može biti vrednovan. Za to je
predviđena tabela EvaluationTable. Pri evaluaciji polja, kao inicijalna vrednost koristi se
vrednost iz tabele EvaluationTable na koordinatama koje ima polje (naime, dimenzije tabele
su iste kao i dimenzije table za igru tako da svako polje ima dodeljenu vrednost).
U implementaciji ovo može biti i promenjeno, uzimajući u obzir da je ovo interfejs
(IEvaluation), implementaciona klasa može opisane mehanizme u memoriji implementirati na
bilo koji način.
Takođe, javlja se potreba da se na evaluaciju poteza (stanja tabele) utiče spolja, nekom
vrednošću. Za tu namenu predviđen je atribut Correction u klasi IVal.
Kao što se vidi sa slike svaka klasa za vrednovanje mora naslediti apstraktnu klasu IVal.
Samim tim mora definisati neke atribute. NumericValue je numerička vrednost koja se koristi
za upoređivanje poteza, međutim kako se ta vrednost određuje, nije strogo definisano već je
ostavljeno evaluatorskim implementacionim klasama da je odrede.
Ovaj pristup omogućava da objekti koji opisuju poteze pomoću različitih evaluatora budu
međusobno uporedive. Radi što lakšeg upoređivanja vrednosti različitih objekata za
evaluaciju predefinisani su i operatori >,<. Predefinisanje operatora omogućava direktno
poređenje dva objekata u kodu, bez potrebe za dodatnim izračunavanjima na mestu gde je
poređenje potrebno. Način predefinisanja operatora prikazan je takođe na listingu 3.
21
Listing 3 Abstraktna klasa koja prectavlja vrednost poteza u igri
Kratak primer ove opisane klase: ukoliko , na primer za određenu igru želi implementirati
dve evaluacione funkcije A i B. Evaluacijona funkcija A uzima u obzir samo pobedu ili poraz,
dok B uzima još neki koristan parametar pri ocenjivanju. Ukoliko se koristi univerzalna
platforma za logičke igre, obe ove klase moraju implementirati interfejs IEvaluation. Obe
metode evaluacije takođe mogu definisati i klasu koja će se koristiti da numerički opiše
čvorove, a koja mora naslediti klasu IVal. Iz ovoga sledi da klase A i B mogu imati pomoćne
klase A1 i B1 koje nose brojne vrednosti. Pošto A1 i B1 nasleđuju IVal, one su međusobo
uporedive, jer postoji predefinisani operator. Samim tim, u kodu je moguće direktno postaviti
uslov A1 > B1 što znači da je moguće upoređivati različite klase, direktno. Sam operator
zapravo upoređuje atribut NumericValue koji svaka klasa izračunava na svoj način, ali ga
mora imati.
Za potrebe igre “4 u nizu” implementirana su tri evaluatora (biće opisani kasnije) a samim
tim i tri objekta za vrednovanje (BasicVal, ExtendedVal, TestVal) koji su svi međusobno
uporedivi i ako za opis poteza koriste različit broj parametara (svi nasleđuju klasu IVal).
U ovom slučaju nisu korišćeni interfejsi, jer je bilo potrebno da neke stvari budu definisane,
kao što su operatori i metoda ToString(). Da je korišćen interfejs, ove dve stvari morale bi da
budu definisane u svakoj od klasa koje implementiraju interfejs. Korišćenje abstraktne klase
omogućava da se to definiše jednom i koristi u izvedenim klasama (kao što je slučaj i sa
predefinisanim operatorom – to u interfejsu ne bi bilo moguće uraditi).
Za opisivanje transpozicione tabele takođe je iskorišćen interfejs ITranspositionTable.
Interfejs zahteva samo implementaciju metode za direktan pristup tabeli. Sama tehnika
smeštanja podataka u memoriju ostavljena je implementacijama interfejsa na rešavanje. Na
listingu 4. prikazan je interfejs ITranspositionTable.
22
Listing 4 Interfejs transpozicione tabele
Metoda Reset poziva se pre svakog poteza i ima zadatak da isprazni transpozicionu tabelu.
U vezi sa realizacijom transpozicione tabele realizovana je još i klasa koja opisuje ulaze u
transpozicionu tabelu, odnosno klasa TransTableRecord (listing 5). Svaki ulaz u tabelu
predstavljen je klasom TransTableRecord. Atribut Key predstavlja ključ za direktni pristup.
On se u slučaju implementacije uz korišćenje heš tabele ne mora koristiti, jer bi pristup bio
direktan, pomoću indeksa u tabeli. Atribut Val predstavlja memorisanu vrednost.
Listing 5 Ulaz u transpozicionu tabelu
4.1.3. Players
U direktorijumu Players grupisane su klase i interfejsi koji logički objedinjuju sve
funkcionalnosti vezane za opisivanje igrača i njihovih akcija, bilo da se radi o čoveku ili AI
igraču.
Za opis igrača definisan je interfejs IPlayer (listing 6). Ovaj interfejs se koristi za oba tipa
igrača, čoveka i AI. Prvenstveni cilj ovog interfejsa jeste da objedini sve atribute zajedničke
za oba tipa igrača, a i da predstavlja jedinstveni tip iz koga su izvedene obe vrste igrača.
Listing 6 Interfejs igrača
Za predstavljanje igrača čoveka koristi se klasa Player. Ova klasa nema atributa osim onih iz
osnovne klase (interfejsa). Implementacija je prikazana na listingu 7.
23
Listing 7 Klasa koja reprezentuje igrača čoveka
Za predstavljanje AI igrača koristi se apstraktna klasa IAIPlayer. Klasa je apstraktna, jer
implementira osnovne metode koje se koriste u igri, ali pruža mogućnost da se u
implementaciji to promeni (override). Atributi i metode ove klase prikazani su na listingu 8.
Listing 8 Abstraktna klasa AI igrača
24
Atributi UseBookForOpening, UseMultiTasking, UseAlphaBeta, UseTransTable,
UseTimer, UseIterativeDeeping, UseEvaluationTable, UseMoveSorting i UseAdaptiveDepth
označavaju istoimene dodatke MinMax algoritmu. Neki od dodataka su heuristički ,a neki su
implementacioni (kao Multi-Tasking i Timer).
Ovi parametri određuju profil AI igrača, odnosno određuju mu šta sve može da koristi pri
donošenju odluke u igri. Cilj svih dodataka je da poboljšaju proces odlučivanja i povećaju
performanse.
Atribut Book predstavlja knjigu poteza koja je na raspolaganju AI igraču i koju on može
koristiti ako mu je uključena opcija UseBookForOpening.
Atribut Evaluator predstavlja klasu evaluatora koja je pridružena AI igraču da je koristi pri
evaluaciji poteza. Tip ovog atributa je IEvaluation (interfejs) što znači da kao evaluator može
biti dodeljena klasa samo iz implementacije (univerzalna platforma ne nudi evaluatore, jer
evaluacija mora biti vezana i specifična za svaku igru, već nudi samo interfejs koji evaluator
mora implementirati kako bi bio korišćen od strane platforme).
Atribut TransTable je je transpoziciona tabela koja je na raspolaganju AI igraču pri evaluaciji
poteza. Važi isto što i za IEvaluator, odnosno sama platforma diktira samo interfejs koji
implementacija transpozicione tabele mora da implementira ali ne i samu implementaciju.
Razlog za ovo jeste taj što transpoziciona tabela može biti implementirana na različite načine,
zavisno od potreba igre (kao heš tabela, kao niz, itd.).
Depth i MaxDepth su trenutna dubina generisanog stabla traženja i maksimalna dubina stabla
traženja koju treba generisati, respektivno (oba ova parametra značajna su kod
inkrementalnog povećanja dubine).
Sve metode iz klase implementirane su kao virtuelne, odnosno nude implementaciju, ali u igri
se ne moraju koristiti ukoliko se implementacijom zahteva drugačiji pristup (override ovih
metoda u samoj implementaciji).
Metoda Reset ima ulogu da resetuje sve promenljive, koje se koriste u toku donošenja odluke,
na inicijalnu vrednost. Poziva se nakon ili pre svakog poteza.
Metoda Play inicira proces odabira poteza (traženja). Sam proces se razlikuje od dodataka
koji su na raspolaganju pri donošenju odluke (listing 9).
Ukoliko se koristi sat, on se inicira, ukoliko se koristi inkrementalno povećanje dubine ili
adaptivno povećanje dubine određuje se početni i krajnji parametric, a zatim se kreće u
proces kreiranja stabla i evaluaciju. Nakon završetka procesa evaluacije, bira se najbolji potez
(u samoj virtuelnoj metodi to zapravo nije odvojeno), a nakon toga se aktivira događaj
(event) koji obaveštava sve zainteresovane strane (najčešće GUI kako bi to bilo i prikazano
na korisničkom interfejsu) o odabranom potezu.
25
Listing 9 Play metoda – traženje poteza
Metoda CreateSearchTree inicira kreiranje stabla traženja. Na početku ove metode, poziva se
generator poteza (listing 10) i od tih poteza kreće generisanje stabla traženja. Ukoliko je na
raspolaganju mogućnost sortiranja poteza, potezi se sortiraju na bazi njihovih vrednosti u
26
evaluacionoj tabeli. Takođe, metoda podržava i paralelno izvršenje (ukoliko je dozvoljeno
koristiti ga).
Listing 10 Osnovna metoda za generisanje stabla traženja
Iz metode CreateSearchTree na svakom nivou stabla poziva se metoda GenerateNextLevel
koja kreira sledeći nivo stabla (listing 11).
27
Listing 11 Rekurzivna metoda za generisanje narednog nivoa u stablu traženja
Metoda za generisanje stabla je izuzetno bitna, jer utiče i na evaluaciju. Naime, pri kreiranju
čvorova stabla, dodaje se i event handler koji obrađuje događaj kada se čvoru dodeli
vrednost.
Suština ove obrade jeste da kada jedan čvor dobije vrednost on “obaveštava” svog roditelja o
tome i roditelj onda može ažurirati svoju vrednost. To opet inicira ažuriranje vrednosti
njegovog roditelja i tako rekurzivno do korena generisanog stabla.
Ova metoda rekurzivno poziva sama sebe ukoliko trenutni čvor ne predstavlja kraj igre.
28
Metoda PlayByBook (listing 12) nalazi potez u knjizi poteza koji odgovara traženim
kriterijumima i odabira ga.
Listing 12 Metoda koja vraća potez iz knjige otvaranja/zatvaranja
Metoda MinMax implementira MinMax algoritam traženja (listing 13). Ova metoda poziva
se iz metode Play nakon kreiranja stabla traženja za koren generisanog stabla (koren
generisanog stabla prosleđuje se kao parametar funkcije).
Metoda rekurzivno poziva sama sebe i pri svakom pozivu proverava da li sme da nastavi (u
slučaju inkrementalnog povećanja dubine sat postavlja kontrolnu promenljivu StopSearch na
true i time zaustavlja dalju evaluaciju stabla).
Metoda poziva sebe rekurzivno za čvorove sve veće dubine dok ne dođe do terminalnih
čvorova (u smislu terminalnih čvorova celog stabla ili terminalnih čvorova na horizontu, sve
jedno) a onda vrši evaluaciju tih čvorova korišćenjem dodeljenog evaluatora. Pri evaluaciji,
koristi se transpoziciona tabela ukoliko je dozvoljeno. Takođe, ukoliko je to dozvoljeno,
metoda se izvršava paralelno za sve potomke tekućeg čvora.
Metoda evidentira neke kontrolne parametre kao što su broj pogodaka i promašaja u
transpozicionu tabelu kao i ukupan broj evaluiranih čvorova.
29
Listing 13 Implementacija MinMax algoritma
Metoda Alfa-Beta implementira istoimeno heurističko poboljšanje MinMax algoritma
(opisano u prethodnim delovima). Implementacija metode prikazana je na listingu 14. Kao i
kod osnovnog algoritma traženja MinMax-a, metoda Alfa-Beta počinje proverom
zadovoljenosti uslova za prekid traženja (StopSearch) koje postavlja inkrementalni način
traženja (inkrementalna promena dubine traženja). Metoda je takođe rekurzivna, a kao
parametri pri prvom pozivu prosleđuju se koren generisanog stabla traženja i maksimalna
vrednost (A) inicirana na najmanju moguću i minimalna vrednost (B) inicirana na
maksimalnu vrednost.
Iniciranje na suprotne vrednosti radi se namerno kako bi se osiguralo da one budu zamenjene
već pri prvom izvršenju. Kada se evaluira terminalni čvor, ta se vrednost upisuje u
transpozicionu tabelu – ako je dostupna, ili se iz nje pročita vrednost ako je takav čvor već
evaluiran ranije. Zatim se proveravaju Alfa (A) i Beta (B) i vrši se odsecanje u skladu s
pravilima koja su opisana ranije. Odsecanje se praktično vrši tako što se prekida dalja
evaluacija čvorova na tom nivou.
Po detekciji odsecanja, vrši se i korekcija kontrolnih parametara koji broje koliko je
odsecanja bilo. Kao i kod MinMaxa broji se i broj pogodaka i promašaja u transpozicionu
tabelu kao i ukupan broj evaluiranih čvorova.
30
Listing 14 Implementacija Alpha-Beta algoritma
Metoda Evaluate je glavna metoda za evaluaciju (listing 15). Ona vrši ocenjivanje poteza
(čvora) pozivanjem dodeljenog evaluatora kao i invertovanje (postavljanje znaka – ispred
vrednosti) ako je evaluacija pozvana za čvor u kome igra protivnik (ninimizirajući čvor).
Detekcija potrebe za invertovanjem vrši se testom parnosti dubine na kojoj se čvor nalazi
(neparni čvorovi su maksimizirajući, parni minimizirajući). Kao što se vidi sa slike, osim
naredbe Invert koja se koristi za evaluaciju protivničkih poteza (menja znak), postoji i
korekcija vrednosti po dubini. Suština je da se koriguje vrednost čvora ukoliko svi čvorovi
imaju istu vrednost. Najbolji će onda biti potez sa najvećom dubinom ako odlaže poraz
najduže, odnosno najmanjom ako ubrzava pobedu.
31
Listing 15 Evaluaciju poteza odabranim evaluatorom
4.1.4. Table
U direktorijumu Table nalazi se abstraktna klasa ITable koja definiše način pristupa tabli za
igranje i njenim atributima kao i neke pomoćne klase koje se koriste u toku partije.
Prava od pomoćnih klasa je GameOverDetails koja nosi podatke o pobednuku u partiji.
Instanca ove klase kreira se kada se igra završi. Atribut Winner označava boju igrača koji je
pobedio. Atributi X1,Y1 i X2,Y2 označavaju koordinate početka i kraja niza figurica koji je
doveo do pobede. Implementacija je prikazana na listingu 16.
Listing 16 Implementacija klase koja nosi podatke o kraju igre
Enumerator FieldStata predstavlja skup vrednosti koje može uzeti svako polje u tabeli, može
biti prazno, zauzeto crvenim i zauzeto plavim (listing 17). Pored ovog podatka, klasa
FieldDesc sadrži i podatak o poziciji polja (atributi X i Y).
Svako polje u matrici koja reprezentuje tablu za igru sadrži po jednu instancu klase
FieldDesc.
32
Listing 17 Klase i enumeratori koji se koriste za opis polja na tabli
Glavna klasa je apstraktna klasa ITable koja opisuje način pristupa tabli igre i njenim poljima
(listing 18).
Listing 18 Univerzalna tabla igre
Predefinisani operator + omogućava da se sabiraju potezi sa matricom, odnosno da se u
trenutno stanje partije doda potez. Kada neko od igrača odigra potez, potez se u tabeli dodaje
kao zbir stare tabele i novog poteza. Rezultat je nova tabela koja sadrži i taj novi potez.
Ovaj operator omogućio je znatnu uštedu u pogledu memorije koja se troši pri izvršenju
programa, jer zahvaljujuci njemu nema potrebe da svaki čvor čuva u stablu traženja tablu na
koju se odnosi već samo koren stable, a svi ostali čvorovi pamte samo svoj potez. Ovo će biti
objašnjeno detaljnije kasnije.
33
4.1.5. Tree
Direktorijum Tree objedinjuje klase i interfejse za opisivanje stabla traženja. Klasa TreeNode
(listing 19) objedinjava sve funkcionalnosti vezane za čvor stabla (TreeNode). Na samom
početku definisan je delegat koji opisuje interfejs metoda koje obaveštavaju o promeni
vrednosti čvorova potomaka.
Listing 19 Čvor stabla traženja
Svaki čvor prethodnik (roditelj) mora dodati funkciju koja će se pozvati kad neki od njegovih
potomaka promeni vrednost. Na taj način omogućeno je da on lako koriguje svoju vrednost.
Metoda se dodaje u metodi GenerateNextLevel u klasi IAIPlayer.
34
Takođe definisan je i enumerator NodeType koji opisuje da li je čvor maksimizirajući ili
minimizirajući. Ova vrednost za svaki novi čvor takođe se postavlja u GenerateNextLevel
metodi u klasi IAIPlayer.
Jedan od klučnih elemenata ove klase je atribut Table koji daje tablu koju taj čvor predstavlja.
On je implementiran kao rekurzivan radi uštede memorije (pre ovakve implementacije, u
verziji u kojoj je svaki čvor imao svoju tabelu na dubini 5, program je u operativnoj memoriji
zauzimao oko 1.3GB što je neprihvatljivo, sa novom implementacijom za dubinu 6 zauzima
oko 300MB).
Kolekcija potomaka (čvorova sledbenika) predstavljena je klasom TreeNodeCollection
(listing 20). Razlog zašto je ovo implementirano kao zasebna klasa, a ne kao prosta; list u
okviru svakog čvora jeste dodavanje metoda kao što su ToString() koja pruža lako izdavanje
skupa čvorova pri debagiranju i uvid u njihove vrednosti, a i lakše oslobađanje memorije
(garbage collector u .net frameworku oslobađa memoriju čim ne postoji nijedna referenca na
taj objekat u programu). Sa ovakvim pristupom cela kolekcija se oslobađa samo uništavanjem
jednog objekta.
Listing 20 Klasa koja prectavlja potomke čvora
4.1.6. Table game
Ova celina implementira samu logiku igre.
Pomocna klasa MoveInfo nosi informacije o odabranom potezu nakon što se završi proces
traženja. Od informacija koje ovaj objekat nosi tu su: broj alfa odsecanja, broj beta odsecanja,
35
sam potez, celokupnu transpozicionu tabelu, broj pogodaka i promašaja u transpozicionu
tabelu, dubina traženja na kojoj je nađen potez, vreme početka i kraja traženja.
Svi ovi podaci ne opterećuju memoriju (ne zauzimaju dodatni prostor), jer se objekti u .net
frameworku prenose isključivo po referenci. Dakle, ne prave se kopije postojećih već se
prenose reference na postojeće. Na listingu 21 prikazana je implementacija klase.
Listing 21 Klasa koja opisuje odabrani potez
Na listingu 22 prikazan je interfejs ITableGame koji je glavni interfejs za logičke igre. On
upravlja samom logikom igre.
Implementacija ovog interfejsa mora obezbediti metodu koja kao parametar prihvata objekat
tipe MoveInfo i ta metoda biće pozvana kad se završi proces traženja. Najčešće je ta metoda
povezana sa interfejsom i prikazuje odabrani potez korisniku na grafičkom interfejsu.
Listing 22 Interfejs za realizaciju logike igre
36
Takođe, implementacija interfejsa mora sadržati listu igrača (predstavljenih atributom
IPlayer[] a s obzirom na to da je to niz interfejsa IPlayer, u tom nizu može se naći AI igrač ili
čovek budući da obe klase nasleđuju IPlayer interfejs. Koliki će broj igrača biti i kog će oni
tipa biti, zavisi od potreba same implementacije (konkretne igre); sama platforma to ne
ograničava.
CurrentPlayer i CurrentPlayerIndex ukazuju na trenutnog igrača u partiji (onog koji je na
potezu ili čije je potez u toku).
Veoma značajna metoda koja se mora implementirati u implementacionoj klasi jeste
NextPlayer. Ova metoda je bitna zato što zavisno od implementacije ove metode u igri se
igrači mogu smenjivati naizmenično ili na bilo koji drugi način. Ovo omogućava da se
interfejs primeni na veoma veliki skup igara, ako ne i na sve.
4.1.7. Paralelizacija
U implementaciji je u cilju postizanja paralelizma korišćena biblioteka TPL (framework 4.0).
Ova biblioteka omogućava paralelno izvršenje petlji. Takođe ova biblioteka sadrži još neke
korisne implementacije (taskove, niti itd.) koje omogućavaju lako korišćenje nekih
tradicionalnih metoda paralelizacije i multi-taskinga.
Kao jedan od efekata paralelizma u izvršenju jeste i mutacija koja je korisna u smislu
varijacija u igri, odnosno, pošto se ne igra uvek isti potez, stvara se utisak da se igra sa
čovekom. Ovo se događa zbog toga što pri paralelnoj obradi nema garancija koji će element
biti prvi obrađen. Prvi koji bude obrađen, a zadovoljava uslove, biće odabran. To nije uvek
isti potez.
U prilogu obrazloženja uticaja paralelizma na izvršenje programa, data je tabela 2 koja treba
da pokaže uticaj paralelizma na trajanje izvršenja programa za različite dubine stabla traženja
(navedena vremena označavaju vreme potrebno za prvi potez, sva ostala poboljšanja su
aktivirana – samo je TPL izostavljen kod testiranja sekvencijalnog izvršenja). U tabeli 2
uporedo su prikazana vremena izvršenja pri sekvencijalnom i paralelnom izvršenju.
Dubina stabla TPL (s) Sekvencijalno (s)
1 0.05900 0.0380
2 0.06980 0.0624
3 0.08200 0.0980
4 0.17960 0.2660
5 0.68763 1.3268
6 4.27575 8.8721
7 34.54829 61.21468
Tabela 2 Uticaj paralelizma na vreme izvršenja
Na slici 10. prikazani su grafici koji odslikavaju vrednosti iz tabele 2. Sa grafika se može
uočiti eksponencijalna zavisnost vremena izvršenja MinMax-a od dubine stabla traženja (kao
što je ranije napomenuto).
37
Slika 10 Uporedni grafički prikaz zavisnosti vremena izvršenja od dubine
Takođe, važno je napomenuti zašto je u implementaciji korišćena ‘for’ petlja umesto ‘foreach’
petlje (koja je inače mnogo lakša za korišćenje od strane programera).
Razlog za to su performanse. Naime, dvostruko je brže iteriranje korišćenjem for petlje u
odnosu na iteriranje korišćenjem foreach petlje. Takođe, iz istog razloga se koriste Array
liste (nizovi) umesto generičkih listi ,koje su inače izuzetno praktične i lakše za korišćenje od
običnih array listi - nizova. Naime, iteriranje kroz Array niz je dvostruko brže od
iteriranja kroz listu. Experimentalno se može utvrditi da je za veći broj iteracija (oko
100000) iteriranje sa for kroz noz čak do 5 puta brže nego iteriranje kroz listu sa foreach.
Vremena koja su u tabeli 2. postignuta su na PC-ju sledeće konfiguracije:
CPU Intel i5 2500k – Turbo Boost unlocked
RAM DDR3 – 1333 MHz – 2GB – Single channel
HDD 500GB – 7200rpm
Tabela 3 PC konfiguracija na kojoj je izvršeno testiranje
4.1.8. Problem sinhronizacije rekurentnih taskova
Prvobitna implementacija aplikacije imala je paralelizam implementiran preko taskova. Svaki
nivo generisanja stabla bio je zasebni task. U ovakvoj implementaciji javlja se problem
sinhronizacije tih taskova – neophodno je znati kada je celokupno stablo traženja kreirano
kako bi se krenulo u njegovu evaluaciju. Dodatni problem ovde jeste što su taskovi
rekurzivni, odnosno svaki čvor kreira svoje potomke pozivanjem iste metode u kojoj je i sam
kreiran. Zbog ove činjenice teže je realizovati mehanizam za sinhronizaciju nego samo
kreiranje paralelnih taskova.
Sam TPL omogućava više pristupa za realizaciju paralelizma::
- Implementacija pomoću taskova
- Implementacija pomoću niti (threadpool)
- Implementacija paralelizacijom petlji
Pri upotrebi TPL-a kao generatora taskova (tako što se dodaju taskovi u interni bafer TPL-a)
performanse se zapravo degradiraju. Zbog nemogućnosti kontrole broja taskova, jer je sama
metoda koja treba da se izvrši rekurzivna, svaki task dobija zasebnu nit koja će ga obrađivati.
0
10
20
30
40
50
60
70
1 2 3 4 5 6 7
TPL Sekvencijalno
38
Posledica ovoga jeste da se zauzme ogromna količina memorije. Naime, pri pokretanju svake
niti pod windows OS-om rezerviše se oko 1MB radne memorije za njeno izvršenje. Imajući u
vidu da je broj niti približno jednak broju čvorova u stablu (svaki task kreira svoju decu, a
deca opet kreiraju svoje taskove za svoje potomke).
Posledica ovoga jeste usporavanje sistema. Zapravo, ovoliki broj niti ima negativan efekat i
degradira performanse. Takođe, na određenoj dubini stabla (nakon kreiranja određenog broja
taskova – niti) dolazi do greške. Do dubine 4 (oba igrača do dubine 4) program se izvršava,
međutim za dubine 5,6 i 7 dolazi do greške.
Takođe, problem koji se javlja u implementaciji ovog rešenja uz upotrebu TPL-a jeste i
sinhronizacija. TPL poseduje ugrađen mehanizam za sinhronizaciju taskova pokrenutih pod
njegovom kontrolom. To se obavlja sledećom metodom:
Listing 23 Ugrađen metod sinhronizacije taskova ugrađen u TPL
Ova metoda omogućava da sam TPL upravlja izvršenjem pokrenutih taskova. Svodi se na to
da se poziva prosleđena metoda nakon što se svi taskovi iz date liste taskova završe.
Međutim, postoji veliki praktični problem u slučaju implementacije uz upotrebu ove tehnike
za sinhronizaciju taskova.
Pošto je lista taskova zajednička (pošto je kritični resurs, zaštićena je LOCK blokom), a
metoda koja se izvršava je rekurzivna, svaki task menja listu taskova u kojoj se sam nalazi, a
za sinhronizaciju je neophodno proslediti istu tu listu. Međutim, pošto je prosleđena lista
podložna promenama u toku izvršenja, u praksi se dešava de se više puta detektuje prazna
lista taskova i time se pogrešno izazove događaj koji signalizira da je stablo kreirano.
Ovo je posledica implementacije. Iako je lista taskova javna, TPL-u se prosleđuje samo deo
(celokupna do tada kreirana lista). Na primer, ukoliko imamo 3 taska, koji se dodaju jedan po
jedan, najpre se u listi taskova doda prvi i krene se u njegovo izvršenje, a TPL-u se prosleđuje
ta lista (sa samo tim jednim taskom). TPL čeka da se taj jedan task završi. Taj task pri
izvršenju kreira 2 nova taska i dodaje ih u listu taskova, pri čemu je već detektovano
izvršenje prvog taska, a pošto druga dva taska još uvek nisu dodata u listu, dolazi do
signalizacije kraja (jer je lista taskova TPL-a prazna). Međutim, taskovi koji se upravo sada
izvršavaju opet menjaju listu i nakon njihovog izvršenja se ponovo signalizira isti događaj.
Ovo se ne dešava na prvom nivou (kao što je opisano u primeru) već na višim nivoima ali je
prvi nivo dobar za primer. U suštini radi se o klasičnom problemu proizvođač-potrošač, ali
39
pošto se ne radi o podacima već o metodama koje se izvršavaju unutar niti – operativni sistem
menja prioritet niti ,te nema garancije da će se niti završiti u redosledu izdavanja (pokretanja).
Poboljšanje rešenja trebalo je da donese dodatni brojač internih taskova. Pri dodavanju taska
u list čekanja na izvršenje inkrementira se brojač taskova. Po završetku taska isti taj brojač se
dekrementira. Kad brojač dostigne vrednost 0, to je događaj koji se čeka. Implementacija
ovog rešenja prikazana je na listingu 24.
Listing 24 Metoda sinhronizacije pomoću brojača
U praksi se dešava isto kao i kod prethodne implementacije. Svako pokretanje novog taska
inkrementira brojač a završetak izvršenja dekrementira isti taj brojač. Nema liste taskova.
Međutim i ovde se desi da se više taskova završi nego što se pokrene pa se detekcija
vrednosti 0 za brojač (to je trenutak u kome treba signalizirati da je proces završen). Takođe,
kao i u prethodnoj tehnici, problem se ne javlja na malim dubinama stabla već na dubinama
većim od 3. Uzrok problema u sinhronizaciji jeste rekurzivna metoda koju niti izvršavaju.
Sledeći pokušaj poboljšanja bio je pomoću timer-a. Kad se proces pokrene, pokrene se i sat
koji se resetuje nakon svakog novog pokrenutog taska. Znači svaki novi task resetuje sat koji
odbrojava u nazad. Ovo omogućava da sat bude resetovan zadnji put kad zadnji task bude
pokrenut (ili završen – resetuje se pri svakoj promeni), tj. završen.
Ovo omogućava da sat signalizira događaj određeno vreme nakon završetka zadnjeg taska i
time garantuje da neće biti naknadnih promena (ako neki task kasni sa izvršenjem). Na
listingu 25 prikazana je ova implementacija.
40
Listing 25 Metoda sinhronizacije pomoću timer-a
Nedostatak ovog rešenja je što je neophodno setovati vreme tajmera na neku relativno veliku
vrednost (3 do 10 sekundi) što je vrlo nepraktično, pogotovo za male dubine. Za mala
vremena, desi se da task zakasni više od tog vremena, pa imamo istu situaciju kao i ranije.
Naredna implementacija je najbolja u smislu sinhronizacije rekurzivnih taskova. Ova
implementacija je uspešno rešila problem sinhronizacije. Suština je u tome da svaki task
poseduje internu listu taskova potomaka (taskove koje je on pokrenuo) i čeka da se oni završe
pre nego što se on sam završi.
Ovo omogućava da su taskovi koji su viši u hijerarhiji blokirani dok se svi njihovi potomci ne
završe. Ne postoji globalna (deljiva, zajednička) lista taskova koji su pokrenuti u sistemu.
Implementacija je prikazana na listingu 26.
Listing 26 Roditelj task čeka na izvršenje potomaka taskova
Glavnu ulogu pri sinhronizaciji opet ima metoda WaitAll (interna metoda TPL) kao i u
orginalnoj implementaciji. Jedina je razlika što ovde nema zajedničeke liste taskova te nema
ni problema koje ta lista izaziva (kao u orginalnoj implementaciji).
Nakon uspešnog rešavanja problema sinhronizacije, zaključak je da su performanse zapravo
pogoršane, te je kompletno rešenje odbačeno.
Na listingu 27 prikazan je primer implementacije uz korišćenje TPL-a za paralelizaciju petlji.
41
Listing 27 Implementacija sa korišćenjem paralelizma u TPL-a
TPL omogućava paralelno izvršenje FOR i FOREACH petlji.
Razlika između normalne implementacije i implementacije uz upotrebu TPL za ralelizaciju
petlji je velika, u korist TPL-a. Prosečno vreme za izračunavanje prvog poteza je oko 6
sekundi bez upotrebe TPLa, a oko 3.5 sekundi (za dubinu 6).
Pri ovoj implementaciji, nema problema sinhronizacije, jer se operacija obavlja za sve
elemente niza (potomke čvorova) paralelno. Vreme potrebno za izvršenje, idealno, jednako je
jednoj iteraciji (najdužoj). Nivo paralelizacije (broj elemenata koji se paralelno obrađuju)
inicijalno je jednak broju jezgara računara, ali može se promeniti.
Ovo rešenje je na kraju usvojeno kao konačno, ali je radi praktične provere implementirano i
rešenje koje koristi TPL za generisanje niti i upravljanje paralelnim izvršenjem procedura
(threadpool).
U slučaju korišćenje TPL-a za upravljanje taskovima ili nitima postoji i praktično ograničenje
vezano za rezervisanje hardverskih resursa računara (operativna memorija). Na slici 11.
prikazana je greška koja se dobija kada se prekorači broj dozvoljenih niti (prekoračen je broj
niti koje mogu biti kreirane u raspoloživoj memoriji). Naime, za svaku nit rezerviše se jedan
megabajt prostora u operativnoj memoriji računara.
Zbog postojanja velikog broja čvorova (samim tim velikim brojem metoda / taskova / niti)
veliki deo operativne memorije je zauzet. Operativni sistem u određenom trenutku ne
dozvoljava dalje kreiranje taskove.
42
Slika 11 Izgled greške pri velikom broju taskova / niti
Listing 28 i 29 prikazuju implementaciju ThreadPool-a.
Listing 28 Pomoćne klase u implementaciji ThreadPool-a
43
Listing 29 Implementacija ThreadPool-a
44
Klasa Worker objedinjuje funkcionalnosti vezane za upravljanje nitima u threadpool-u. Evant
JobDone signalizira threadpool-u da je ta nit završila posao koji joj je dodeljen (ukoliko
postoji još poslova u listi, može joj se dodeliti novi posao). Enumerator State opisuje status
koji može imati nit, Idle (slobodna) i Running (zauzeta, pokrenuta). Metoda DoWork daje
naredbu niti da uzme prvi slobodan posao iz threadpool-a i izvrši ga. Metoda Stop zaustavlja
nit (prekida trenutnu operaciju).
Klasa Job objedinjuje atribute koji opisuju posao (jedinicu izvršenja, jedan poziv nekoj
funkciji). Status jednog job-a (instance klase Job) opisan je enumeratorom State. Job može
imati dva statusa, InProgress (izvršava se) i Free (slobodan). Za izvršenje metode koja je
opisana Job-om vezana je još jedna metoda, opisana atributom CallBack, koja se poziva
nakon nakon osnovne metode dodeljene tom Job-u. Svrha druge metoda je da pozivaoca
obavesti o tome da je tražena funkcija izvršena. Izvršenje Job-a obavlja se pozivom njegove
metode Execute koja onda redom pozove metode ToDo i CallBack.
Klasa ThreadPool implementira funkcionalnosti vezane za sam threadpool. Suštinski način
funkcionisanja threadpool-a je sledeći. Kad se doda novi posao u threadpool, proverava se
ima li slobodnih niti, ako ima, prvoj slobodnoj niti se dodeljuje posao. Ako nema slobodnih
niti, posao se dodaje u red čekanja. Kada se oslobodi prva nit, dodeljuje joj se prvi job iz reda
čekanja. Broj niti koje će raditi u threadpoolu određuje se pozivom metode Intit kao paramtar
ThreadCount. Metoda Stop zaustavlja rad threadpool-a tako što zaustavlja sve niti. Završeni
posao se izbacuje iz liste čekanja.
I ova implementacija nije dala značajnih poboljšanja u performansama pa je kao najbolje
rešenje uzeta implementacija sa korišćenjem TPL-a za paralelizaciju petlji.
4.2. Implementacija igre „4 u nizu“
Implementacija igre „4 u nizu“ podeljena je na tri dela. Implementacija osnovne platforme,
implementacija specifičnih delova igre oslonjenih na platformu i na kraju, implementacija
korisničkog interfejsa. Implementacija osnovne platforme je objašenjena u prethodnom delu.
U ovom delu biće objašnjen način implementacije specifičnih delova igre koji se oslanjaju na
osnovnu platformu za logičke igre.
4.2.1. Tabla igre (implementacija ITable)
Tabla igre (table game) implementira abstraktnu klasu ITable iz TableGameBase platforme za
logičke igre. Klasa se zove 4inLineTable.
Generator poteza - Skup poteza koji su legalni u svakom trenutku za svakog igrača generiše
generator poteza. Generator legalnih poteza implementiran je kao metoda klase table igre
(4inLineTable), a koja implementira apstraktnu klasu ITable kojim je ova metoda zahtevana
(više o ovome u opisu implementacije interfejsa). Kad god se ta metoda pozove ona vraća niz
legalnih poteza koji su na raspolaganju igraču koji je pozvao metodu. Ime metode je
GetAvailableMoves i implementacija metode prikazana je na listingu 30.
U igri “4 u nizu” legalan je svaki potez koji se igra na slobodno polje pri čemu to polje mora
biti na dnu table ili neposredno iznad nekog zauzetog polja.
45
Princip funkcionisanja ove metode je sledeći: vraća se lista slobodnih polja u zadnjem redu
matrice polja (koja reprezentuje tablu igre) zajedno sa svim slobodnim poljima iz ostalih
redova, a ispod kojih se nalazi popunjeno polje. Implementacija metode je prikazana na
listingu 30.
Listing 30 Implementacija generatora poteza u igri “4 u nizu”
Detekcija kraja igre implementirana je kao metoda table igre koja se poziva pre svakog
poteza. Metoda funkcioniše tako što proverava dva parametra:
- Da li ima praznih mesta na tabli,
- Da li neki od igrača ima 4 vezane figure
Ukoliko nema praznih mesta (nerešeno) ili neko od igrača ima 4 vezane figure (pobeda), igra
ne može biti nastavljena (kraj igre). U tom trenutku, kreira se instanca klase
GameOverDetails koja nosi podatke o pobedniku i kraju igre. Implementacija klase
prikazana je na listingu 16. U implementaciji je korišćena bazična implementacija ove klase
iz platforme, tako da ovde neće biti posebno objašnjavana (već je objašnjena u delu o
univerzalnoj platformi).
Detekcija kraja igre vrši se analizom cele tabele, liniju po liniju, kako bi se utvrdilo da li su
zadovoljeni uslovi za prekid igre.
46
Metoda ToString ima praktičnu ulogu da na lak način vizuelizuje matricu tabele. Metoda
Clone ima ulogu da napravi identičnu kopiju tabele. Atribut HashCode vraća heš kod tabele
(radi lakog upisa u transpozicionu tabelu).
4.2.2. Logika igre (implementacija ITableGame)
Ova klasa ima zadatak da upravlja smenom igrača, implementira pravila igre itd. Za potrebe
igre “4 u nizu” implementiran je interfejs ITableGame u obliku klase 4inLineTableGame
koja je prikazana na listingu 31.
Listing 31 Implementacija ITableGame interfejsa za igru “4 u nizu”
Značenje svakog pojedinačnog atributa objašenjeno je u delu koji opisuje ITableGame
interfejs. Što se same implementacije tiče, smena igrača (implementirana u metodi
NextPlayer) je naizmenična ( s obzirom na to da je ovo igra za dva igrača, lista igrača sadrži
dve instance objekta IPlayer – bilo kojom od implementacija tog interfejsa) između dva
igrača u listi. Pri dodavanju metode za obradu događaja kad je potez odabran, ta metoda
prosleđuje se svakom od AI igrača u listi.
47
4.2.3. Transpoziciona tabela (implementacija ITransTable)
Transpoziciona tabela implementirana je kao niz. Klasa u kojoj je implementacija izvršena je
4inLineTransTable (listing 32).
Listing 32 Implementacija transpozicione tabele za potrebe igre “4 u nizu”
Pristup transpozicionoj tabeli wrši se pomoću Linq izraza po ključu koji predstavlja heš
vrednost tabele igre. Ovaj pristup nije najoptimalniji.
48
Transpoziciona tabela trebalo bi biti implementirana kao heš tabela i tako obezbediti brz
direktan pristup ulazima u tabeli. Međutim, pristup sa korišćenjem Linq izraza i
neograničenog niza ima upravo tu prednost što ima neograničen broj ulaza za razliku od heš
tabele. Najbolje bi bilo implementirati kompromisno rešenje koje bi imalo direktan pristup,
jednostavnu heš funkciju i neograničenu heš tabelu.
4.2.4. Evaluatori (implementacija IEvaluation)
U implementaciji igre “4 u nizu” realizovane su tri metode evaluacije.
Prva je osnovna metoda evaluacije. U njoj se u obzir uzimaju samo polja zauzeta od igrača za
koga se evaluacija radi. Ukoliko se u čvoru (zapravo u tabeli koju taj čvor prectavlja) nađe 4
polja u nizu zauzeta od strane igrača (pobeda), to se evaluira kao +4. Ukoliko se nađu 4 polja
u nizu zauzeta od strane protivnika (poraz), to se evaluira kao -4. Sve ostalo evaluira se kao 0.
Ova metoda kasnije je izmenjena pa se ostali potezi evaluiraju kao maksimum svojih figurica
u nizu u bilo kom pravcu. Maksimum i minimum su ostali +4 i -4, ali se pored vrednosti 0
mogu javiti i 1,2,3 i -1,-2 i -3. Na ovaj način postignuto je da ova funkcija evaluacije
implementira “gramzivi algoritam”, jer teži da što više svojih figurica spoji u nizu.
Druga metoda evaluacije nazvana je “Osnovna proširena”. Ona poseduje sve što i osnovna
metoda sa dodatkom analize praznih polja na tabli. Naime, ova metoda ocenjuje i
“potencijal” nekog poteza, odnosno mogućnost da on bude deo neke još neodigrane
kombinacije.
Poslednja je “Test” metoda koja poseduje sve što i prethodne dve sa dodatkom analize
protivničkih pozicija u kontekstu trenutnog poteza, odnosno da li je i koliko protivnikovih
kombinacija sprečeno tim potezom.
Vezano za MinMax algoritam i evaluaciju treba reći da prvi potez (ko igra prvi) utiče na
krajnji ishod igre. U tabeli 4 prikazani su rezultati testova uticaja prvog poteza.
Prvi igra Evaluaciona metoda
Plavi Crveni
Pobeda
Crveni Osnovna Osnovna Remi
Crveni Proširena Osnovna Crveni
Crveni Test Osnovna Remi
Crveni Proširena Proširena Crveni
Crveni Test Proširena Crveni
Crveni Test Test Crveni
Plavi Osnovna Osnovna Remi
Plavi Proširena Proširena Plavi
Plavi Test Test Plavi
Tabela 4 Uticaj prednosti prvog poteza na krajnji ishod
Iz tabele se može zaključiti da prednost prvog poteza nadmašuje prednost u heuristici. Kao
što se iz tabele vidi, igrač koji igra drugi nikad ne uspe da pobedi uprkos prednosti u
evaluacionim funkcijama. Što se ostalih parametara tiče, oni su identični. Oba igrača koristila
49
su TPL, Adaptivno produbljivanje, Alfa-Beta, Evaluacionu i Transpozicionu tabelu. Jedino
što se menjalo tokom testova jeste evaluacija i ko igra prvi.
Takođe treba napomenuti da su rezultati iz tabele uzeti iz više ponovljenih testiranja
(zahvaljujući paralelizmu, program poseduje izvestan stepen mutacija, pa nema garancija da
će redosled poteza uvek biti isti – misli se na poteze iste vrednosti).
Logičkim upoređivanjem implementiranih evaluacionih metoda može se reći da su one u
osnovi iste, jer koriste i osnovnu – gramzivu metodu kao svoju suštinu)ali da metode
“Proširena” i “Test” imaju blaga poboljšanja zbog uzimanja više parametara u obzir pri
ocenjivanju.
4.3. Implementacija korisničkog interfejsa igre
4.3.1. Konfiguracioni prozor
Prvi ekran u aplikaciji jeste konfiguracioni prozor (slika 12).
Slika 12 Konfiguracioni prozor
Ovaj prozor ima svrhu da konfiguriše igru. Prvo se može podesiti tip i redosled igrača. Iz
padajućih listi na vrhu prozora može se izabrati čovek ili ai za tip oba igrača. Zatim se može
50
za oba igrača odabrati evaluaciona funkcija (može se odabrati za svakog AI igrača). Zatim se
može odabrati dubina stabla traženja i eventualno vremensko ograničenje u traženju.
Vremensko ograničenje je dostupno samo ako se izabere “Inkrementalno povećanje dubine”.
Zatim slede heuristički dodaci koje AI može koristiti pri pretrazi stabla traženja. Zadnja
opcija koja može biti odabrana je TPL i ona nije heuristički dodatak već dozvoljava upotrebu
TPL-a pri procesiranju (paralelizaciju).
Konfiguracioni prozor smešten je u NewGame klasi. Listing 33 prikazuje način konfiguracije
igrača.
Listing 33 Konfiguracija AI igrača za igru
Kao što se sa listinga može videti, svi parametri se sa grafičkog interfejsa prenose preko
atributa klase IAIPlayer. Pri inicijalizaciji atributa koristi se naredba uslovne dodele radi
preglednosti. Time je svaki atribut inicijalizovan jednom naredbom (i mahom u jednom redu).
Za svakog od AI igrača potrebno je uraditi isto (ista sekvenca naredbi).
4.3.2. Situacije
Ukoliko se želi testirati neka spcifična situacija (kako se program ponaša pod određenim
uslovima), ili se jednostavno ne želi početi od prazne tabele, klikom na dugme “Situacija” na
prozoru za konfiguraciju, otavara se novi prozor koji to omogućava. Taj prozor je prikazan na
slici 13.
Klikom na prazna polja na prozoru menja se status polja (crveni, plavi, prazni). Svaki klik
menja status u navedenom redosledu – prvi klik crveno, drugi klik plavo, treći klik prazno.
Klikom na dugme “Start” otvara se glavni prozor igre (tabla igre). Isto se dešava i u slučaju
klika na dugme “Start” sa konfiguracionog prozora.
Ovaj dodatak je idealan za testiranje evaluacionih funkcija i karakterističnih situacija.
51
Slika 13 Konfiguracija početnog stanja u partiji
Na listingu 34 prikazan je princip startovanja igre sa ovog prozora (prikazan je način
postavljanja početnog stanja tabele).
Kao što se vidi sa listinga, najpre se inicijalizuje matrica igre (4inLineTable). Sva polja se
postavljaju na vrednost “prazno” (empty).
Zatim sledi deo koji sa korisničkog interfejsa proverava stanje svih polja i inicijalizuje tabelu
igre na osnovu slike koja je učitana u polja na korisničkom interfejsu (plava, crvena, prazno).
Taj deo je zbog svoje dužine na listingu prikazan skraćeno (označen sa “Table settings”).
Nakon toga, inicijalizuje se statička instanca forme za igre (instanca je statička, jer se igra
može pokrenuti sa dva mesta, sa forme za podešavanja i forme za situacije, a koristi se ista
forma – na ovaj način odakle god da se igra startuje, koristi se ista instanca).
Posle inicijalizacije forme za igru, ubacuju se figurice koje je korisnik definisao (na
pozicijama koje je korisnik definisao) na formi za situacije. Pri ovome se koristi metoda
InsertPownAtPosition, koja je ugrađena u kontroli 4inLine (instanca ove kontrole nalazi se
na formi za igru).
52
Listing 34 Startovanja igre sa početnim stanjem
4.3.3. Glavni prozor
Glavni prozor igre prikazan je na slici 14. Potezi se povlače naizmenično između dva igrača,
počevši od onoga koji je na konfiguracionom prozoru odabran da igra prvi. Klikom na dugme
“Konzola” otvara se dodatak u donjem delu prozora koji u realnom vremenu, odmah nakon
povučenog poteza, prikazuje podatkke o tom potezu, i to:
- Boju igrača – prvi parametar (može biti Red i Blue),
- koordinate poteza – u kockastim zagradama, koordinate poteza na tabli za igru,
- vrednost – numerička vrednost koju mu je dodelio evaluator (označen sa Val),
- dubinu – dubina stabla na kome je potez odabran (označen sa D),
- broj evaluiranih čvorova – broj evaluiranih čvorova stabla pri traženju (označen sa
TN),
- vreme – vreme koje je bilo potrebno da se potez odabere (označen sa T),
53
- broj pogodaka u transpozicionu – broj pogodaka u transpozicionu tabelu (označen sa
TTg),
- broj promašaja u transpozicionu – broj promašaja u transpozicionu tabelu (označen
sa TTm).
Slika 14 Glavni prozor igre
Potezi u igri se povlače klikom bilo gde na prozoru kada se figurica pozicionira na željeno
mesto. Pomeranje figurice vrši se pomeranjem miša. Najpre se figurica pozicionira po X osi,
pomeranjem miša, a zatim se nakon klika miša figurica sama spušta do prvog slobodnog
mesta.
54
Listing 35 prikazuje konstruktor glavnog prozora igre. Kao parametri konstruktora prosleđuje
se objekat ITableGame zatim referenca na Log formu i na kraju eventualno tabela igre. Tabla
igre se prosleđuje samo u slučaju da igra počinje sa forme “Situacija”.
Listing 35 Konstruktor glavnog prozora
U konstrukoru se definiše funkcija za dodavanje poteza u log prozir. S obzirom na to da se
potezi biraju asinhrono – nezavisno od korisničkog interfejsa, neophodna je specifična
tehnika za prenos rezultata tog događaja na korisnički interfejs.
Naime, kako bi grafički korisnički interfejs ostao upotrebljiv u toku procesa odabira poteza
od strane AI (s obzirom na to da taj proces dugo traje i upotrebljava značajne resurse
računara) neophodno je da se proces traženja poteza pokrene u zasebnoj niti, različitoj od one
na kojoj radi korisnički interfejs. Konkretan princip pokretanja traženja na zasebnoj niti biće
objašnjen kasnije.
Međutim, i ako ova tehnika omogućava da korisnički interfejs ostane potpuno neblokiran u
toku traženja poteza, ona ima i jedan dodatni zahtev. Rezultati obrade koji se dobiju u toj
odvojenoj niti (u ovom slučaju potez koji je pronađen) ne mogu biti direktno preneti na
interfejs već se mora pozvati specijalna metoda koja će ažurirati korisnički interfejs. To je
metoda BeginInvoke koju ima svaka grafička kontrola na window formama.
Kao što se iz listinga vidi poziv ove metode je uslovan, zavisi od atributa InvokeRequired
koju postavlja sama forma. Naime, ukoliko forma još uvek nije prikazana, nema potrebe za
pozivom metode BeginInvoke, u suprotnom, neophodno je. Zavisno od atributa
InvokeRequired, metoda DrawTree poziva se uz pomoć BeginInvoke metode ili bez nje.
55
Poslednja naredba iz listinga dodaje 4inLine kontrolu na formu. Celokupna logika igre se
nalazi u ovoj kontroli.
Listing 36 Način dodavanja reda u log
Na listingu 36 prikazan je način logovanja odabranog poteza. Potez se loguje na dva načina.
Loguju se generalni podaci o potezu u tekstualno polje na samom glavnom prozoru kao i na
log prozoru, gde se pored ovih generalnih podataka o potezu, loguje i celokupno stablo
traženja.
Na listingu 37 prikazan je konstruktor drugog dela glavnog prozora – kontrola igre, 4inLine.
Kao parametri konstruktora prosleđuju se instance ITableGame i ITable.
U konstruktoru se najpre vrši inicijalizacija tabele igre, a zatim se dodaju metode za
upravljanje odabranim potezom (kada AI signalizira da je potez odabran).
Po kreiranju igre, na tablu se ubacuje prva figurica. Kako bi se figurica ubacila, neophodno je
da se kreira kontrolni poenter (pokazivač) na ovu formu od strane operativnog sistema. Za to
je iskorišćen događaj HandleCreated koji signalizira sama forma.
56
Listing 37 Konstruktor klase 4inLine – kontrola igre
Metoda InsertPownAtPosition ubacuje jednu figuricu na koordinate koje se prosleđuju kao
parametri funkcije pri pozivu. Boja figurice koju treba ubaciti takođe se prosleđuje kao
parametar. Metoda kreira novu instancu klase PictureBox koja se nalazi u skupu standardnih
windows form kontrola, podešava mu visinu i širina na visinu i širinu figurice. Nakon toga se
toj kontroli dodeljuje sličica (crvena ili plava). Nakon svega ovoga, kontrola se dodaje na
formu. Sama metoda je prikazana na listingu 38.
57
Listing 38 Metoda za ubacivanje figurice na određenu poziciju bez animacije
Na listingu 39 prikazana je metoda InsertPown_Job koja se razlikuje od metode
InsertPownAtPosition samo po tome što se ne prosleđuju obe koordinate poteza i što se sama
figurica dodaje na tablu igre animirano.
Pri ubacivanju nove figurice se najpre proveri da li igra može biti nastavljena (poziv metodi
IsGameOver klase ITable).
Nakon ovoga, sledi deo koji je identičan kao u prethodnoj metodi.
Nakon ubacivanja figurice na tablu, sledi deo koji inicijalizuje proces traženja, u slučaju da je
trenutni igrač AI. Inicijalizacija procesa traženja vrši se u zasebnoj niti (kako ne bi blokirao
korisnički interfejs).
Najpre se kreira nova nit i toj niti se dodeli metoda koju će ta nit izvršavati, a to je metoda
Play. Nakon toga nit se pokreće.
58
Listing 39 Metoda za ubacivanje figurice na tablu i pokreće AI
59
Listing 40 Metode koje pozicioniraju figuricu po X osi kada AI odabere potez
Na listingu 40 prikazane su metode koje inicijalizuju animirano ubacivanje figurice na tablu
igre. Metoda DoMove_Job pozicionira figuricu po X osi na lokaciju koju odabere AI igrač, a
zatim inicijalizuje sat (tajmer) koji vrši pomeranje figurice po Y osi do željene pozicije.
Kontrolna promenljiva isDragable omogućava/zabranjuje pomeranje trenutne figurice po X
osi pomeranjem kursora miša (ovo se koristi da spreči korisnika-čoveka da pomera figuricu
dok AI igra). Kontrolna promenljiva isMoving signalizira da li se figurica već pomera.
Promenljiva dA predstavlja interval sata (tajmera) odnosno frekvenciju pozivanja metode
timer1_Tick (prikazana na listingu 41) u milisekundama. Atribut Enabled predstavlja
kontrolnu promenljivu sata, koja ga aktivira/deaktivira.
60
Listing 41 Metoda sata (tajmera) koja animira kretanje figurice pri ubacivanju
Metoda timer1_Tick vrši pomeranje figurice. Svaki poziv ove metode pomera figuricu
moving za određeni broj piksela po Y osi. Kada se uslov dostigne (figurica se postavi na prvo
slobodno mesto) promenljive se resetuju.
Promenljiva current čuva referencu na trenutnu figuricu, onu koja se pomera po horizontali
sa pomeranjem miša.
Moving je promenljiva koja čuva referencu na onu figuricu koja se spušta po Y osi. Po
završetku spuštanja figure, na tablu se ubacuje nova figurica.
Na listingu 42 prikazana je metoda MarkWinner.
61
Listing 42 Metoda koja markira pobednički niz na tabli
Ova metoda markira pobednički niz kada partija bude završena. Markiranje se vrši polje po
polje, za sve figurice u nizu.
4.3.4. Log
Klikom na dugme “Stablo” na glavnom prozoru prikazuje se kontrolni prozor koji loguje
kontrolne podatke o svakom potezu kao i kompletno stablo traženja. Izgled prozora prikazan
je na slici 15.
62
Slika 15 Izgled kontrolnog prozora koji loguje poteze oba igrača
Na slici 16 prikazan je izgled stabla onako kako se ono predstavlja na kontrolnom prozoru. U
korenu stabla je odabrani potez. Takođe, tu su i kontrolni podaci koji se štampaju u konzoli.
Iz korena stabla dalje se grana kompletno stablo.
Sam prozor podeljen je na dva dela, po jedan deo za svakog od igrača. Na levoj strani je uvek
igrač koji igra prvi, a na desnoj onaj koji igra drugi. Nakon svakog odigranog poteza, potez se
loguje dodavanjem čvora na odgovarajuću listu (levu ili desnu, zavisno od igrača).
63
Slika 16 Grafički prikaz stabla traženja i odabranog poteza
Pregled celog stabla je izuzetno pogodan pri debagiranju i testiranju aplikacije. Može se
propratiti celo stablo traženja kao i MinMax algoritam (vrednost svakog čvora). Za grafičko
predstavljanje stabla iskorišćena je standardna windows forms kontrola TreeView koja
omogućava grafičku reprezentaciju rekurzivnih struktura.
U kontrolu se pozivom metode Add dodaju objekti tipa TreeNode, a koji i sami mogu imati
svoje TreeNode-ove kao potomke. Ova struktura je identična TreeNode strukturi iz aplikacije
što se uređenja tiče i omogućavaju lako formiranje stabla.
64
5.Zaključak
Ovaj projekat trebalo je da pokaže način upotrebe algoritama veštačke inteligencije u
realizaciji logičke igre “4 u nizu”.
Mogućnosti za proširenje (nadogradnju) su velike. Najviše prostora za poboljšanje
ima u implementaciji samog stabla traženja. Poboljšanje mehanizma za generisanje stabla
može značajno povećati performanse aplikacije.
Takođe, prostora za poboljšanje ima i u realizaciji paralelizma u aplikaciji, odnosno
generički mehanizam koji je direktno preuzet iz Microsoft .net frameworka 4.0 nije
najoptimalnije moguće rešenje. Bolje performanse aplikacije mogle bi se postići uz pažljivu
implementaciju paralelizma na nižem nivou kodiranja.
Evaluacione funkcije takođe mogu biti poboljšane i time poboljšati rezultate pretrage.
Međutim, možda najznačajnija stvar koja bi povećala kvalitet programa (pa i performanse)
jeste pondering, odnosno korišćenje protivnikovog vremena za razmišljanje u svoju korist.
Trenutna implementacija aplikacije čeka da protivnik povuče potez, pa tek onda pokreće
mehanizam traženja što je prilično veliko gubljenje vremena. U realnim uslovima, kada
čovek igra logičku igru, on razmišlja konstantno tokom celog toka igre, bez obzira na to ko je
na potezu, a kada protivnik povuče potez, samo se koriguje odluka, ukoliko ima potrebe.
Tako nešto moguće je implementirati i u AI sistemu, korišćenjem transpozicionih tabela.
Poundering može lepo da se iskoristi kod iznuđenih poteza. Poundering zapravo predstavlja
jedan nivo više u stablu traženja, ali kod iznuđenih poteza to nema, jer se zna da će protivnik
da odigra tu, te nema potrebe za zaustavljanjem pretrage.
Nešto što smatram kvalitetom ovog sistema jeste modularnost. S obzirom na to da su
bazne klase i interfejsi generički pisani sa ciljem da budu primenljivi na što veći opseg igara i
varijacija, veoma lako se može postojeća implementacija proširiti da podržava, npr. tri igrača
umesto dva ili da podržava tabelu 7x7 umesto 6x7. Takođe, moguće je implementirati i
potpuno drugačije igre uz potpuno očuvanje baznih klasa i interfejsa, a uz potrebu da se
promeni samo logika igre, odnosno implementacija apstraktnih klasa, interfejsa, itd.
Jedna od ideja pri razvoju ove aplikacije bila je da se razvije i platforma koja će biti
sposobna da podrži ceo spektar tabelarnih igara i mislim da je taj cilj ostvaren.
Sama realizacija logičke igre “4 u nizu” postiže solidne rezultate pri testiranju tako da
je cilj i u tom pogledu ostvaren.
Upotrebljeni su svi algoritmi i tehnike veštačke inteligencije koje je bilo moguće
realizovati u ograničenom vremenskom roku koje je bilo na raspolaganju za ovaj rad.
Primenjeni algoritmi su detaljno opisani, kao i svrha njihove primene. Za svaki algoritam koji
je korišćen u aplikaciji prikazana je i realizacija u kodu.
65
6.Literatura
1. Fudenberg, D. and Tirole, J. Game Theory. MIT Press, Boston, MA, 1995.
2. Adelson-Velskiy, G.M, Arlazarov, V.L. and Donskoy, M.V. Algorithms for Games.
Springer-Verlag, New York, NY. ISBN 3-540-96629-3, 1988.
3. Vladan Vučković, "Prilog teoriji i praksi naprednih šahovskih algoritama", doktorska
disertacija, Elektronski fakultet u Nišu, 2006.
4. Petar Rajković, Владан Вучковић, “Основни елементи хеуристичке евалуационе
функције”, Зборник радова са 52. Конференције ЕТРАН-а, CD ROM Proceedings,
Секција Вештачка интелигенција, рад VI2.4, Палић, Србија, 8-12. јуни 2008, (ISBN
978-86-80509-63-1) (M63)
5. Владан Вучковић, “Специјални елементи евалуационе функције”, Зборник радова
са 53. Конференције ЕТРАН-а, CD ROM Proceedings, Секција Вештачка
интелигенција, рад VI1.3, Vrnjačka Banja, Србија, 15 – 18. juna 2009. (ISBN 978-86-
80509-64-8) (M63)
66
7.Lista slika
Slika 1 Izgled table za igranje u igri “4 u nizu”. Strana 7.
Slika 2 Struktura podataka – Stablo. Strana 9.
Slika 3 Stablo igre. Strana 10.
Slika 4 Algoritam MinMax – igra “Iks-Oks”. Strana 11.
Slika 5 Pogrešan potez zbog nesavršenosti u funkciji evaluacije. Strana 12.
Slika 6 Primer Alfa-Beta odsecanja. Strana 13.
Slika 7 Alfa-Beta odsecanje – objašnjenje. Strana 14.
Slika 8 Vrednosti polja u evaluacionoj tabeli za igru „4 u nizu“. Strana 15.
Slika 9 Primer situacije u kojima primena transpozicione tabele donosi korist. Strana 15.
Slika 10 Uporedni grafički prikaz zavisnosti vremena izvršenja od dubine. Strana 36.
Slika 11 Izgled greške pri velikom broju taskova / niti. Strana 41.
Slika 12 Konfiguracioni prozor. Strana 48.
Slika 13 Konfiguracija početnog stanja u partiji. Strana 50.
Slika 14 Glavni prozor igre. Strana 52.
Slika 15 Izgled kontrolnog prozora koji loguje poteze oba igrača. Strana 61.
Slika 16 Grafički prikaz stabla traženja i odabranog poteza. Strana 62.
67
8.Lista tabela
Tabela 1 Matrica ispravnosti za igru „4 u nizu“. Strana 6.
Tabela 2 Uticaj paralelizma na vreme izvršenja. Strana 35.
Tabela 3 PC konfiguracija na kojoj je izvršeno testiranje. Strana 36.
Tabela 4 Uticaj prednosti prvog poteza na krajnji ishod. Strana 47.

More Related Content

Featured

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
Marius Sescu
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
Expeed Software
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
Pixeldarts
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
ThinkNow
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
marketingartwork
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
Skeleton Technologies
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
Neil Kimberley
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
contently
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
Albert Qian
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
Kurio // The Social Media Age(ncy)
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
Search Engine Journal
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
SpeakerHub
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
Tessa Mero
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Lily Ray
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
Rajiv Jayarajah, MAppComm, ACC
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
Christy Abraham Joy
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
Vit Horky
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
MindGenius
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
RachelPearson36
 

Featured (20)

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
 

Diplomski rad final - Sasa Stojkovic

  • 1. Univerzitet u Nišu Elektronski fakultet Katedra za računarstvo DIPLOMSKI RAD TEORIJSKE I PRAKTIČNE OSNOVE REALIZACIJE LOGIČKE IGRE „4-U-NIZU“ NA PERSONALNIM RAČUNARIMA Zadatak: Proučiti i opisati teorijske i praktične metode realizacije logičke igre „4-u-nizu“. U teorijskom delu rada opisati osnovne algoritme (MinMax, Alfa-Beta) koji će biti iskorišćeni za implementaciju. U praktičnom delu rada realizovati kompletnu aplikaciju. Komisija: Student: Predsednik komisije Saša Stojković, 11332 1.____________________ Datum prijave rada Član komisije ____________________ 2.____________________ Datum predaje rada Član komisije ____________________ 3.____________________ Datum odbrane rada ____________________
  • 2. 2
  • 3. 3 Sadržaj: 1. Uvod........................................................................................................4 2. Teorija igara............................................................................................5 2.1. Osnovni pojmovi teorije igara ............................................................5 2.2. Logička igra „4 u nizu“ .....................................................................7 3. Osnovni pojmovi veštačke inteligencije .....................................................9 4. Implementacija igre “4 u nizu”...............................................................18 4.1. Univerzalna platforma za logičke igre...............................................18 4.1.1. Book..........................................................................................18 4.1.2. Evaluation .................................................................................19 4.1.3. Players ......................................................................................22 4.1.4. Table.........................................................................................31 4.1.5. Tree...........................................................................................33 4.1.6. Table game................................................................................34 4.1.7. Paralelizacija.............................................................................36 4.1.8. Problem sinhronizacije rekurentnih taskova ................................37 4.2. Implementacija igre „4 u nizu“ ........................................................44 4.2.1. Tabla igre (implementacija ITable).............................................44 4.2.2. Logika igre (implementacija ITableGame) ..................................46 4.2.3. Transpoziciona tabela (implementacija ITransTable) ..................47 4.2.4. Evaluatori (implementacija IEvaluation).....................................48 4.3. Implementacija korisničkog interfejsa igre........................................49 4.3.1. Konfiguracioni prozor ................................................................49 4.3.2. Situacije.....................................................................................50 4.3.3. Glavni prozor.............................................................................52 4.3.4. Log............................................................................................61 5. Zaključak...............................................................................................64 6. Literatura..............................................................................................65 7. Lista slika..............................................................................................66 8. Lista tabela............................................................................................67
  • 4. 4 1.Uvod Današnje aplikacije sve više zahtevaju upotrebu specijalizovanih algoritama koji se inače tradicionalno primenjuju u oblasti veštačke inteligencije u cilju rešenja nekih praktičnih problema. Sa razvojem računarskog hardvera rastu i zahtevi vezani za mogućnosti softvera. Jedan od novijih problema koji se javlja jeste i problem automatske klasifikacije podataka ili profilisano traženje (korisnicima više nije dovoljno prosto poređenje teksta već se zahteva i semantička analiza traženog uzorka i rezultata traženja), itd. Sposobnost rešavanja ovih i sličnih problema vezuje se za čoveka i njegovu inteligenciju, odnosno sposobnost da rešava složene zadatke. Međutim, u eri savremenih računara koji su sposobni da obavljaju ogroman broj operacija u sekundi, korisnici očekuju da ne moraju sami rešavati te zadatke, imajući u vidu da su ti zadaci za njih same trivijalni. Rešenje za ovakve probleme nudi nam veštačka inteligencija. Nekada je veštačka inteligencija imala za cilj rešavanje uskog kruga problema, međutim, vremenom se rešenja koja su u toj oblasti pronađena sve više koriste u projektovanju aplikacija koje se svakodnevno koriste. Neke od njih koristimo svakodnevno, a ni ne primećujemo da se iza njih nalazi „veštačka inteligencija“, npr. svakodnevno koristimo web pretraživače, a najveći web pretraživač Google već neko vreme koristi tehnike veštačke inteligencije kako bi efikasnije obavljao proces pretraživanja i sortiranja rezultata korisnika. Takođe, mnogi rečnici i alati za prevođenje sa različitih jezika koriste tehnike veštačke inteligencije kako bi poboljšali kvalitet svoje obrade. Razlog autora da se bavi ovom temom ogleda se u samoj želji da se što bolje upozna sa tehnikama veštačke inteligencije radi njihove primene u praktičnim problemima. Tema diplomskog rada je implementacija igre “4 u nizu” i predstavljanje algoritama veštačke inteligencije koje je neophodno koristiti u realizaciji. U radu će biti opisani i praktično realizovni neki od najpoznatijih algoritama iz oblasti algoritma traženja, jedne od oblasti veštačke inteligencije. Takođe, u teorijskom delu biće objašnjeni osnovni pojmovi iz oblasti teorije igara koji će biti korišćeni u ovom radu. U praktičnom delu rada biće realizovana kompletna aplikacija u kojoj će biti primenjeni svi algoritmi i tehnike koji budu opisani u teorijskom delu rada. Rad će biti realizovan korišćenjem razvojnog okruženja „Microsoft Visual Studio 2010“, a kao osnova za razvoj biće iskorišćen „Microsoft .NET Framework 4.0“. Aplikacija je realizovana u programskom jeziku C#.
  • 5. 5 2.Teorija igara Teorija igara je naučna oblast koja ima svoje korene još u 17. veku. Ova teorija je u osnovi povezana sa matematičkom teorijom verovatnoće, ali se kasnije razvila u potpuno samostalnu teoriju koja obuhvata tretiranje ne samo logičkih igara već i brojnih problema koji su u vezi sa ekonomskim, vojnim i sociološkim fenomenima [1]. 2.1. Osnovni pojmovi teorije igara Prema interesima igrača koji učestvuju u igri postoje nekoliko klasa igara koje se mogu izdvojiti [1]: - Kooperativne igre - (cooperative games) je klasa igara kod kojih igrači imaju zajednički interes. - Nekooperativne igre (non-cooporatve games) - U mnogim igrama su interesi igrača u potpunosti suprotni. „4 u nizu“ i šah su dobar primer za takvu situaciju. Igre tog tipa se u teoriji igara nazivaju nekoperativne igre sa nultim sumiranjem (zero-sum non- cooperative games). Pojam nultog sumiranja objašnjava vrednovanje (evaluaciju) svakog poteza za oba igrača, odnosno pošto su im interesi suprotni, isti potez za jednog igrača ima pozitivnu vrednost, a za drugog negativnu te je njihov zbir nula. - Igre sa kombinovanim motivima (mixed-motive game) – Ukoliko igrači imaju elemente i kooperativnosti i nekooperativnosti istovremeno, igre se mogu svrstati u ovu klasu. Primer bi mogao biti jedan fudbalski tim (svaki igrač želi da postigne go- individualni motiv, ali je glavni motiv pobeda tima). Igre se takođe mogu klasifikovati [1]: - Igre veštine (games of skill) - U ovu grupu spadaju igre koje igra jedan igrač koji ima potpunu kontrolu nad svim mogućim ishodima. - Igre šansi (games of chance) – U ovu grupu spadaju igre koje jedan igrač igra protiv prirode. Definicija prirode kao drugog igrača omogućava nešto viši nivo tretiranja ovih igara u odnosu na igru veštine. Osnovna karakteristika je da igrač ne može da konroliše sve moguće ishode u igri, već da može da prilikom građenja strategije ima u vidu samo verovatnoće nekih ishoda. U literaturi se ove igre nazivaju takođe i igrom rizika. Unutar ove grupe moguće je podeliti tipove igara na još dve podgrupe: o ako su poznate verovatnoće pojedinih mogućih ishoda u okviru prirodnih zakona (involving risk games) o ako su mogući ishodi i verovatnoće u potpunosti nepoznati. U prvom slučaju moguće je izgraditi prilaz u biranju mogućih poteza na osnovu opadajućeg predviđenog niza verovatnoća, dok je u drugom slučaju ukupni ishod i njegove verovatnoće apsolutno nepoznat.
  • 6. 6 - Igre strategije (games of strategy) – Uključuju dva ili više igrača, bez uključivanja prirode, od kojih svaki ima delimičnu kontrolu nad mogućim ishodima. Pošto svaki igrač poseduje autonomnost u odlučivanju, verovatnoće ishoda ili donošenja odluka drugih igrača su potpuno nepoznate svakom igraču. Ova grupa igara se takođe deli na dve podgrupe – igre sa dva ili više igrača. Unutar svake podgrupe postoji još tri podgrupe igara u zavisnosti od toga u kakvom je odnosu funkcija isplativosti jednog igrača u odnosu na ostale: Ako su interesi igrača u potpunosti koincidentni, ako su u potpunosti suprotni ili ako su delimično koincidentni, a delimično suprotni. o Igre strategije dva ili više igrača u kojima su interesi igrača koincidentni se nazivaju kooperativne igre strategije. o Igre u kojima su interesi igrača u potpunosti suprotni se nazivaju igre strategije sa nultim sumiranjem (zero-sum games of strategy). o Igre koje nisu u potpunosti kooperativne ili suprotne se nazivaju igre strategije sa kombinovanim motivima (mixed-motive games of strategy). U nastavku će biti navedene neke osnovne definicije iz teorije igara sa akcentom na njihovu primenu u igri “4 u nizu” [1]. Definicija 1 - Igra je formalni opis strateške situacije. Definicija 2 - Igrač je entitet koji učestvuje u igri i donosi samostalne odluke. Definicija 3 - Funkcija isplativosti (pay-off function) koja je sinonim za evaluacionu funkciju predstavlja numerički opis značajnosti nekog ishoda za nekog od igrača. Definicija 4 - Igra sa nultim sumiranjem (zero-sum game) podrazumeva tip igre gde je suma svih ishoda za sve igrače nula. Kod igara u kojima su interesi igrača suprotni, kao što je to slučaj u igri „4 u nizu“, funkcije isplativosti imaju suprotan predznak. Ako neka pozicija koja je rezultat igre ima vrednost +E za crvenog, to istovremeno znači da ona ima vrednost -E za plavog. Definicija 5 - Igra sa potpunim informacijama (perfect information game) znači da u svakom momentu samo jedan igrač može da povuče potez. Svaki igrač poseduje sve inforamcije o svim mogućnostima koje može da odigra drugi igrač računajući i informacije o funkciji isplativosti. Definicija 6 - Ekstenzivna forma igre (extensive game form) je stablo koje predstavlja tok odigravanja igre. Stablo se generiše na osnovu naizmeničnog redosleda odigravanja poteza. U svakoj tački u stablu svaki igrač poseduje perfektnu informaciju (prema definiciji 5). Definicija 7 - Strategija je jedna od više mogućih akcija (poteza) nekog igrača. U ekstenzivnoj formi igre, strategija je kompletan plan izbora mogućnosti za svaku tačku (čvor) odlučivanja za svakog od igrača. Definicija 8 - Matrica isplativosti je analogija funkciji isplativosti. Vrednost isplativosti za svakog igrača je predstavljena odgovarajućom matricom umesto jedinstvenom numeričkom vrednošću. Definicija 9 - Racionalnost je osnovna pretpostavka u teoriji igara i podrazumeva da svaki igrač igra sa ciljem da izvrši maksimizaciju svoje funkcije isplativosti.
  • 7. 7 Definicija 10 - Konačna igra je tip igre koja svakom igraču dozvoljava samo konačan broj poteza i ograničenu mogućnost izbora u svakom potezu. Definicija 11 - Kombinaciona igra predstavlja igru za dva igrača sa potpunim informacijama i strogo definisanim pravilima po kojima se generišu potezi. Skup pozicija je definisan pravilima igre i konačan je. Terminalna pozicija se definiše kao ona pozicija u kojoj strana koja je na potezu nema više legalnih poteza na raspolaganju. Definicija 12 - Nepristrasnom igrom (impartial game) se smatra ona igra za dva igrača kod koje je skup poteza podudaran za bilo koju stranu koja je na potezu u istoj poziciji. Ako je taj skup poteza različit igra se smatra tipom partizan. Definicija 13 - Normalna definicija kraja igre podrazumeva da u terminalnoj poziciji igrač koji je na potezu dobija. U suprotnom igra je tipa misere. Definicija 14 - Igra je konačna ako se završava u končanom broju poteza. 2.2. Logička igra „4 u nizu“ Igra “4 u nizu” je logička igra za dva igrača. Prema podelama opisanim u poglavlju „Osnovni pojmovi teorije igara“ ova igra se može svrstati u Nekooperativne igre prema prvoj podeli, odnosno Nekooperativne igre strategije sa nultim sumiranjem po drugoj podeli. Takođe, važe i sledeće tvrdnje: - „4 u nizu“ je strateška igra u kojoj učestvuju dva igrača čiji se potezi smenjuju naizmenično. Igrači se označavaju pojmovima plavi i crveni. Podrazumeva se da igrači igraju racionalno (definicija 9). - „4 u nizu“ je igra sa perfektnim informacijama (definicija 5) i nultim sumiranjem (definicija 4). - „4 u nizu“ je kombinaciona igra (definicija 11) tipa partizan (definicija 12). Broj mogućih legalnih poteza u svakoj poziciji je konačan i može biti različit za svakog od igrača. - „4 u nizu“ ima tri moguće vrednosti funkcije isplativosti: pobedu crvenog, pobedu plavog i nerešen rezultat. - Partija se uvek završava u konačnom broju poteza (definicija 10) bez obzira na strategije igrača. - Funkcija isplativosti u „4 u nizu“ se može definisati matricom isplativosti: Crveni igrač Pobeda Nerešeno Poraz Plavi igrač Pobeda - - 1, -1 Nerešeno - 0,0 - Poraz -1, 1 - - Tabela 1 Matrica ispravnosti za igru „4 u nizu“
  • 8. 8 Imajući u vidu gore navedene definicije, na igru „4 u nizu“ može se primeniti osnovna minimaks teorema: Za svaku konačnu igru sa potpuno definisanim informacijama u kojoj učestvuju dva igrača i koja ima nultu sumu može se definisati optimalna strategija igre. Pod datim uslovima može se definisati sledeća jednakost [1]: 𝑀𝐴𝑋 𝑋 𝑀𝐼𝑁 𝑌 𝑋 𝑇 𝐴𝑌 = 𝑀𝐼𝑁 𝑌 𝑀𝐴𝑋 𝑋 𝑋 𝑇 𝐴𝑌 = 𝑣 Gde je: V - vrednost igre (evalucacija), A - matrica isplativosti (tabela 1), X,Y – matrica rešenja. Logički gledano, ova teorema definiše postupak nalaženja najboljeg nastavka za igrača A koji istovremeno predstavlja maksimalnu vrednost mogućih nastavaka koji su mu na raspolaganju. Igrač B, koji igra protiv igrača A nastoji da maksimizuje svoju funkciju isplativosti, odnosno da minimizuje funkciju isplativosti igrača A [1]. Nekoliko reči o samoj igri i pravilima. Igra se na tabli koja je podeljena u 42 polja (6 redova i 7 kolona). Igra je poteznog tipa (igrači se smenjuju naizmenično posle svakog odigranog poteza). U svakom potezu igrač koji igra ubacuje novu figuricu na tablu u jedno od 42 polja (pomeranje već ubačenih figura nije dozvoljeno). Polje na koje se figurica ubacuje mora biti slobodno (na njemu se ne nalazi figurica) i mora biti iznad nekog već zauzetog polja ili na dnu tabele (u prvom redu). Nakon postavljanja u slobodno polje, figurica se ne pomera do kraja partije. Cilj igre jeste dobiti najmanje 4 svoje figurice u nizu (izmedju njih se ne sme nalaziti nijedna protivnička figurica). Figurice mogu biti u nizu horizontalno, vertikalno i dijagonalno. Slika 1 Izgled table za igranje u igri “4 u nizu”
  • 9. 9 3.Osnovni pojmovi veštačke inteligencije Veštačka inteligencija kao pojam pripisuje se sistemima i računarskim programima sa sposobnostima realizovanja složenih zadataka, odnosno sposobnostima simulacije ljudskog razmišljanja. Kada govorimo o veštačkoj inteligenciji u oblasti računarskih igara govorimo o težnji da računarski program donosi odluke na način na koji bi to čovek uradio, odnosno o simulaciji težnje za pobedom u partiji. U okviru veštačke inteligencije kao nauke tokom vremena razvile su se razne grane, svaka izučavajući određeni problem ili određeni pravac istraživanja (neuronske mreže, expertni sistemi, logičko zaključivanje, mašinsko učenje, algoritmi pretrage, itd.). Nisu sve tehnike veštačke inteligencije primenljive na sve probleme niti su podjednako efikasne u rešavanju svih problema. U igrama kao što je “4 u nizu” primenjuju se algoritmi za rešavanje problema, odnosno algoritmi traženja. Kad se govori o pretraživanju, misli se na “pretraživanje” mogućih poteza (elementi skupa legalnih poteza) za svakog igrača. Legalni potez je svaki potez koji igrač može odigrati (poštujući pravila igre) kada je na redu da igra. Pojednostavljeno, ovo znači da algoritmi traženja izdvajaju-nalaze, najbolji potez u datoj situaciji uzimajući u obzir sve parametre igre. Kada kažemo najbolji potez, mislimo na potez koji pruža najviše šanse za pobedu. Da bi algoritam traženja bio u stanju da oceni koji je potez najbolji, neophodno je da izvrši ocenjivanje, tj. evaluaciju svakog poteza. Ovaj zadatak obavlja deo programa koji se naziva evaluator (ili evaluaciona funkcija) [4][5]. On ne mora biti odvojen od ostatka programa, ali će radi pojednostavljenja objašnjenja to biti pretpostavljeno u daljem tekstu. Evaluator ima ulogu da na što svrsishodniji način uporedivim vrednostima opiše svaki potez (čvor stabla igre – definicija 6 iz teorije igara). Ovo znači da vrednosti poteza koje je opisao evaluator moraju biti međusobno uporedive, kako bi se znalo koji je bolji, a koji gori. Kako bi “taktička” situacija u partiji mogla da bude sagledana u potpunosti, evaluator mora uzeti u obzir i eventualne poteze protivnika, odnosno, ne samo da mora da pronađe najbolji potez za trenutnog igrača, već mora pronaći i najbolji potez za njegovog suparnika kako bi mogao da donese ispravnu odluku i pravilno oceni (evaulira) potez. Neophodno je da algoritam traženja gleda unapred. Broj koraka unapred koji algoritam traženja uzima u obzir pri izvršenju naziva se dubina traženja. Ukoliko se zahteva samo traženje najboljeg poteza za trenutnog igrača, to je dubina 1. Ukoliko se zahteva i nalaženje najboljeg koraka protivnika nakon toga, to je dubina 2. Dubina traženja ograničena je samo brojem raspoloživih poteza za igrače (može se generisati sve dok se igra ne završi – pobedom jednog od igrača ili nerešenim rezultatom – što u slučaju igre “4 u nizu” znači da više nema praznih polja na table). Maksimalna dubina stabla za igru “4 u nizu” je jednaka broju polja, odnosno 42 nivoa.
  • 10. 10 Nivoi se mogu naizmenično smenjivati dok ne bude ispunjen neki od navedenih uslova za kraj igre. Naizmenično smenjivanje se vrši zato što igrači igraju naizmenično, svaki potez jednog igrača praćen je potezom drugog igrača. U praktičnim realizacijama algoritama za traženje, kao model partije koji algoritam pretražuje koristi se struktura podataka stablo. Slika 2 Struktura podataka – Stablo Stablo je nelinearna struktura podataka koja se sastoji od proizvoljnog broja čvorova. Svaki čvor može biti u relaciji sa proizvoljnim brojem drugih čvorova koji se nazivaju njegovim potomcima, a sam taj čvor može biti potomak nekog drugog čvora. Samo jedan čvor nema prethodnika (roditelja) i on se naziva koren stabla. Najniži u hijerarhiji stabla su listovi (nazivaju se još i terminalnim čvorovima) i oni nemaju potomke. Jedan čvor ne sme biti potomak više od jednog čvora (u suprotnom imamo strukturu podataka koja se zove graf). Terminalni nodovi (listovi) predstavljaju kraj igre, odnosno najveću dozvoljenu dubinu stabla (u slučaju da nemamo celo stablo). Horizont je dubina do koje je praktično moguće pretražiti stablo odlučivanja (stablo igre). Iz više praktičnih razloga nije moguće pretražiti celo stablo kada je ono veliko (zahtevaju se značajni resursi za obradu). Pošto se praktično pretražuje samo deo stabla do određene dubine (horizonta) moguće je doći do pogrešnog zaključka ukoliko je uticajni potez odmah iza horizonta. U tom slučaju, smatra se da je odluka pod uticajem efekta horizonta. Na slici 3 prikazano je stablo igre za deo partije igre „Iks Oks“. Kao što se na slici može videti, svaki potez predstavljen je jednim čvorom stabla. Iz tog čvora dalje se granaju potomci tog čvora – potezi koji logički slede taj potez. Na svakom nivou stabla nalaze se potezi iste „boje“, odnosno potezi istog igrača. Koren stabla je trenutno stanje partije. Na redu da igra je igrač „X“. On može odigrati na neke od tri raspoložive pozicije i to je na stablu predstavljeno sa tri potomka korenog čvora. Nakon toga, na redu da igra je igrač „Oks“, koji za svaki od mogućih poteza igrača „Iks“ ima svoje dve mogućnosti, jer gde god da „Iks“ odigra ostaju prazna dva polja na tabli s obzirom na to da nijedan od tih poteza ne vodi kraju igre. Na ovom nivou već postoje terminalni čvorovi, odnosno čvorovi koji se više ne granaju, jer označavaju potez u kome se igra završava (pobedom ili nerešenim rezultatom). Kao što se na slici vidi, „Oks“ ima dva poteza kojima završava partiju. Međutim, postoje i tri poteza koji vode daljem produžavanju igre. Objašnjeni princip koristi se tokom generisanja celog stabla. Ako je u korenu stabla prazna tabla, znači da je to početak partije. Stablo igre trebalo bi da iscrpe sve moguće poteze i
  • 11. 11 predstavi ih u sebi – to bi bilo kompletno stablo igre. Ukoliko to nije slučaj, već se stablo generiše do određenog nivoa, onda imamo horizont (ta dubina predstavlja horizont). Nakon kreiranja stabla ,celog ili delimičnog, potrebno je primeniti neki od algoritama traženja kako bi se među svim raspoloživim potezima odabrao najbolji. Algoritmi traženja dele se na slepe (neinformisane) i heurističke (informisane) algoritme. Slepi algoritmi pretražuju celo stablo i garantuju najbolje rešenje – ukoliko se izvrše nad celim stablom, odnosno najbolje rešenje do zadate dubine – ako se izvrše nad unapred zadatim podstablom. Najpoznatiji slepi algoritam je MinMax. Heuristički ili informisani algoritmi traže optimalno, a ne najbolje rešenje, jer traženje najboljeg rešenja može trajati dugo. Neki od heurističkih algoritama su A*, First-Best (prvi najbolji-još se naziva i “pohlepni algoritam”) itd. Slika 3 Stablo igre Pohlepnim algoritmom nazivamo algoritam iz kategorije heurističkih algoritama koji teži neposrednom povećanju vrednosti neke ciljne funkcije, odnosno algoritam koji bira lokalno optimalne akcije. Lokalna optimalnost znači da algoritam ne može da proceni dugoročni kvalitet izabranih akcija, odnosno koliko te akcije doprinose ostvarenju konačnog cilja, već da bira akciju koja se na osnovu znanja dostupnog u trentuku izbora procenjuje kao najbolja među raspoloz¡ivim akcijama. Ovakvi algoritmi su često značajno jednostavniji za formulaciju od algoritama koji garantuju optimalnost procesa rešavanja. Takođe, često daju praktično prihvatjiva rešenja, iako često neoptimalna [2]. MinMax spada u grupu “slepih” odnosno neinformisanih algoritama traženja. Algoritam zahteva da se najpre kreira stablo igre. Stablo ne mora da bude kompletno, već može biti kreirano do određene dubine. Nakon kreiranja stable, vrši se evaluacija (ocenjivanje)
  • 12. 12 terminalnih čvorova (listova) stabla. Terminalni čvorovi ne moraju da budu na istoj dubini. U slučaju da neki čvor predstavlja kraj igre (nemoguće dalje grananje) on je takođe terminalni čvor [2][3]. Na slici 4. je prikazan deo partije u igri “Iks Oks” (objašnjenje MinMax algoritma). Nakon ocenjivanja terminalnih čvorova, primenjuje se MinMax algoritam. MinMax algoritam se sastoji u tome što se unutrašnji čvorovi stabla evaluiraju (vrednuju, dobijaju vrednost) na osnovu vrednosti svojih potomaka. Svi čvorovi stabla proglašavaju se za maksimizirajuće i minimizirajuće, naizmenično. Koren stabla je maksimizirajući čvor, njegovi potomci minimizirajući, njihovi potomci opet maksimizirajući i tako naizmenično do listova. Ako je čvor maksimizirajući, njegova vrednost se određuje kao maksimum vrednosti njegovih potomaka, a ako je minimizirajuću, kao minimum vrednosti njegovih potomaka. Na ovaj način odrede se vrednosti svih čvorova u stablu. Slika 4 Algoritam MinMax – igra “Iks-Oks” Ovaj algoritam zapravo realno odslikava proces donošenja odluke kada čovek igra igru. Evaluacija se vrši od listova prema korenu stabla, ali za objašnjenje logike krećemo od korena ka listovim stabla. U korenu stabla treba da se nađe potez koji taj igrač treba da odigra. Taj potez predstavlja najbolji potez u analiziranom stablu (ili delu stabla). Svaki igrač teži da odigra najbolji potez koji mu je na raspolaganju. Algoritam MinMax omogućava da najbolji potez “ispliva” do korena stabla.
  • 13. 13 Međutim, protivnik teži da odigra najbolji potez za sebe, a to je ujedno i najgori potez za trenutnog igrača. Upravo ovu situaciju simulira MinMax algoritam. Nivoi Max teže da maksimiziraju vrednost poteza za trenutnog igrača dok nivoi Min teže da ih minimizuju. Ocenjivanje za oba igrača vrši se istom funkcijom evaluacije, ali se za protivničkog igrača uzima predznak minus. Jedan od problema koji se javlja kod MinMax algoritma jeste pojava da kad se na svim terminalnim čvorovima detektuje negativna vrednost (protivnik pobeđuje u svakom slučaju), MinMax nema mogućnost da izabere adekvatan potez, jer su svi potezi jednake, negativne vrednosti. Posledica ovoga je da se odabere prvi potez iz liste legalnih i time se stvara utisak kao da je računar predao partiju ili da evaluacija nije dobra. Algoritam pretpostavlja da greške neće biti napravljene, on vidi potez koji vodi pobedi i kad čovek to previđa. Slika 5 Pogrešan potez zbog nesavršenosti u funkciji evaluacije Ovo se može rešiti poboljšavanjem funkcije evaluacije. Ista pojava može se zapaziti kod potomaka sa istom, pozitivnom vrednošću (slika 5). Tada se takođe bira prvi potez i ako on može imati veću dubinu od nekog drugog. Naime, kao što se može videti na slici 5, plavi igrač umesto da odigra na polje (4,2) i time završi partiju pobedom, bira potez koji je evaluiran ranije (redosled evaluacije poteza). Odabrani potez zapravo ima istu vrednost (sigurno vodi pobedi, crveni ni u kom slučaju nema šansu da pobedi) kao i potez za pobedu u jednom potezu. Rešenje za ovaj problem je takođe u poboljšanju evaluacionih funkcija. U oba slučaja korekcija evaluacione funkcije je minimalna – evaluaciona funkcija jednostavno mora uzeti u obzir dubinu na kojoj se nalazi odabrani terminalni čvor. U slučaju jednakih pozitivnih ishoda neophodno je od vrednosti čvora oduzeti dubinu kako bi dublji čvorovi imali manju vrednost i na taj način bili diskriminisani u odnosu na čvorove bliže korenu stabla (čvorovi sa manjom dubinom), jer oni brže vode pobedi. U slučaju da svi čvorovi imaju jednaku negativnu vrednost, vrednostima čvorova je neophodno dodati brojnu vrednost njihove dubine – time se dublji čvorovi favorizuju jer vode
  • 14. 14 porazu, ali najdužim putem i time mogu iskoristiti potencijalne greške protivnika za koje je sam algoritam pretpostavio da ih neće biti. MinMax ima exponencijalnu zavisnost vremena izvršenja od dubine stable traženja i to je najveći ograničavajući faktor u njegovoj primeni. Međutim moguća su heuristička poboljšanja MinMax algoritma u cilju efikasnijeg izvršenja. Takva poboljšanja su npr. Alfa- Beta odsecanje, Killer move – killer heuristic (heuristika ubice), transpozicione tabele i drugo. Alfa-Beta odsecanje je tehnika koja ne menja kvalitet MinMax algoritma, tj. potez koji bi bio odabran od strane MinMax-a biće odabran i od strane Alfa-Beta algoritma. Dobitak od primene Alfa-Beta algoritma jeste u efikasnosti, odnosno omogućava da se ne analizira celo stablo igre, već omogućava “odsecanje” dela stabla – odsečeni deo se ne analizira. Najveći dobitak od Alfa-Beta algoritma jeste u slučaju da se najbolji/najgori potez analizira prvi (ili među prvima) pri obilasku stabla po dubini. Na taj način, samo je taj čvor evaluiran, ostatak je “odsečen” [2][3]. Slika 6 Primer Alfa-Beta odsecanja Suština Alfa Beta odsecanja jeste logika iza samog MinMax algoritma. Neki potezi jednostavno nikada neće biti odigrani zbog pozicije na kojoj se nalaze. Poboljšanje koje ugrađuje Alfa-Beta odnosi se na uštedu vremena, odnosno odsečeni čvorovi se ne obrađuju, a samim tim proces traženja poteza može biti značajno skraćen. Uzmimo primer sa slike 6. Imajući u vidu da crveni čvorovi minimizuju (biraju minimum), a zeleni maksimizuju (biraju maksimum), nakon evaluacije vrednosti -4, nema potrebe nastaviti sa evaluacijom ostatka tog podstabla (pošto njegov roditelj vrši minimizaciju, veće vrednosti sigurno neće uticati na roditelja, a s obzirom na to da koren vrši maksimizaciju, vrednost -1 je već odabrana kao maksimum). Algoritam se implementira kao rekurzivna procedura, pri svakom pozivu prosleđuje se trenutna vrednost za Alfa (maksimum) i Beta (minimum). Implementacija Alfa Beta algoritma biće data kasnije u delu koji opisuje praktičnu realizaciju. Dobitak od Alfa Beta algoritma može biti značajan, naročito u slučaju velikog broja terminalnih čvorova (veće dubine) i složenih (skupih, dugotrajnih) funkcija evaluacije. Ukoliko se pravilno primeni, Alfa Beta omogućava ubrzavanje traženja kao i povećanje dubine.
  • 15. 15 Slika 7 Alfa-Beta odsecanje – objašnjenje Adaptivno povećanje dubine [2][3] je tehnika za povećanje performansi MinMax algoritma u toku same partije. Pošto je inicijalno stablo traženja veliko, nije moguće pretražiti ga za kratko vreme. Ova tehnika se sastoji u tome da se na početku partije koriste manje dubine traženja, a kako partija odmiče, dubina se povećava sve do nekog trenutka u partiji kad postaje neograničena. S obzirom na to da se broj raspoloživih poteza smanjio, manje je i stablo te je moguće pretražiti ga brže u realnom vremenu. Sortiranje legalnih poteza [2][3] je tehnika koja povećava performanse Alfa-Beta algoritma. Alfa-Beta algoritam daje najbolje performanse ako se najbolji potez pretraži prvi – onda je odsecanje najveće (nema nepotrebne evaluacije). Da bi se ovo postiglo, potrebno je da generator poteza vrati legalne poteze u niz poređane u opadajućem redosledu po izgledima da su najbolji, odnosno prvi treba da bude potez sa najvećim izgledima da je najbolji, pa onaj sa manjim i tako redom. Sortiranje poteza može se obaviti po više kriterijuma (više kriterijuma može se koristiti pri oceni da li potez ima izgleda da je najbolji). Najčešće se koristi ocenjivanje uz pomoć transpozicione tabele (ulazi iz prethodne iteracije) ili evaluaciona tabela. Evaluaciona tabela [3] je tehnika koja omogućava da se samim pozicijama na tabeli dodeli određena vrednost. Samim svojim položajem, neke pozicije su bolje od drugih. Pri ovome se u obzir ne uzimaju pozicije ostalih figura iste boje. Koja god figura da se nađe na određenom polju uzima tu vrednost kao početnu. Na slici 8 prikazane su vrednosti polja za igru „4 u nizu“. Kao što se na slici vidi, favorizuju se polja u centru tabele, odnosno igrač treba da teži da ovlada sredinom tabele. Dodeljene vrednosti su male, jer evaluaciona tabela ne treba da ima prasudan uticaj na evaluaciju. Ona treba samo da se iskoristi kako bi u slučaju veoma bliske/jednake evaluacije dva polja odabralo ono koje je bolje pozicionirano.
  • 16. 16 Slika 8 Vrednosti polja u evaluacionoj tabeli za igru „4 u nizu“ Transpoziciona tabela [3], tj. upotreba transpozicione tabele je još jedna od tehnika koja se može upotrebiti radi poboljšavanja performanisi MinMax algoritma. Ideja iza ove tehnike je sledeća: najbolji potez u jednoj grani stabla može istovremeno biti i najbolji u drugoj grani, odnosno potez koji vodi do pobede u jednoj situaciji može takođe voditi do pobede u drugoj. Ako se takav potez evaulira jednom, nema potrebe da se evaulira ponovo, pošto je to isti potez. U primeru na slici 9. prikazana je situacija u kojoj primena transpozicione tabele poboljšava performanse (štedi evaluaciju jednog čvora) za igru šah. Slika 9 Primer situacije u kojima primena transpozicione tabele donosi korist Kao što se može uočiti sa slike, u prikazanoj situaciji, skakač može doći na ciljno polje preko dva polja. Odakle god da dođe, krajnji potez je isti. U stablu igre ova situacija biće prikazana kao dve grane stabla, obe sa po terminalnim čvorom identičnog sadržaja. U ovoj i sličnim situacijama transpoziciona tabela omogućava da se takva situacija ne evaluira dva puta, već samo jednom. Transpoziciona tabela sa prvenstveno implementira kao heš tabela čija heš funkcija treba da detektuje situacije kao na slici 9 preslikavajući tablu igre u indeks za pristup memorijskoj
  • 17. 17 lokaciji. Obe situacije sa slike 9 morale bi heš funkcijom biti preslikane u istu memorijsku lokaciju. Inkrementalno povećanje dubine stabla [3](Iterative Deeping) je tehnika koja poboljšava performanse MinMax algoritma, a primenjuje se u situacijama kada je potrebno odabrati najbolji potez u nekom ograničenom vremenskom intervalu. U realnim uslovima, tokom testiranja, neophodno je da program uvek ima spreman potez za igru. To nije moguće dobiti sa fiksnom dubinom stabla, jer dok se ne završi proces analize stabla nije moguće utvrditi koji je potez najbolji. Tehnika inkrementalnog povećanja dubine pruža mogućnost da se odabere najbolji potez u do tada kreiranom stablu. Tehnika se implementira kroz niz iteracija sa sve većom i većom dubinom (počevši od dubine 1) i pamćenjem do tada evaluiranih vrednosti u transpozicionoj tabeli. Zahvaljujući tome što se prethodno izračunate vrednosti pamte u transpozicionoj tabeli njih je moguće koristiti u narednim iteracijama. Iteriranje se prekida kada istekne zadati period vremena (timeout), ili nastupi neka druga akcija (pošto se implementacija svodi na proveru vrednosti kontrolne promenljive pre ulaska u narednu iteraciju; tu promenljivu može postaviti ona akcija koju korisnik želi, to nije od važnosti). Knjiga otvaranja i Knjiga završnica predstavljaju heurističke tehnike za unapređenje MinMax algoritma na početku i kraju partije. Ideja knjige otvaranja je u tome da se na samom početku partije ne troše resursi računara na izračunavanje poteza, jer je verovatnoća pobede najmanja, a skup legalnih poteza najveći. U takvoj situaciji može se pribeći izboru nekog od kvalitetnih poteza koji su ranije pripremljeni (smešteni u knjigu otvaranja). Knjiga završnica primenjuje se u kompleksnim situacijama u završnici igre (kao što je mat u šahu). Killer heuristics - ideja je sledeća: ukoliko je u jednoj grani stabla na dubini d najbolji potez W, ima izgleda da je on najbolji (ako je legalan) i u drugim granama stabla na istoj dubini. Ilustrujmo to na primeru šaha: neka igraču koji je na redu preti mat u sledećem potezu i neka nijedan njegov potez ne može da otkloni tu pretnju. Pretraživanjem stabla, u čvoru u kojem je na potezu protivnik, otkriva se matni potez i on postaje killer potez (za dubinu 1). Pri daljem pretraživanju stabla, na dubini 1 najpre se ispituje taj potez i kako on vodi pobedi protivnika, alfa odsecanje čini nepotrebnim dalje ispitivanje poteza u tom čvoru. Time se broj čvorova stabla ,koje u ovakvoj situaciji treba ispitati, drastično smanjuje [2][3].
  • 18. 18 4.Implementacija igre “4 u nizu” Pri implementaciji igre „4 u nizu“ korišćen je modularni pristup, odnosno, igra nije razvijena kao jedinstveno rešenje, već kao skup celina povezanih u jedinstvenu aplikaciju. Svaka od tih celina može biti zamenjena-izmenjena nezavisno od ostalih samo pridržavajući se interfejsa za komunikaciju sa ostalim delovima aplikacije (modulima). Moduli koji čine aplikaciju su: - Univerzalna platforma za logičke igre - Jezgro sistema – implementaciono zavisni delovi univerzalne platforme - GUI (grafički korisnički interfejs) U implementaciji igre iskorišćen je algoritam MinMax kao osnova sistema za odlučivanje. Kao što je ranije navedeno, MinMax spada u slepe algoritme traženja, a kao heuristička poboljšanja ugrađena su Knjiga otvaranja, Alfa Beta odsecanje, Evaluaciona tabela, Sortiranje poteza, Inkrementalno povećanje dubina, Adaptivno podešavanje dubine i Transpoziciona tabela. 4.1. Univerzalna platforma za logičke igre Jedan od ciljeva ovog rada jeste i implementacija univerzalne platforme za logičke igre, odnosno univerzalne osnove koja bi mogla da se koristi ne samo za igru „4 u nizu“, već i za druge igre koje se igraju na tabli. Platforma je implementirana u okviru TableGameBase projekta u solution-u. Sam projekat podeljen je na više celina pomoću direktorijuma koji ujedno odslikavaju i podelu projekta na funkcionalne celine. Projekat se sastoji iz sledećih funkcionalnih celina: - Book (deo koji zaokružuje funkcionalnosti vezane za knjigu otvaranja i završnica - Evaluation (deo koji omogućava implementaciju funkcija evaluacije i pomoćne mehanizme uključene u proces evaluacije) - Players (funkcionalnosti koje omogućavaju manipulisanje igračima, kako za čoveka tako i za simuliranog protivnika (AI). - Table (model tabele na kojoj se igra) - Tree (logička celina koja sadrži klase i funkcionalnosti koje manipulišu stablom traženja – stablom igre) - ITableGame (glavni interfejs za implementaciju igre, svaka igra koja bi koristila platformu za igre, mora implementirati ovaj interfejs i povezati ga sa korisničkim interfejsom (UI kontrolama, prozorima, dugmićima i akcijama) 4.1.1. Book U igri “4 u nizu” implementirana je knjiga otvaranja. Kada se uključi ovo poboljšanje prva tri poteza biraju se iz internog skupa poteza. Potezi koji su na raspolaganju grupisani su oko središnjeg dela table, jer ti potezi pružaju najveće mogućnosti za pobedu – mogu biti kombinovani sa najvećim brojem drugih poteza.
  • 19. 19 Listing 1. prikazuje implementaciju klase koja reprezentuje jedan ulaz u knjizi otvaranja. Atribut ListID predstavlja identifikator liste poteza, odnosno taj parametar treba da sugeriše kada treba (kada je pogodno) upotrebiti poteze iz atributa Moves. Sami potezi smešteni su u atributu Moves. Listing 1 Klasa koja prectavlja jedan ulaz u knjigu otvaranja/zatvaranja U implementaciji igre, kao identifikator poteza, iskorišćen je redni broj poteza. U knjigu otvaranja dodate su 3 liste poteza, po jedna za svaki od tri početna poteza. Za prvi potez, bira se potez iz liste sa identifikatorom 1, za drugi potez iz liste sa identifikatorom 2 i tako redom. Ovo je najjednostavniji način upotrebe knjige otvaranja (zapravo i vrlo primitivan), ali je cilj implementacije zapravo bio da se implementira mehanizam koji univerzalan i može se lako poboljšati. U samoj realizaciji nije bilo posebne implementacije ove funkcionalnosti, već je zadržana ova najosnovnija iz univerzalne platforme. 4.1.2. Evaluation U implementaciji igre “4 u nizu” realizovana su tri “evaluatora”. Evaluatori su klase koje implementiraju interfejs IEvaluation koji je prikazan na listingu 2. Listing 2 Interfejs evaluatora Sama evaluacija u igrama može biti realizovana i samo jednom funkcijom koja će brojnom vredniošću opisati neki potez, međutim, korišćenje interfejsa, a iz toga sledi i klasa koje ga implementiraju, omogućava laku promenu funkcije evaluacije odnosno implementaciju više različitih funkcija evaluacije i njihovo testiranje bez potrebe da se menja kod. Modularnost je omogućena upravo ovim pristupom. Veoma lako se može modul evaluacije zameniti bez potrebe da se menja ostatak projekta. Atribut MaxPoints označava maksimalnu numeričku vrednost koja može biti dodeljena potezu (na koju potez može biti evaluiran). Ova konstanta se koristi pri inicijalizaciji promenljivih (npr. kod Alfa-Beta alfa se inicijalizuje na –MaxPoints, a beta na MaxPoints) i pri ispitivanju uslova.
  • 20. 20 Metoda Evaluate je glavna metoda evaluatora i ona neposredno vrši ocenjivanje (evaluaciju) poteza (čvorova u stablu traženja). Način ocenjivanja zavisi od implementacije, odnosno svaki evaluator koji implementira ovaj interfejs može primeniti različitu tehniku. Metode NewEvalObject, NewMax i NewMin su metode koje kreiraju nove vrednosti i odmah ih inicijalizuju na neku specifičnu vrednost. NewEvalObject kreira novi objekat i ne inicijalizuje numeričke vrednosti. NewMax i NewMin kreiraju instance objekta koji opisuje vrednost poteza (specifičan objekat za svaki evaluator), i inicijalizuju ga na maksimum, odnosno minimum (korišćenjem MaxPoints atributa). Pri evaluaciji ponekad nije dovoljno potez opisati samo jednom vrednošću. Ponekad se javlja potreba da se potez opiše sa više atributa. Najbolji način da se ovo postigne je korišćenjem objekata koji imaju potrebne atribute za opis poteza. Evaluator onda ima zadatak da te atribute postavi na određenu (ocenjenu) vrednost. Dakle, ocenjivanje poteza se ne vrši korišćenjem jedne brojne vrednosti, već složenim objektom koji ocenjuje više parametara. Međutim, broj parametara može biti različit od evaluatora do evaluatora (neki evaluatori mogu ocenjivati samo pobedu, drugi mogu uzimati u obzir i raspored figura itd.). Zbog toga, klasa koja opisuje poteze nije strogo definisana, već je apstraktna. To je IVal klasa (listing 3). Pri evaluaciji poteza takođe je moguće uzeti u obzir samu poziciju polja, bez posmatranja konteksta, odnosno samim tim što je potez tu gde je, on može biti vrednovan. Za to je predviđena tabela EvaluationTable. Pri evaluaciji polja, kao inicijalna vrednost koristi se vrednost iz tabele EvaluationTable na koordinatama koje ima polje (naime, dimenzije tabele su iste kao i dimenzije table za igru tako da svako polje ima dodeljenu vrednost). U implementaciji ovo može biti i promenjeno, uzimajući u obzir da je ovo interfejs (IEvaluation), implementaciona klasa može opisane mehanizme u memoriji implementirati na bilo koji način. Takođe, javlja se potreba da se na evaluaciju poteza (stanja tabele) utiče spolja, nekom vrednošću. Za tu namenu predviđen je atribut Correction u klasi IVal. Kao što se vidi sa slike svaka klasa za vrednovanje mora naslediti apstraktnu klasu IVal. Samim tim mora definisati neke atribute. NumericValue je numerička vrednost koja se koristi za upoređivanje poteza, međutim kako se ta vrednost određuje, nije strogo definisano već je ostavljeno evaluatorskim implementacionim klasama da je odrede. Ovaj pristup omogućava da objekti koji opisuju poteze pomoću različitih evaluatora budu međusobno uporedive. Radi što lakšeg upoređivanja vrednosti različitih objekata za evaluaciju predefinisani su i operatori >,<. Predefinisanje operatora omogućava direktno poređenje dva objekata u kodu, bez potrebe za dodatnim izračunavanjima na mestu gde je poređenje potrebno. Način predefinisanja operatora prikazan je takođe na listingu 3.
  • 21. 21 Listing 3 Abstraktna klasa koja prectavlja vrednost poteza u igri Kratak primer ove opisane klase: ukoliko , na primer za određenu igru želi implementirati dve evaluacione funkcije A i B. Evaluacijona funkcija A uzima u obzir samo pobedu ili poraz, dok B uzima još neki koristan parametar pri ocenjivanju. Ukoliko se koristi univerzalna platforma za logičke igre, obe ove klase moraju implementirati interfejs IEvaluation. Obe metode evaluacije takođe mogu definisati i klasu koja će se koristiti da numerički opiše čvorove, a koja mora naslediti klasu IVal. Iz ovoga sledi da klase A i B mogu imati pomoćne klase A1 i B1 koje nose brojne vrednosti. Pošto A1 i B1 nasleđuju IVal, one su međusobo uporedive, jer postoji predefinisani operator. Samim tim, u kodu je moguće direktno postaviti uslov A1 > B1 što znači da je moguće upoređivati različite klase, direktno. Sam operator zapravo upoređuje atribut NumericValue koji svaka klasa izračunava na svoj način, ali ga mora imati. Za potrebe igre “4 u nizu” implementirana su tri evaluatora (biće opisani kasnije) a samim tim i tri objekta za vrednovanje (BasicVal, ExtendedVal, TestVal) koji su svi međusobno uporedivi i ako za opis poteza koriste različit broj parametara (svi nasleđuju klasu IVal). U ovom slučaju nisu korišćeni interfejsi, jer je bilo potrebno da neke stvari budu definisane, kao što su operatori i metoda ToString(). Da je korišćen interfejs, ove dve stvari morale bi da budu definisane u svakoj od klasa koje implementiraju interfejs. Korišćenje abstraktne klase omogućava da se to definiše jednom i koristi u izvedenim klasama (kao što je slučaj i sa predefinisanim operatorom – to u interfejsu ne bi bilo moguće uraditi). Za opisivanje transpozicione tabele takođe je iskorišćen interfejs ITranspositionTable. Interfejs zahteva samo implementaciju metode za direktan pristup tabeli. Sama tehnika smeštanja podataka u memoriju ostavljena je implementacijama interfejsa na rešavanje. Na listingu 4. prikazan je interfejs ITranspositionTable.
  • 22. 22 Listing 4 Interfejs transpozicione tabele Metoda Reset poziva se pre svakog poteza i ima zadatak da isprazni transpozicionu tabelu. U vezi sa realizacijom transpozicione tabele realizovana je još i klasa koja opisuje ulaze u transpozicionu tabelu, odnosno klasa TransTableRecord (listing 5). Svaki ulaz u tabelu predstavljen je klasom TransTableRecord. Atribut Key predstavlja ključ za direktni pristup. On se u slučaju implementacije uz korišćenje heš tabele ne mora koristiti, jer bi pristup bio direktan, pomoću indeksa u tabeli. Atribut Val predstavlja memorisanu vrednost. Listing 5 Ulaz u transpozicionu tabelu 4.1.3. Players U direktorijumu Players grupisane su klase i interfejsi koji logički objedinjuju sve funkcionalnosti vezane za opisivanje igrača i njihovih akcija, bilo da se radi o čoveku ili AI igraču. Za opis igrača definisan je interfejs IPlayer (listing 6). Ovaj interfejs se koristi za oba tipa igrača, čoveka i AI. Prvenstveni cilj ovog interfejsa jeste da objedini sve atribute zajedničke za oba tipa igrača, a i da predstavlja jedinstveni tip iz koga su izvedene obe vrste igrača. Listing 6 Interfejs igrača Za predstavljanje igrača čoveka koristi se klasa Player. Ova klasa nema atributa osim onih iz osnovne klase (interfejsa). Implementacija je prikazana na listingu 7.
  • 23. 23 Listing 7 Klasa koja reprezentuje igrača čoveka Za predstavljanje AI igrača koristi se apstraktna klasa IAIPlayer. Klasa je apstraktna, jer implementira osnovne metode koje se koriste u igri, ali pruža mogućnost da se u implementaciji to promeni (override). Atributi i metode ove klase prikazani su na listingu 8. Listing 8 Abstraktna klasa AI igrača
  • 24. 24 Atributi UseBookForOpening, UseMultiTasking, UseAlphaBeta, UseTransTable, UseTimer, UseIterativeDeeping, UseEvaluationTable, UseMoveSorting i UseAdaptiveDepth označavaju istoimene dodatke MinMax algoritmu. Neki od dodataka su heuristički ,a neki su implementacioni (kao Multi-Tasking i Timer). Ovi parametri određuju profil AI igrača, odnosno određuju mu šta sve može da koristi pri donošenju odluke u igri. Cilj svih dodataka je da poboljšaju proces odlučivanja i povećaju performanse. Atribut Book predstavlja knjigu poteza koja je na raspolaganju AI igraču i koju on može koristiti ako mu je uključena opcija UseBookForOpening. Atribut Evaluator predstavlja klasu evaluatora koja je pridružena AI igraču da je koristi pri evaluaciji poteza. Tip ovog atributa je IEvaluation (interfejs) što znači da kao evaluator može biti dodeljena klasa samo iz implementacije (univerzalna platforma ne nudi evaluatore, jer evaluacija mora biti vezana i specifična za svaku igru, već nudi samo interfejs koji evaluator mora implementirati kako bi bio korišćen od strane platforme). Atribut TransTable je je transpoziciona tabela koja je na raspolaganju AI igraču pri evaluaciji poteza. Važi isto što i za IEvaluator, odnosno sama platforma diktira samo interfejs koji implementacija transpozicione tabele mora da implementira ali ne i samu implementaciju. Razlog za ovo jeste taj što transpoziciona tabela može biti implementirana na različite načine, zavisno od potreba igre (kao heš tabela, kao niz, itd.). Depth i MaxDepth su trenutna dubina generisanog stabla traženja i maksimalna dubina stabla traženja koju treba generisati, respektivno (oba ova parametra značajna su kod inkrementalnog povećanja dubine). Sve metode iz klase implementirane su kao virtuelne, odnosno nude implementaciju, ali u igri se ne moraju koristiti ukoliko se implementacijom zahteva drugačiji pristup (override ovih metoda u samoj implementaciji). Metoda Reset ima ulogu da resetuje sve promenljive, koje se koriste u toku donošenja odluke, na inicijalnu vrednost. Poziva se nakon ili pre svakog poteza. Metoda Play inicira proces odabira poteza (traženja). Sam proces se razlikuje od dodataka koji su na raspolaganju pri donošenju odluke (listing 9). Ukoliko se koristi sat, on se inicira, ukoliko se koristi inkrementalno povećanje dubine ili adaptivno povećanje dubine određuje se početni i krajnji parametric, a zatim se kreće u proces kreiranja stabla i evaluaciju. Nakon završetka procesa evaluacije, bira se najbolji potez (u samoj virtuelnoj metodi to zapravo nije odvojeno), a nakon toga se aktivira događaj (event) koji obaveštava sve zainteresovane strane (najčešće GUI kako bi to bilo i prikazano na korisničkom interfejsu) o odabranom potezu.
  • 25. 25 Listing 9 Play metoda – traženje poteza Metoda CreateSearchTree inicira kreiranje stabla traženja. Na početku ove metode, poziva se generator poteza (listing 10) i od tih poteza kreće generisanje stabla traženja. Ukoliko je na raspolaganju mogućnost sortiranja poteza, potezi se sortiraju na bazi njihovih vrednosti u
  • 26. 26 evaluacionoj tabeli. Takođe, metoda podržava i paralelno izvršenje (ukoliko je dozvoljeno koristiti ga). Listing 10 Osnovna metoda za generisanje stabla traženja Iz metode CreateSearchTree na svakom nivou stabla poziva se metoda GenerateNextLevel koja kreira sledeći nivo stabla (listing 11).
  • 27. 27 Listing 11 Rekurzivna metoda za generisanje narednog nivoa u stablu traženja Metoda za generisanje stabla je izuzetno bitna, jer utiče i na evaluaciju. Naime, pri kreiranju čvorova stabla, dodaje se i event handler koji obrađuje događaj kada se čvoru dodeli vrednost. Suština ove obrade jeste da kada jedan čvor dobije vrednost on “obaveštava” svog roditelja o tome i roditelj onda može ažurirati svoju vrednost. To opet inicira ažuriranje vrednosti njegovog roditelja i tako rekurzivno do korena generisanog stabla. Ova metoda rekurzivno poziva sama sebe ukoliko trenutni čvor ne predstavlja kraj igre.
  • 28. 28 Metoda PlayByBook (listing 12) nalazi potez u knjizi poteza koji odgovara traženim kriterijumima i odabira ga. Listing 12 Metoda koja vraća potez iz knjige otvaranja/zatvaranja Metoda MinMax implementira MinMax algoritam traženja (listing 13). Ova metoda poziva se iz metode Play nakon kreiranja stabla traženja za koren generisanog stabla (koren generisanog stabla prosleđuje se kao parametar funkcije). Metoda rekurzivno poziva sama sebe i pri svakom pozivu proverava da li sme da nastavi (u slučaju inkrementalnog povećanja dubine sat postavlja kontrolnu promenljivu StopSearch na true i time zaustavlja dalju evaluaciju stabla). Metoda poziva sebe rekurzivno za čvorove sve veće dubine dok ne dođe do terminalnih čvorova (u smislu terminalnih čvorova celog stabla ili terminalnih čvorova na horizontu, sve jedno) a onda vrši evaluaciju tih čvorova korišćenjem dodeljenog evaluatora. Pri evaluaciji, koristi se transpoziciona tabela ukoliko je dozvoljeno. Takođe, ukoliko je to dozvoljeno, metoda se izvršava paralelno za sve potomke tekućeg čvora. Metoda evidentira neke kontrolne parametre kao što su broj pogodaka i promašaja u transpozicionu tabelu kao i ukupan broj evaluiranih čvorova.
  • 29. 29 Listing 13 Implementacija MinMax algoritma Metoda Alfa-Beta implementira istoimeno heurističko poboljšanje MinMax algoritma (opisano u prethodnim delovima). Implementacija metode prikazana je na listingu 14. Kao i kod osnovnog algoritma traženja MinMax-a, metoda Alfa-Beta počinje proverom zadovoljenosti uslova za prekid traženja (StopSearch) koje postavlja inkrementalni način traženja (inkrementalna promena dubine traženja). Metoda je takođe rekurzivna, a kao parametri pri prvom pozivu prosleđuju se koren generisanog stabla traženja i maksimalna vrednost (A) inicirana na najmanju moguću i minimalna vrednost (B) inicirana na maksimalnu vrednost. Iniciranje na suprotne vrednosti radi se namerno kako bi se osiguralo da one budu zamenjene već pri prvom izvršenju. Kada se evaluira terminalni čvor, ta se vrednost upisuje u transpozicionu tabelu – ako je dostupna, ili se iz nje pročita vrednost ako je takav čvor već evaluiran ranije. Zatim se proveravaju Alfa (A) i Beta (B) i vrši se odsecanje u skladu s pravilima koja su opisana ranije. Odsecanje se praktično vrši tako što se prekida dalja evaluacija čvorova na tom nivou. Po detekciji odsecanja, vrši se i korekcija kontrolnih parametara koji broje koliko je odsecanja bilo. Kao i kod MinMaxa broji se i broj pogodaka i promašaja u transpozicionu tabelu kao i ukupan broj evaluiranih čvorova.
  • 30. 30 Listing 14 Implementacija Alpha-Beta algoritma Metoda Evaluate je glavna metoda za evaluaciju (listing 15). Ona vrši ocenjivanje poteza (čvora) pozivanjem dodeljenog evaluatora kao i invertovanje (postavljanje znaka – ispred vrednosti) ako je evaluacija pozvana za čvor u kome igra protivnik (ninimizirajući čvor). Detekcija potrebe za invertovanjem vrši se testom parnosti dubine na kojoj se čvor nalazi (neparni čvorovi su maksimizirajući, parni minimizirajući). Kao što se vidi sa slike, osim naredbe Invert koja se koristi za evaluaciju protivničkih poteza (menja znak), postoji i korekcija vrednosti po dubini. Suština je da se koriguje vrednost čvora ukoliko svi čvorovi imaju istu vrednost. Najbolji će onda biti potez sa najvećom dubinom ako odlaže poraz najduže, odnosno najmanjom ako ubrzava pobedu.
  • 31. 31 Listing 15 Evaluaciju poteza odabranim evaluatorom 4.1.4. Table U direktorijumu Table nalazi se abstraktna klasa ITable koja definiše način pristupa tabli za igranje i njenim atributima kao i neke pomoćne klase koje se koriste u toku partije. Prava od pomoćnih klasa je GameOverDetails koja nosi podatke o pobednuku u partiji. Instanca ove klase kreira se kada se igra završi. Atribut Winner označava boju igrača koji je pobedio. Atributi X1,Y1 i X2,Y2 označavaju koordinate početka i kraja niza figurica koji je doveo do pobede. Implementacija je prikazana na listingu 16. Listing 16 Implementacija klase koja nosi podatke o kraju igre Enumerator FieldStata predstavlja skup vrednosti koje može uzeti svako polje u tabeli, može biti prazno, zauzeto crvenim i zauzeto plavim (listing 17). Pored ovog podatka, klasa FieldDesc sadrži i podatak o poziciji polja (atributi X i Y). Svako polje u matrici koja reprezentuje tablu za igru sadrži po jednu instancu klase FieldDesc.
  • 32. 32 Listing 17 Klase i enumeratori koji se koriste za opis polja na tabli Glavna klasa je apstraktna klasa ITable koja opisuje način pristupa tabli igre i njenim poljima (listing 18). Listing 18 Univerzalna tabla igre Predefinisani operator + omogućava da se sabiraju potezi sa matricom, odnosno da se u trenutno stanje partije doda potez. Kada neko od igrača odigra potez, potez se u tabeli dodaje kao zbir stare tabele i novog poteza. Rezultat je nova tabela koja sadrži i taj novi potez. Ovaj operator omogućio je znatnu uštedu u pogledu memorije koja se troši pri izvršenju programa, jer zahvaljujuci njemu nema potrebe da svaki čvor čuva u stablu traženja tablu na koju se odnosi već samo koren stable, a svi ostali čvorovi pamte samo svoj potez. Ovo će biti objašnjeno detaljnije kasnije.
  • 33. 33 4.1.5. Tree Direktorijum Tree objedinjuje klase i interfejse za opisivanje stabla traženja. Klasa TreeNode (listing 19) objedinjava sve funkcionalnosti vezane za čvor stabla (TreeNode). Na samom početku definisan je delegat koji opisuje interfejs metoda koje obaveštavaju o promeni vrednosti čvorova potomaka. Listing 19 Čvor stabla traženja Svaki čvor prethodnik (roditelj) mora dodati funkciju koja će se pozvati kad neki od njegovih potomaka promeni vrednost. Na taj način omogućeno je da on lako koriguje svoju vrednost. Metoda se dodaje u metodi GenerateNextLevel u klasi IAIPlayer.
  • 34. 34 Takođe definisan je i enumerator NodeType koji opisuje da li je čvor maksimizirajući ili minimizirajući. Ova vrednost za svaki novi čvor takođe se postavlja u GenerateNextLevel metodi u klasi IAIPlayer. Jedan od klučnih elemenata ove klase je atribut Table koji daje tablu koju taj čvor predstavlja. On je implementiran kao rekurzivan radi uštede memorije (pre ovakve implementacije, u verziji u kojoj je svaki čvor imao svoju tabelu na dubini 5, program je u operativnoj memoriji zauzimao oko 1.3GB što je neprihvatljivo, sa novom implementacijom za dubinu 6 zauzima oko 300MB). Kolekcija potomaka (čvorova sledbenika) predstavljena je klasom TreeNodeCollection (listing 20). Razlog zašto je ovo implementirano kao zasebna klasa, a ne kao prosta; list u okviru svakog čvora jeste dodavanje metoda kao što su ToString() koja pruža lako izdavanje skupa čvorova pri debagiranju i uvid u njihove vrednosti, a i lakše oslobađanje memorije (garbage collector u .net frameworku oslobađa memoriju čim ne postoji nijedna referenca na taj objekat u programu). Sa ovakvim pristupom cela kolekcija se oslobađa samo uništavanjem jednog objekta. Listing 20 Klasa koja prectavlja potomke čvora 4.1.6. Table game Ova celina implementira samu logiku igre. Pomocna klasa MoveInfo nosi informacije o odabranom potezu nakon što se završi proces traženja. Od informacija koje ovaj objekat nosi tu su: broj alfa odsecanja, broj beta odsecanja,
  • 35. 35 sam potez, celokupnu transpozicionu tabelu, broj pogodaka i promašaja u transpozicionu tabelu, dubina traženja na kojoj je nađen potez, vreme početka i kraja traženja. Svi ovi podaci ne opterećuju memoriju (ne zauzimaju dodatni prostor), jer se objekti u .net frameworku prenose isključivo po referenci. Dakle, ne prave se kopije postojećih već se prenose reference na postojeće. Na listingu 21 prikazana je implementacija klase. Listing 21 Klasa koja opisuje odabrani potez Na listingu 22 prikazan je interfejs ITableGame koji je glavni interfejs za logičke igre. On upravlja samom logikom igre. Implementacija ovog interfejsa mora obezbediti metodu koja kao parametar prihvata objekat tipe MoveInfo i ta metoda biće pozvana kad se završi proces traženja. Najčešće je ta metoda povezana sa interfejsom i prikazuje odabrani potez korisniku na grafičkom interfejsu. Listing 22 Interfejs za realizaciju logike igre
  • 36. 36 Takođe, implementacija interfejsa mora sadržati listu igrača (predstavljenih atributom IPlayer[] a s obzirom na to da je to niz interfejsa IPlayer, u tom nizu može se naći AI igrač ili čovek budući da obe klase nasleđuju IPlayer interfejs. Koliki će broj igrača biti i kog će oni tipa biti, zavisi od potreba same implementacije (konkretne igre); sama platforma to ne ograničava. CurrentPlayer i CurrentPlayerIndex ukazuju na trenutnog igrača u partiji (onog koji je na potezu ili čije je potez u toku). Veoma značajna metoda koja se mora implementirati u implementacionoj klasi jeste NextPlayer. Ova metoda je bitna zato što zavisno od implementacije ove metode u igri se igrači mogu smenjivati naizmenično ili na bilo koji drugi način. Ovo omogućava da se interfejs primeni na veoma veliki skup igara, ako ne i na sve. 4.1.7. Paralelizacija U implementaciji je u cilju postizanja paralelizma korišćena biblioteka TPL (framework 4.0). Ova biblioteka omogućava paralelno izvršenje petlji. Takođe ova biblioteka sadrži još neke korisne implementacije (taskove, niti itd.) koje omogućavaju lako korišćenje nekih tradicionalnih metoda paralelizacije i multi-taskinga. Kao jedan od efekata paralelizma u izvršenju jeste i mutacija koja je korisna u smislu varijacija u igri, odnosno, pošto se ne igra uvek isti potez, stvara se utisak da se igra sa čovekom. Ovo se događa zbog toga što pri paralelnoj obradi nema garancija koji će element biti prvi obrađen. Prvi koji bude obrađen, a zadovoljava uslove, biće odabran. To nije uvek isti potez. U prilogu obrazloženja uticaja paralelizma na izvršenje programa, data je tabela 2 koja treba da pokaže uticaj paralelizma na trajanje izvršenja programa za različite dubine stabla traženja (navedena vremena označavaju vreme potrebno za prvi potez, sva ostala poboljšanja su aktivirana – samo je TPL izostavljen kod testiranja sekvencijalnog izvršenja). U tabeli 2 uporedo su prikazana vremena izvršenja pri sekvencijalnom i paralelnom izvršenju. Dubina stabla TPL (s) Sekvencijalno (s) 1 0.05900 0.0380 2 0.06980 0.0624 3 0.08200 0.0980 4 0.17960 0.2660 5 0.68763 1.3268 6 4.27575 8.8721 7 34.54829 61.21468 Tabela 2 Uticaj paralelizma na vreme izvršenja Na slici 10. prikazani su grafici koji odslikavaju vrednosti iz tabele 2. Sa grafika se može uočiti eksponencijalna zavisnost vremena izvršenja MinMax-a od dubine stabla traženja (kao što je ranije napomenuto).
  • 37. 37 Slika 10 Uporedni grafički prikaz zavisnosti vremena izvršenja od dubine Takođe, važno je napomenuti zašto je u implementaciji korišćena ‘for’ petlja umesto ‘foreach’ petlje (koja je inače mnogo lakša za korišćenje od strane programera). Razlog za to su performanse. Naime, dvostruko je brže iteriranje korišćenjem for petlje u odnosu na iteriranje korišćenjem foreach petlje. Takođe, iz istog razloga se koriste Array liste (nizovi) umesto generičkih listi ,koje su inače izuzetno praktične i lakše za korišćenje od običnih array listi - nizova. Naime, iteriranje kroz Array niz je dvostruko brže od iteriranja kroz listu. Experimentalno se može utvrditi da je za veći broj iteracija (oko 100000) iteriranje sa for kroz noz čak do 5 puta brže nego iteriranje kroz listu sa foreach. Vremena koja su u tabeli 2. postignuta su na PC-ju sledeće konfiguracije: CPU Intel i5 2500k – Turbo Boost unlocked RAM DDR3 – 1333 MHz – 2GB – Single channel HDD 500GB – 7200rpm Tabela 3 PC konfiguracija na kojoj je izvršeno testiranje 4.1.8. Problem sinhronizacije rekurentnih taskova Prvobitna implementacija aplikacije imala je paralelizam implementiran preko taskova. Svaki nivo generisanja stabla bio je zasebni task. U ovakvoj implementaciji javlja se problem sinhronizacije tih taskova – neophodno je znati kada je celokupno stablo traženja kreirano kako bi se krenulo u njegovu evaluaciju. Dodatni problem ovde jeste što su taskovi rekurzivni, odnosno svaki čvor kreira svoje potomke pozivanjem iste metode u kojoj je i sam kreiran. Zbog ove činjenice teže je realizovati mehanizam za sinhronizaciju nego samo kreiranje paralelnih taskova. Sam TPL omogućava više pristupa za realizaciju paralelizma:: - Implementacija pomoću taskova - Implementacija pomoću niti (threadpool) - Implementacija paralelizacijom petlji Pri upotrebi TPL-a kao generatora taskova (tako što se dodaju taskovi u interni bafer TPL-a) performanse se zapravo degradiraju. Zbog nemogućnosti kontrole broja taskova, jer je sama metoda koja treba da se izvrši rekurzivna, svaki task dobija zasebnu nit koja će ga obrađivati. 0 10 20 30 40 50 60 70 1 2 3 4 5 6 7 TPL Sekvencijalno
  • 38. 38 Posledica ovoga jeste da se zauzme ogromna količina memorije. Naime, pri pokretanju svake niti pod windows OS-om rezerviše se oko 1MB radne memorije za njeno izvršenje. Imajući u vidu da je broj niti približno jednak broju čvorova u stablu (svaki task kreira svoju decu, a deca opet kreiraju svoje taskove za svoje potomke). Posledica ovoga jeste usporavanje sistema. Zapravo, ovoliki broj niti ima negativan efekat i degradira performanse. Takođe, na određenoj dubini stabla (nakon kreiranja određenog broja taskova – niti) dolazi do greške. Do dubine 4 (oba igrača do dubine 4) program se izvršava, međutim za dubine 5,6 i 7 dolazi do greške. Takođe, problem koji se javlja u implementaciji ovog rešenja uz upotrebu TPL-a jeste i sinhronizacija. TPL poseduje ugrađen mehanizam za sinhronizaciju taskova pokrenutih pod njegovom kontrolom. To se obavlja sledećom metodom: Listing 23 Ugrađen metod sinhronizacije taskova ugrađen u TPL Ova metoda omogućava da sam TPL upravlja izvršenjem pokrenutih taskova. Svodi se na to da se poziva prosleđena metoda nakon što se svi taskovi iz date liste taskova završe. Međutim, postoji veliki praktični problem u slučaju implementacije uz upotrebu ove tehnike za sinhronizaciju taskova. Pošto je lista taskova zajednička (pošto je kritični resurs, zaštićena je LOCK blokom), a metoda koja se izvršava je rekurzivna, svaki task menja listu taskova u kojoj se sam nalazi, a za sinhronizaciju je neophodno proslediti istu tu listu. Međutim, pošto je prosleđena lista podložna promenama u toku izvršenja, u praksi se dešava de se više puta detektuje prazna lista taskova i time se pogrešno izazove događaj koji signalizira da je stablo kreirano. Ovo je posledica implementacije. Iako je lista taskova javna, TPL-u se prosleđuje samo deo (celokupna do tada kreirana lista). Na primer, ukoliko imamo 3 taska, koji se dodaju jedan po jedan, najpre se u listi taskova doda prvi i krene se u njegovo izvršenje, a TPL-u se prosleđuje ta lista (sa samo tim jednim taskom). TPL čeka da se taj jedan task završi. Taj task pri izvršenju kreira 2 nova taska i dodaje ih u listu taskova, pri čemu je već detektovano izvršenje prvog taska, a pošto druga dva taska još uvek nisu dodata u listu, dolazi do signalizacije kraja (jer je lista taskova TPL-a prazna). Međutim, taskovi koji se upravo sada izvršavaju opet menjaju listu i nakon njihovog izvršenja se ponovo signalizira isti događaj. Ovo se ne dešava na prvom nivou (kao što je opisano u primeru) već na višim nivoima ali je prvi nivo dobar za primer. U suštini radi se o klasičnom problemu proizvođač-potrošač, ali
  • 39. 39 pošto se ne radi o podacima već o metodama koje se izvršavaju unutar niti – operativni sistem menja prioritet niti ,te nema garancije da će se niti završiti u redosledu izdavanja (pokretanja). Poboljšanje rešenja trebalo je da donese dodatni brojač internih taskova. Pri dodavanju taska u list čekanja na izvršenje inkrementira se brojač taskova. Po završetku taska isti taj brojač se dekrementira. Kad brojač dostigne vrednost 0, to je događaj koji se čeka. Implementacija ovog rešenja prikazana je na listingu 24. Listing 24 Metoda sinhronizacije pomoću brojača U praksi se dešava isto kao i kod prethodne implementacije. Svako pokretanje novog taska inkrementira brojač a završetak izvršenja dekrementira isti taj brojač. Nema liste taskova. Međutim i ovde se desi da se više taskova završi nego što se pokrene pa se detekcija vrednosti 0 za brojač (to je trenutak u kome treba signalizirati da je proces završen). Takođe, kao i u prethodnoj tehnici, problem se ne javlja na malim dubinama stabla već na dubinama većim od 3. Uzrok problema u sinhronizaciji jeste rekurzivna metoda koju niti izvršavaju. Sledeći pokušaj poboljšanja bio je pomoću timer-a. Kad se proces pokrene, pokrene se i sat koji se resetuje nakon svakog novog pokrenutog taska. Znači svaki novi task resetuje sat koji odbrojava u nazad. Ovo omogućava da sat bude resetovan zadnji put kad zadnji task bude pokrenut (ili završen – resetuje se pri svakoj promeni), tj. završen. Ovo omogućava da sat signalizira događaj određeno vreme nakon završetka zadnjeg taska i time garantuje da neće biti naknadnih promena (ako neki task kasni sa izvršenjem). Na listingu 25 prikazana je ova implementacija.
  • 40. 40 Listing 25 Metoda sinhronizacije pomoću timer-a Nedostatak ovog rešenja je što je neophodno setovati vreme tajmera na neku relativno veliku vrednost (3 do 10 sekundi) što je vrlo nepraktično, pogotovo za male dubine. Za mala vremena, desi se da task zakasni više od tog vremena, pa imamo istu situaciju kao i ranije. Naredna implementacija je najbolja u smislu sinhronizacije rekurzivnih taskova. Ova implementacija je uspešno rešila problem sinhronizacije. Suština je u tome da svaki task poseduje internu listu taskova potomaka (taskove koje je on pokrenuo) i čeka da se oni završe pre nego što se on sam završi. Ovo omogućava da su taskovi koji su viši u hijerarhiji blokirani dok se svi njihovi potomci ne završe. Ne postoji globalna (deljiva, zajednička) lista taskova koji su pokrenuti u sistemu. Implementacija je prikazana na listingu 26. Listing 26 Roditelj task čeka na izvršenje potomaka taskova Glavnu ulogu pri sinhronizaciji opet ima metoda WaitAll (interna metoda TPL) kao i u orginalnoj implementaciji. Jedina je razlika što ovde nema zajedničeke liste taskova te nema ni problema koje ta lista izaziva (kao u orginalnoj implementaciji). Nakon uspešnog rešavanja problema sinhronizacije, zaključak je da su performanse zapravo pogoršane, te je kompletno rešenje odbačeno. Na listingu 27 prikazan je primer implementacije uz korišćenje TPL-a za paralelizaciju petlji.
  • 41. 41 Listing 27 Implementacija sa korišćenjem paralelizma u TPL-a TPL omogućava paralelno izvršenje FOR i FOREACH petlji. Razlika između normalne implementacije i implementacije uz upotrebu TPL za ralelizaciju petlji je velika, u korist TPL-a. Prosečno vreme za izračunavanje prvog poteza je oko 6 sekundi bez upotrebe TPLa, a oko 3.5 sekundi (za dubinu 6). Pri ovoj implementaciji, nema problema sinhronizacije, jer se operacija obavlja za sve elemente niza (potomke čvorova) paralelno. Vreme potrebno za izvršenje, idealno, jednako je jednoj iteraciji (najdužoj). Nivo paralelizacije (broj elemenata koji se paralelno obrađuju) inicijalno je jednak broju jezgara računara, ali može se promeniti. Ovo rešenje je na kraju usvojeno kao konačno, ali je radi praktične provere implementirano i rešenje koje koristi TPL za generisanje niti i upravljanje paralelnim izvršenjem procedura (threadpool). U slučaju korišćenje TPL-a za upravljanje taskovima ili nitima postoji i praktično ograničenje vezano za rezervisanje hardverskih resursa računara (operativna memorija). Na slici 11. prikazana je greška koja se dobija kada se prekorači broj dozvoljenih niti (prekoračen je broj niti koje mogu biti kreirane u raspoloživoj memoriji). Naime, za svaku nit rezerviše se jedan megabajt prostora u operativnoj memoriji računara. Zbog postojanja velikog broja čvorova (samim tim velikim brojem metoda / taskova / niti) veliki deo operativne memorije je zauzet. Operativni sistem u određenom trenutku ne dozvoljava dalje kreiranje taskove.
  • 42. 42 Slika 11 Izgled greške pri velikom broju taskova / niti Listing 28 i 29 prikazuju implementaciju ThreadPool-a. Listing 28 Pomoćne klase u implementaciji ThreadPool-a
  • 44. 44 Klasa Worker objedinjuje funkcionalnosti vezane za upravljanje nitima u threadpool-u. Evant JobDone signalizira threadpool-u da je ta nit završila posao koji joj je dodeljen (ukoliko postoji još poslova u listi, može joj se dodeliti novi posao). Enumerator State opisuje status koji može imati nit, Idle (slobodna) i Running (zauzeta, pokrenuta). Metoda DoWork daje naredbu niti da uzme prvi slobodan posao iz threadpool-a i izvrši ga. Metoda Stop zaustavlja nit (prekida trenutnu operaciju). Klasa Job objedinjuje atribute koji opisuju posao (jedinicu izvršenja, jedan poziv nekoj funkciji). Status jednog job-a (instance klase Job) opisan je enumeratorom State. Job može imati dva statusa, InProgress (izvršava se) i Free (slobodan). Za izvršenje metode koja je opisana Job-om vezana je još jedna metoda, opisana atributom CallBack, koja se poziva nakon nakon osnovne metode dodeljene tom Job-u. Svrha druge metoda je da pozivaoca obavesti o tome da je tražena funkcija izvršena. Izvršenje Job-a obavlja se pozivom njegove metode Execute koja onda redom pozove metode ToDo i CallBack. Klasa ThreadPool implementira funkcionalnosti vezane za sam threadpool. Suštinski način funkcionisanja threadpool-a je sledeći. Kad se doda novi posao u threadpool, proverava se ima li slobodnih niti, ako ima, prvoj slobodnoj niti se dodeljuje posao. Ako nema slobodnih niti, posao se dodaje u red čekanja. Kada se oslobodi prva nit, dodeljuje joj se prvi job iz reda čekanja. Broj niti koje će raditi u threadpoolu određuje se pozivom metode Intit kao paramtar ThreadCount. Metoda Stop zaustavlja rad threadpool-a tako što zaustavlja sve niti. Završeni posao se izbacuje iz liste čekanja. I ova implementacija nije dala značajnih poboljšanja u performansama pa je kao najbolje rešenje uzeta implementacija sa korišćenjem TPL-a za paralelizaciju petlji. 4.2. Implementacija igre „4 u nizu“ Implementacija igre „4 u nizu“ podeljena je na tri dela. Implementacija osnovne platforme, implementacija specifičnih delova igre oslonjenih na platformu i na kraju, implementacija korisničkog interfejsa. Implementacija osnovne platforme je objašenjena u prethodnom delu. U ovom delu biće objašnjen način implementacije specifičnih delova igre koji se oslanjaju na osnovnu platformu za logičke igre. 4.2.1. Tabla igre (implementacija ITable) Tabla igre (table game) implementira abstraktnu klasu ITable iz TableGameBase platforme za logičke igre. Klasa se zove 4inLineTable. Generator poteza - Skup poteza koji su legalni u svakom trenutku za svakog igrača generiše generator poteza. Generator legalnih poteza implementiran je kao metoda klase table igre (4inLineTable), a koja implementira apstraktnu klasu ITable kojim je ova metoda zahtevana (više o ovome u opisu implementacije interfejsa). Kad god se ta metoda pozove ona vraća niz legalnih poteza koji su na raspolaganju igraču koji je pozvao metodu. Ime metode je GetAvailableMoves i implementacija metode prikazana je na listingu 30. U igri “4 u nizu” legalan je svaki potez koji se igra na slobodno polje pri čemu to polje mora biti na dnu table ili neposredno iznad nekog zauzetog polja.
  • 45. 45 Princip funkcionisanja ove metode je sledeći: vraća se lista slobodnih polja u zadnjem redu matrice polja (koja reprezentuje tablu igre) zajedno sa svim slobodnim poljima iz ostalih redova, a ispod kojih se nalazi popunjeno polje. Implementacija metode je prikazana na listingu 30. Listing 30 Implementacija generatora poteza u igri “4 u nizu” Detekcija kraja igre implementirana je kao metoda table igre koja se poziva pre svakog poteza. Metoda funkcioniše tako što proverava dva parametra: - Da li ima praznih mesta na tabli, - Da li neki od igrača ima 4 vezane figure Ukoliko nema praznih mesta (nerešeno) ili neko od igrača ima 4 vezane figure (pobeda), igra ne može biti nastavljena (kraj igre). U tom trenutku, kreira se instanca klase GameOverDetails koja nosi podatke o pobedniku i kraju igre. Implementacija klase prikazana je na listingu 16. U implementaciji je korišćena bazična implementacija ove klase iz platforme, tako da ovde neće biti posebno objašnjavana (već je objašnjena u delu o univerzalnoj platformi). Detekcija kraja igre vrši se analizom cele tabele, liniju po liniju, kako bi se utvrdilo da li su zadovoljeni uslovi za prekid igre.
  • 46. 46 Metoda ToString ima praktičnu ulogu da na lak način vizuelizuje matricu tabele. Metoda Clone ima ulogu da napravi identičnu kopiju tabele. Atribut HashCode vraća heš kod tabele (radi lakog upisa u transpozicionu tabelu). 4.2.2. Logika igre (implementacija ITableGame) Ova klasa ima zadatak da upravlja smenom igrača, implementira pravila igre itd. Za potrebe igre “4 u nizu” implementiran je interfejs ITableGame u obliku klase 4inLineTableGame koja je prikazana na listingu 31. Listing 31 Implementacija ITableGame interfejsa za igru “4 u nizu” Značenje svakog pojedinačnog atributa objašenjeno je u delu koji opisuje ITableGame interfejs. Što se same implementacije tiče, smena igrača (implementirana u metodi NextPlayer) je naizmenična ( s obzirom na to da je ovo igra za dva igrača, lista igrača sadrži dve instance objekta IPlayer – bilo kojom od implementacija tog interfejsa) između dva igrača u listi. Pri dodavanju metode za obradu događaja kad je potez odabran, ta metoda prosleđuje se svakom od AI igrača u listi.
  • 47. 47 4.2.3. Transpoziciona tabela (implementacija ITransTable) Transpoziciona tabela implementirana je kao niz. Klasa u kojoj je implementacija izvršena je 4inLineTransTable (listing 32). Listing 32 Implementacija transpozicione tabele za potrebe igre “4 u nizu” Pristup transpozicionoj tabeli wrši se pomoću Linq izraza po ključu koji predstavlja heš vrednost tabele igre. Ovaj pristup nije najoptimalniji.
  • 48. 48 Transpoziciona tabela trebalo bi biti implementirana kao heš tabela i tako obezbediti brz direktan pristup ulazima u tabeli. Međutim, pristup sa korišćenjem Linq izraza i neograničenog niza ima upravo tu prednost što ima neograničen broj ulaza za razliku od heš tabele. Najbolje bi bilo implementirati kompromisno rešenje koje bi imalo direktan pristup, jednostavnu heš funkciju i neograničenu heš tabelu. 4.2.4. Evaluatori (implementacija IEvaluation) U implementaciji igre “4 u nizu” realizovane su tri metode evaluacije. Prva je osnovna metoda evaluacije. U njoj se u obzir uzimaju samo polja zauzeta od igrača za koga se evaluacija radi. Ukoliko se u čvoru (zapravo u tabeli koju taj čvor prectavlja) nađe 4 polja u nizu zauzeta od strane igrača (pobeda), to se evaluira kao +4. Ukoliko se nađu 4 polja u nizu zauzeta od strane protivnika (poraz), to se evaluira kao -4. Sve ostalo evaluira se kao 0. Ova metoda kasnije je izmenjena pa se ostali potezi evaluiraju kao maksimum svojih figurica u nizu u bilo kom pravcu. Maksimum i minimum su ostali +4 i -4, ali se pored vrednosti 0 mogu javiti i 1,2,3 i -1,-2 i -3. Na ovaj način postignuto je da ova funkcija evaluacije implementira “gramzivi algoritam”, jer teži da što više svojih figurica spoji u nizu. Druga metoda evaluacije nazvana je “Osnovna proširena”. Ona poseduje sve što i osnovna metoda sa dodatkom analize praznih polja na tabli. Naime, ova metoda ocenjuje i “potencijal” nekog poteza, odnosno mogućnost da on bude deo neke još neodigrane kombinacije. Poslednja je “Test” metoda koja poseduje sve što i prethodne dve sa dodatkom analize protivničkih pozicija u kontekstu trenutnog poteza, odnosno da li je i koliko protivnikovih kombinacija sprečeno tim potezom. Vezano za MinMax algoritam i evaluaciju treba reći da prvi potez (ko igra prvi) utiče na krajnji ishod igre. U tabeli 4 prikazani su rezultati testova uticaja prvog poteza. Prvi igra Evaluaciona metoda Plavi Crveni Pobeda Crveni Osnovna Osnovna Remi Crveni Proširena Osnovna Crveni Crveni Test Osnovna Remi Crveni Proširena Proširena Crveni Crveni Test Proširena Crveni Crveni Test Test Crveni Plavi Osnovna Osnovna Remi Plavi Proširena Proširena Plavi Plavi Test Test Plavi Tabela 4 Uticaj prednosti prvog poteza na krajnji ishod Iz tabele se može zaključiti da prednost prvog poteza nadmašuje prednost u heuristici. Kao što se iz tabele vidi, igrač koji igra drugi nikad ne uspe da pobedi uprkos prednosti u evaluacionim funkcijama. Što se ostalih parametara tiče, oni su identični. Oba igrača koristila
  • 49. 49 su TPL, Adaptivno produbljivanje, Alfa-Beta, Evaluacionu i Transpozicionu tabelu. Jedino što se menjalo tokom testova jeste evaluacija i ko igra prvi. Takođe treba napomenuti da su rezultati iz tabele uzeti iz više ponovljenih testiranja (zahvaljujući paralelizmu, program poseduje izvestan stepen mutacija, pa nema garancija da će redosled poteza uvek biti isti – misli se na poteze iste vrednosti). Logičkim upoređivanjem implementiranih evaluacionih metoda može se reći da su one u osnovi iste, jer koriste i osnovnu – gramzivu metodu kao svoju suštinu)ali da metode “Proširena” i “Test” imaju blaga poboljšanja zbog uzimanja više parametara u obzir pri ocenjivanju. 4.3. Implementacija korisničkog interfejsa igre 4.3.1. Konfiguracioni prozor Prvi ekran u aplikaciji jeste konfiguracioni prozor (slika 12). Slika 12 Konfiguracioni prozor Ovaj prozor ima svrhu da konfiguriše igru. Prvo se može podesiti tip i redosled igrača. Iz padajućih listi na vrhu prozora može se izabrati čovek ili ai za tip oba igrača. Zatim se može
  • 50. 50 za oba igrača odabrati evaluaciona funkcija (može se odabrati za svakog AI igrača). Zatim se može odabrati dubina stabla traženja i eventualno vremensko ograničenje u traženju. Vremensko ograničenje je dostupno samo ako se izabere “Inkrementalno povećanje dubine”. Zatim slede heuristički dodaci koje AI može koristiti pri pretrazi stabla traženja. Zadnja opcija koja može biti odabrana je TPL i ona nije heuristički dodatak već dozvoljava upotrebu TPL-a pri procesiranju (paralelizaciju). Konfiguracioni prozor smešten je u NewGame klasi. Listing 33 prikazuje način konfiguracije igrača. Listing 33 Konfiguracija AI igrača za igru Kao što se sa listinga može videti, svi parametri se sa grafičkog interfejsa prenose preko atributa klase IAIPlayer. Pri inicijalizaciji atributa koristi se naredba uslovne dodele radi preglednosti. Time je svaki atribut inicijalizovan jednom naredbom (i mahom u jednom redu). Za svakog od AI igrača potrebno je uraditi isto (ista sekvenca naredbi). 4.3.2. Situacije Ukoliko se želi testirati neka spcifična situacija (kako se program ponaša pod određenim uslovima), ili se jednostavno ne želi početi od prazne tabele, klikom na dugme “Situacija” na prozoru za konfiguraciju, otavara se novi prozor koji to omogućava. Taj prozor je prikazan na slici 13. Klikom na prazna polja na prozoru menja se status polja (crveni, plavi, prazni). Svaki klik menja status u navedenom redosledu – prvi klik crveno, drugi klik plavo, treći klik prazno. Klikom na dugme “Start” otvara se glavni prozor igre (tabla igre). Isto se dešava i u slučaju klika na dugme “Start” sa konfiguracionog prozora. Ovaj dodatak je idealan za testiranje evaluacionih funkcija i karakterističnih situacija.
  • 51. 51 Slika 13 Konfiguracija početnog stanja u partiji Na listingu 34 prikazan je princip startovanja igre sa ovog prozora (prikazan je način postavljanja početnog stanja tabele). Kao što se vidi sa listinga, najpre se inicijalizuje matrica igre (4inLineTable). Sva polja se postavljaju na vrednost “prazno” (empty). Zatim sledi deo koji sa korisničkog interfejsa proverava stanje svih polja i inicijalizuje tabelu igre na osnovu slike koja je učitana u polja na korisničkom interfejsu (plava, crvena, prazno). Taj deo je zbog svoje dužine na listingu prikazan skraćeno (označen sa “Table settings”). Nakon toga, inicijalizuje se statička instanca forme za igre (instanca je statička, jer se igra može pokrenuti sa dva mesta, sa forme za podešavanja i forme za situacije, a koristi se ista forma – na ovaj način odakle god da se igra startuje, koristi se ista instanca). Posle inicijalizacije forme za igru, ubacuju se figurice koje je korisnik definisao (na pozicijama koje je korisnik definisao) na formi za situacije. Pri ovome se koristi metoda InsertPownAtPosition, koja je ugrađena u kontroli 4inLine (instanca ove kontrole nalazi se na formi za igru).
  • 52. 52 Listing 34 Startovanja igre sa početnim stanjem 4.3.3. Glavni prozor Glavni prozor igre prikazan je na slici 14. Potezi se povlače naizmenično između dva igrača, počevši od onoga koji je na konfiguracionom prozoru odabran da igra prvi. Klikom na dugme “Konzola” otvara se dodatak u donjem delu prozora koji u realnom vremenu, odmah nakon povučenog poteza, prikazuje podatkke o tom potezu, i to: - Boju igrača – prvi parametar (može biti Red i Blue), - koordinate poteza – u kockastim zagradama, koordinate poteza na tabli za igru, - vrednost – numerička vrednost koju mu je dodelio evaluator (označen sa Val), - dubinu – dubina stabla na kome je potez odabran (označen sa D), - broj evaluiranih čvorova – broj evaluiranih čvorova stabla pri traženju (označen sa TN), - vreme – vreme koje je bilo potrebno da se potez odabere (označen sa T),
  • 53. 53 - broj pogodaka u transpozicionu – broj pogodaka u transpozicionu tabelu (označen sa TTg), - broj promašaja u transpozicionu – broj promašaja u transpozicionu tabelu (označen sa TTm). Slika 14 Glavni prozor igre Potezi u igri se povlače klikom bilo gde na prozoru kada se figurica pozicionira na željeno mesto. Pomeranje figurice vrši se pomeranjem miša. Najpre se figurica pozicionira po X osi, pomeranjem miša, a zatim se nakon klika miša figurica sama spušta do prvog slobodnog mesta.
  • 54. 54 Listing 35 prikazuje konstruktor glavnog prozora igre. Kao parametri konstruktora prosleđuje se objekat ITableGame zatim referenca na Log formu i na kraju eventualno tabela igre. Tabla igre se prosleđuje samo u slučaju da igra počinje sa forme “Situacija”. Listing 35 Konstruktor glavnog prozora U konstrukoru se definiše funkcija za dodavanje poteza u log prozir. S obzirom na to da se potezi biraju asinhrono – nezavisno od korisničkog interfejsa, neophodna je specifična tehnika za prenos rezultata tog događaja na korisnički interfejs. Naime, kako bi grafički korisnički interfejs ostao upotrebljiv u toku procesa odabira poteza od strane AI (s obzirom na to da taj proces dugo traje i upotrebljava značajne resurse računara) neophodno je da se proces traženja poteza pokrene u zasebnoj niti, različitoj od one na kojoj radi korisnički interfejs. Konkretan princip pokretanja traženja na zasebnoj niti biće objašnjen kasnije. Međutim, i ako ova tehnika omogućava da korisnički interfejs ostane potpuno neblokiran u toku traženja poteza, ona ima i jedan dodatni zahtev. Rezultati obrade koji se dobiju u toj odvojenoj niti (u ovom slučaju potez koji je pronađen) ne mogu biti direktno preneti na interfejs već se mora pozvati specijalna metoda koja će ažurirati korisnički interfejs. To je metoda BeginInvoke koju ima svaka grafička kontrola na window formama. Kao što se iz listinga vidi poziv ove metode je uslovan, zavisi od atributa InvokeRequired koju postavlja sama forma. Naime, ukoliko forma još uvek nije prikazana, nema potrebe za pozivom metode BeginInvoke, u suprotnom, neophodno je. Zavisno od atributa InvokeRequired, metoda DrawTree poziva se uz pomoć BeginInvoke metode ili bez nje.
  • 55. 55 Poslednja naredba iz listinga dodaje 4inLine kontrolu na formu. Celokupna logika igre se nalazi u ovoj kontroli. Listing 36 Način dodavanja reda u log Na listingu 36 prikazan je način logovanja odabranog poteza. Potez se loguje na dva načina. Loguju se generalni podaci o potezu u tekstualno polje na samom glavnom prozoru kao i na log prozoru, gde se pored ovih generalnih podataka o potezu, loguje i celokupno stablo traženja. Na listingu 37 prikazan je konstruktor drugog dela glavnog prozora – kontrola igre, 4inLine. Kao parametri konstruktora prosleđuju se instance ITableGame i ITable. U konstruktoru se najpre vrši inicijalizacija tabele igre, a zatim se dodaju metode za upravljanje odabranim potezom (kada AI signalizira da je potez odabran). Po kreiranju igre, na tablu se ubacuje prva figurica. Kako bi se figurica ubacila, neophodno je da se kreira kontrolni poenter (pokazivač) na ovu formu od strane operativnog sistema. Za to je iskorišćen događaj HandleCreated koji signalizira sama forma.
  • 56. 56 Listing 37 Konstruktor klase 4inLine – kontrola igre Metoda InsertPownAtPosition ubacuje jednu figuricu na koordinate koje se prosleđuju kao parametri funkcije pri pozivu. Boja figurice koju treba ubaciti takođe se prosleđuje kao parametar. Metoda kreira novu instancu klase PictureBox koja se nalazi u skupu standardnih windows form kontrola, podešava mu visinu i širina na visinu i širinu figurice. Nakon toga se toj kontroli dodeljuje sličica (crvena ili plava). Nakon svega ovoga, kontrola se dodaje na formu. Sama metoda je prikazana na listingu 38.
  • 57. 57 Listing 38 Metoda za ubacivanje figurice na određenu poziciju bez animacije Na listingu 39 prikazana je metoda InsertPown_Job koja se razlikuje od metode InsertPownAtPosition samo po tome što se ne prosleđuju obe koordinate poteza i što se sama figurica dodaje na tablu igre animirano. Pri ubacivanju nove figurice se najpre proveri da li igra može biti nastavljena (poziv metodi IsGameOver klase ITable). Nakon ovoga, sledi deo koji je identičan kao u prethodnoj metodi. Nakon ubacivanja figurice na tablu, sledi deo koji inicijalizuje proces traženja, u slučaju da je trenutni igrač AI. Inicijalizacija procesa traženja vrši se u zasebnoj niti (kako ne bi blokirao korisnički interfejs). Najpre se kreira nova nit i toj niti se dodeli metoda koju će ta nit izvršavati, a to je metoda Play. Nakon toga nit se pokreće.
  • 58. 58 Listing 39 Metoda za ubacivanje figurice na tablu i pokreće AI
  • 59. 59 Listing 40 Metode koje pozicioniraju figuricu po X osi kada AI odabere potez Na listingu 40 prikazane su metode koje inicijalizuju animirano ubacivanje figurice na tablu igre. Metoda DoMove_Job pozicionira figuricu po X osi na lokaciju koju odabere AI igrač, a zatim inicijalizuje sat (tajmer) koji vrši pomeranje figurice po Y osi do željene pozicije. Kontrolna promenljiva isDragable omogućava/zabranjuje pomeranje trenutne figurice po X osi pomeranjem kursora miša (ovo se koristi da spreči korisnika-čoveka da pomera figuricu dok AI igra). Kontrolna promenljiva isMoving signalizira da li se figurica već pomera. Promenljiva dA predstavlja interval sata (tajmera) odnosno frekvenciju pozivanja metode timer1_Tick (prikazana na listingu 41) u milisekundama. Atribut Enabled predstavlja kontrolnu promenljivu sata, koja ga aktivira/deaktivira.
  • 60. 60 Listing 41 Metoda sata (tajmera) koja animira kretanje figurice pri ubacivanju Metoda timer1_Tick vrši pomeranje figurice. Svaki poziv ove metode pomera figuricu moving za određeni broj piksela po Y osi. Kada se uslov dostigne (figurica se postavi na prvo slobodno mesto) promenljive se resetuju. Promenljiva current čuva referencu na trenutnu figuricu, onu koja se pomera po horizontali sa pomeranjem miša. Moving je promenljiva koja čuva referencu na onu figuricu koja se spušta po Y osi. Po završetku spuštanja figure, na tablu se ubacuje nova figurica. Na listingu 42 prikazana je metoda MarkWinner.
  • 61. 61 Listing 42 Metoda koja markira pobednički niz na tabli Ova metoda markira pobednički niz kada partija bude završena. Markiranje se vrši polje po polje, za sve figurice u nizu. 4.3.4. Log Klikom na dugme “Stablo” na glavnom prozoru prikazuje se kontrolni prozor koji loguje kontrolne podatke o svakom potezu kao i kompletno stablo traženja. Izgled prozora prikazan je na slici 15.
  • 62. 62 Slika 15 Izgled kontrolnog prozora koji loguje poteze oba igrača Na slici 16 prikazan je izgled stabla onako kako se ono predstavlja na kontrolnom prozoru. U korenu stabla je odabrani potez. Takođe, tu su i kontrolni podaci koji se štampaju u konzoli. Iz korena stabla dalje se grana kompletno stablo. Sam prozor podeljen je na dva dela, po jedan deo za svakog od igrača. Na levoj strani je uvek igrač koji igra prvi, a na desnoj onaj koji igra drugi. Nakon svakog odigranog poteza, potez se loguje dodavanjem čvora na odgovarajuću listu (levu ili desnu, zavisno od igrača).
  • 63. 63 Slika 16 Grafički prikaz stabla traženja i odabranog poteza Pregled celog stabla je izuzetno pogodan pri debagiranju i testiranju aplikacije. Može se propratiti celo stablo traženja kao i MinMax algoritam (vrednost svakog čvora). Za grafičko predstavljanje stabla iskorišćena je standardna windows forms kontrola TreeView koja omogućava grafičku reprezentaciju rekurzivnih struktura. U kontrolu se pozivom metode Add dodaju objekti tipa TreeNode, a koji i sami mogu imati svoje TreeNode-ove kao potomke. Ova struktura je identična TreeNode strukturi iz aplikacije što se uređenja tiče i omogućavaju lako formiranje stabla.
  • 64. 64 5.Zaključak Ovaj projekat trebalo je da pokaže način upotrebe algoritama veštačke inteligencije u realizaciji logičke igre “4 u nizu”. Mogućnosti za proširenje (nadogradnju) su velike. Najviše prostora za poboljšanje ima u implementaciji samog stabla traženja. Poboljšanje mehanizma za generisanje stabla može značajno povećati performanse aplikacije. Takođe, prostora za poboljšanje ima i u realizaciji paralelizma u aplikaciji, odnosno generički mehanizam koji je direktno preuzet iz Microsoft .net frameworka 4.0 nije najoptimalnije moguće rešenje. Bolje performanse aplikacije mogle bi se postići uz pažljivu implementaciju paralelizma na nižem nivou kodiranja. Evaluacione funkcije takođe mogu biti poboljšane i time poboljšati rezultate pretrage. Međutim, možda najznačajnija stvar koja bi povećala kvalitet programa (pa i performanse) jeste pondering, odnosno korišćenje protivnikovog vremena za razmišljanje u svoju korist. Trenutna implementacija aplikacije čeka da protivnik povuče potez, pa tek onda pokreće mehanizam traženja što je prilično veliko gubljenje vremena. U realnim uslovima, kada čovek igra logičku igru, on razmišlja konstantno tokom celog toka igre, bez obzira na to ko je na potezu, a kada protivnik povuče potez, samo se koriguje odluka, ukoliko ima potrebe. Tako nešto moguće je implementirati i u AI sistemu, korišćenjem transpozicionih tabela. Poundering može lepo da se iskoristi kod iznuđenih poteza. Poundering zapravo predstavlja jedan nivo više u stablu traženja, ali kod iznuđenih poteza to nema, jer se zna da će protivnik da odigra tu, te nema potrebe za zaustavljanjem pretrage. Nešto što smatram kvalitetom ovog sistema jeste modularnost. S obzirom na to da su bazne klase i interfejsi generički pisani sa ciljem da budu primenljivi na što veći opseg igara i varijacija, veoma lako se može postojeća implementacija proširiti da podržava, npr. tri igrača umesto dva ili da podržava tabelu 7x7 umesto 6x7. Takođe, moguće je implementirati i potpuno drugačije igre uz potpuno očuvanje baznih klasa i interfejsa, a uz potrebu da se promeni samo logika igre, odnosno implementacija apstraktnih klasa, interfejsa, itd. Jedna od ideja pri razvoju ove aplikacije bila je da se razvije i platforma koja će biti sposobna da podrži ceo spektar tabelarnih igara i mislim da je taj cilj ostvaren. Sama realizacija logičke igre “4 u nizu” postiže solidne rezultate pri testiranju tako da je cilj i u tom pogledu ostvaren. Upotrebljeni su svi algoritmi i tehnike veštačke inteligencije koje je bilo moguće realizovati u ograničenom vremenskom roku koje je bilo na raspolaganju za ovaj rad. Primenjeni algoritmi su detaljno opisani, kao i svrha njihove primene. Za svaki algoritam koji je korišćen u aplikaciji prikazana je i realizacija u kodu.
  • 65. 65 6.Literatura 1. Fudenberg, D. and Tirole, J. Game Theory. MIT Press, Boston, MA, 1995. 2. Adelson-Velskiy, G.M, Arlazarov, V.L. and Donskoy, M.V. Algorithms for Games. Springer-Verlag, New York, NY. ISBN 3-540-96629-3, 1988. 3. Vladan Vučković, "Prilog teoriji i praksi naprednih šahovskih algoritama", doktorska disertacija, Elektronski fakultet u Nišu, 2006. 4. Petar Rajković, Владан Вучковић, “Основни елементи хеуристичке евалуационе функције”, Зборник радова са 52. Конференције ЕТРАН-а, CD ROM Proceedings, Секција Вештачка интелигенција, рад VI2.4, Палић, Србија, 8-12. јуни 2008, (ISBN 978-86-80509-63-1) (M63) 5. Владан Вучковић, “Специјални елементи евалуационе функције”, Зборник радова са 53. Конференције ЕТРАН-а, CD ROM Proceedings, Секција Вештачка интелигенција, рад VI1.3, Vrnjačka Banja, Србија, 15 – 18. juna 2009. (ISBN 978-86- 80509-64-8) (M63)
  • 66. 66 7.Lista slika Slika 1 Izgled table za igranje u igri “4 u nizu”. Strana 7. Slika 2 Struktura podataka – Stablo. Strana 9. Slika 3 Stablo igre. Strana 10. Slika 4 Algoritam MinMax – igra “Iks-Oks”. Strana 11. Slika 5 Pogrešan potez zbog nesavršenosti u funkciji evaluacije. Strana 12. Slika 6 Primer Alfa-Beta odsecanja. Strana 13. Slika 7 Alfa-Beta odsecanje – objašnjenje. Strana 14. Slika 8 Vrednosti polja u evaluacionoj tabeli za igru „4 u nizu“. Strana 15. Slika 9 Primer situacije u kojima primena transpozicione tabele donosi korist. Strana 15. Slika 10 Uporedni grafički prikaz zavisnosti vremena izvršenja od dubine. Strana 36. Slika 11 Izgled greške pri velikom broju taskova / niti. Strana 41. Slika 12 Konfiguracioni prozor. Strana 48. Slika 13 Konfiguracija početnog stanja u partiji. Strana 50. Slika 14 Glavni prozor igre. Strana 52. Slika 15 Izgled kontrolnog prozora koji loguje poteze oba igrača. Strana 61. Slika 16 Grafički prikaz stabla traženja i odabranog poteza. Strana 62.
  • 67. 67 8.Lista tabela Tabela 1 Matrica ispravnosti za igru „4 u nizu“. Strana 6. Tabela 2 Uticaj paralelizma na vreme izvršenja. Strana 35. Tabela 3 PC konfiguracija na kojoj je izvršeno testiranje. Strana 36. Tabela 4 Uticaj prednosti prvog poteza na krajnji ishod. Strana 47.