Tietokoneshakki Kari Timonen kari.timonen@cs.helsinki.fi Tekoäly kortti- ja lautapeleissä Helsingin yliopisto, tietojenkäsittelytieteen laitos Raportti C 2008 16, s. 74 85, joulukuu 2008 Tiivistelmä Tässä seminaarityössä selvitetään kuinka tekoäly toimii shakkipelissä. Seminaarityössä esitellään 64-bittinen pelilaudan esitystapa, usein käytetyt menetelmät pelitilanteen hyvyyden arvioimiseen ja pelipuun hakualgoritmi. Pelipuun hakualgoritmina esitellään minmax-algoritmi ja sen nopeuttamiseen käytettävät alpha-beta-karsinta, sekä transpositiotaulukko. Lisäksi esitellään kuinka tekoälyn toimintaa voidaan tehostaa alku- ja loppupelissä tietokantojen avulla. 74
Sisältö 1 Johdanto 76 2 Säännöt 76 2.1 Pelinappulat ja siirrot.............................. 77 2.2 Pelivaiheet..................................... 77 3 Siirtojen generointi ja pelitilanteiden tallennus 78 4 Pelitilanteen arviointi 79 5 Pelipuu 80 5.1 Minmax-algoritmi................................. 81 5.2 Alpha-beta-karsinta................................ 82 5.3 Transpositiotaulukko............................... 83 6 Alku- ja loppupelien tietokannat 83 7 Yhteenveto 84 75
1 Johdanto Shakki on lautapeli, jossa kaksi pelaajaa siirtävät vuoronperään nappuloitaan. Molemmilla pelaajilla on käytössä 16 nappulaa. Pelin tavoitteena on saada vastustajan kuningas hyökkäyksen kohteeksi niin, että vastustajalla ei ole käytössä yhtään laillista siirtoa. Shakki on ominaisuuksiltaan hyvin erilainen peli, kuin esimerkiksi pokeri. Shakissa kaikki mahdolliset siirrot ovat molempien pelaajien nähtävissä, kun taas pokerissa ei tiedetä mitä kortteja toisilla pelaajilla ja korttipakassa on. Shakin tekoälyn kehittämisestä ollaan oltu kiinnostuneita vuodesta 1770 lähtien [Wel84]. Ensimmäinen tunnettu tekoälyvastustaja, The Turk, oli huijaus, jossa kaapin päällä oli shakkilauta ja kaapin sisällä oli ihminen, joka hallinnoi oletetun tekoälyvastustajan peliä. Ensimmäisen toimivan shakkiohjelman kirjoitti Alan Turing vuonna 1951. Turingin kirjoittamaa ohjelmaa simuloitiin ainoastaan käsin ja simuloinnista selvisi, että ohjelma ei ollut taitava pelaaja [Wel84]. Vuonna 1996, IBM:n kehittämä Deep Blue -shakkitietokone voitti ensimmäisen kerran hallitsevan shakin maailmanmestarin, Garry Kasparovin [Hsu99]. Ensimmäisten shakkiohjelmien julkaisuhetkellä suuri ongelma tekoälyn kehittämisen kannalta oli tietokoneiden laskentatehon puute. Shakkiohjelma koostuu usein siirtojen generoinnista, pelitilanteen arvioinnista ja pelipuun läpikäynnistä. Kun shakkiohjelma laskee itselleen seuraavan siirron, se luo ensin listan sallituista siirroista. Jokainen sallittu siirto johtaa tiettyyn pelitilanteeseen, joka arvioidaan ja arvion perusteella pelitilanne saa tietyn määrän pisteitä. Pelin eri tilanteista voi rakentaa pelipuun niin, että juurisolmuksi valitaan lähtötilanne ja lapsisolmuiksi ne pelitilanteet joihin päästään käyttämällä sallittuja siirtoja. Tietokone valitsee seuraavaksi siirrokseen sen siirron, joka johtaa suurimpaan pistemäärän. Tässä seminaarityössä selvitetään, kuinka shakin tekoäly toimii. Seminaarityön alussa esitellään shakin säännöt. Säännöissä ei huomioida useita erikoissiirtoja, kuten tornitusta, jossa kuningasta siirretään kaksi ruutua oikealle, tai vasemmalle ja tornia siirretään kuninkaan yli sen vieressä olevaan ruutuun. Seuraavaksi esitellään, kuinka eri pelitilanteet tallennetaan tietokoneen muistiin, kuinka pelitilanne arvioidaan ja kuinka pelipuu rakennetaan, sekä käydään läpi. Pelitilanteiden muistiin tallentamiseen käytettävistä menetelmistä esitellään 64-bittinen bittikarttamalli. Pelipuun rakentamis- ja läpikäyntimenetelmistä esitellään minmax-algoritmi. Lisäksi esitellään, kuinka minmax-algoritmin toimintaa voidaan nopeuttaa alpha-beta-karsinnalla ja transpositiotaulukoilla. Seminaarityön loppuosassa esitellään alku- ja loppupeliin soveltuvat tietokannat. 2 Säännöt Shakkia pelataan 64 ruudun muodostamalla 8 x 8 kokoisella ruudukolla. Ruudut ovat vuorotellen mustia ja valkoisia siten, ettei samanvärisiä ruutuja ole vierekkäin. Lauta asetetaan niin, että pelaajasta katsottuna oikealla alhaalla on aina valkoinen ruutu. Peliä pelaa kaksi pelaajaa, joista toinen pelaa valkeilla ja toinen mustilla nappuloilla [Wik08b]. Valkeilla nappuloilla pelaava aloittaa aina pelin. Pelaajat siirtävät vuorotellen aina yhtä omaa nappulaansa. Nappulan voi siirtää joko tyhjään ruutuun, tai ruutuun, jossa on vastustajan nappula. Siirrettäessä nappula vastustajan nappulan varaamaan ruutuun tulee vastustajan nappula lyödyksi ja se poistetaan laudalta. Näin ollen ei samassa ruudussa voi olla kahta nappulaa samanaikaisesti. Nappulat eivät voi hyppiä toisten yli ratsua lukuun ottamatta [Wik08b]. 76
Pelin tavoitteena on saada vastustajan kuningas hyökkäyksen kohteeksi niin, että vastustajalla ei ole yhtään laillista siirtoa. Tällaista tilannetta kutsutaan shakkimatiksi. Shakkimattiin johtaneen siirron tehnyt pelaaja voittaa pelin. Pelaaja ei saa jättää kuningastaan hyökkäyksen kohteeksi, tai liikuttaa nappuloitaan niin, että kuningas joutuu hyökkäyksen kohteeksi. Jos kumpikaan pelaaja ei voi tehdä shakkimattia, peli päättyy tasapeliin, eli pattitilanteeseen. 2.1 Pelinappulat ja siirrot Pelin alussa molemmat pelaajat saavat käyttöönsä 16 nappulaa. Nappulat ovat seuraavat: Kahdeksan sotilasta. Kaksi tornia. Kaksi ratsua. Kaksi lähettiä. Yksi kuningatar. Yksi kuningas. Pelin alussa nappulat asetetaan laudalle siten, että kummastakin pelaajasta nähden toiselle riville sijoitetaan kaikki sotilaat riviin. Jos laudan laidoille on merkitty kirjaimet ja numerot, niin mustat sotilaat tulevat riville seitsemän ja valkeat riville kaksi. Korkeampiarvoiset nappulat sijoitetaan vapaalle riville, joka on lähinnä pelaajaa. Molemmilla pelaajilla tornit ovat molemmilla puolilla kaikkein uloimpana, niiden vieressä ratsu, sitten lähetti ja keskellä kuningas ja kuningatar. Kuningas ja kuningatar asetetaan paikoilleen niin, että molemmat kuningattaret ovat D-pystyrivillä ja kuninkaat kuningattariensa vieressä [Wik08b]. Kuvassa 1 esitellään aloitustilanne. Nappulat eivät voi hyppiä toistensa yli, ratsua lukuun ottamatta. Sotilas liikkuu yhden ruudun suoraan eteenpäin. Aloituksessa sotilasta voi liikuttaa halutessaan kaksi ruutua eteenpäin, mikäli molemmat ruudut ovat tyhjiä. Sotilas hyökkää vain etuviistoon, jolloin sotilas lyö kyseisessä ruudussa olevan vastustajan nappulan. Torni liikkuu mihin tahansa samalla rivillä, tai sarakkeella olevaan ruutuun. Ratsu liikkuu ensin kaksi ruutua suoraan ylös, alas, vasemmalle tai oikealle ja sitten yksi ruutu jommallekummalle sivulle [Wik08b]. Lähetti liikkuu mihin tahansa samalla viistorivillä olevaan ruutuun. Kuningatar liikkuu mihin tahansa samalla rivillä, sarakkeella, tai viistorivillä olevaan ruutuun. Kuningas liikkuu yhden ruudun ylös, alas, vasemmalle, oikealle, tai viistoon. Kuningas on shakissa, jos se on jonkin vastustajan nappulan uhkaama. 2.2 Pelivaiheet Shakki voidaan jakaa kolmeen eri pelivaiheeseen: avaukseen, keskipeliin ja loppupeliin. Avauksella tarkoitetaan pelin alussa tehtäviä siirtoja. Yleensä pelin avausvaiheen katsotaan jatkuvan kunnes jompikumpi pelaajista siirtää tavalla, joka poikkeaa siitä, mitä tunnetuissa avausteorioissa suositellaan [Wik08b]. Keskipelissä pelaajat yrittävät lyödä toistensa nappuloita ja saavuttaa strategisen aseman loppupeliä varten. Loppupeli on shakin viimeinen pelivaihe, jolloin pelilaudalla ei ole enää montaa nappulaa. Raja keskipelin ja loppupelin välillä on usein häilyvä. Yhtenä selkeänä erona keskipelin ja loppupelin välillä voidaan pitää sitä, että loppupelissä kuninkaan ja sotilaiden osuus pelissä on merkittävämpi, eikä välitöntä mattihyökkäyksen vaaraa useinkaan ole [Wik08b]. 77
Kuva 1: Aloitustilanne [Wik08b]. 3 Siirtojen generointi ja pelitilanteiden tallennus Tietokone tarvitsee siirtojen generointia varten tietorakenteen, jonka avulla voidaan esittää eri pelitilanteet. Pelitilanne tarkoittaa nappuloiden sijaintia pelilaudalla ja kumman pelaajan vuoro on siirtää nappulaa. Usein käytetty tapa esittää pelitilanne on bittikarttoina 64- bittisten muuttujien avulla. 64-bittiset muuttujat soveltuvat shakkilaudan esittämiseen hyvin, koska shakkilaudan koko on 8 x 8 = 64, eli jokaisella bitillä voi esittää yhden ruudun. Esimerkiksi sotilaiden sijaintia vastaavien ruutujen numeroiden kohdalta bitit asetetaan ykkösiksi, muissa ruuduissa bitit ovat nollia. Shakkilauta ja kaikki shakkilaudalla olevat nappulat esitetään kahdentoista 64-bittisen muuttujan listana [Wel84]. Yhden pelaajan nappulat esitetään kuuden muuttujan listassa, joista jokaisessa solmussa oleva muuttuja sisältää 64-bittisen bittikartan. Jokainen bittikartta sisältää yhden nappulan (sotilaiden, tornien, ratsujen, lähettien, kuningattaren, tai kuninkaan) eri ilmentymien sijainnit pelilaudalla [Hya04]. Kuvassa kaksi esitellään shakkilauta kahdentoista 64-bittisen muuttujan avulla. 64-bittiset bittikartat ovat tehokkaita siirtojen generoimiseen, koska tietokoneella voidaan suorittaa loogisia operaatiota (AND, OR, NOT) bittikarttojen välillä. Esimerkiksi mustan ratsun sallittujen siirtojen selvittämiseksi luodaan ensin bittikartta kaikista mustan ratsun mahdollisista siirroista. Seuraavaksi luodaan bittikartta kaikista pelaajan nappuloista, vertaamalla kaikkia kuutta bittikarttaa OR-operaatiolla. Saadusta bittikartasta otetaan komplementti (NOT) ja verrataan komplementin tuloksena saatua bittikarttaa mustan ratsun mahdolliset siirrot sisältävään bittikarttaan AND-operaatiolla. Saatu bittikartta sisältää kaikki mustan ratsun sallitut siirrot [Suh05]. Bittikartat ovat tehokkaita siirtojen generoimiseen, mutta niiden käyttäminen on monimutkaista ja tilantarpeeltaan vaativaa. Yhden siirron generointia varten tulee tallentaa useita bittikarttoja. Lisäksi pelitilanteet halutaan mahdollisesti tallentaa, esimerkiksi transpositiotaulukkoon. Transpositiotaulukkoa käytetään nopeuttamaan shakkiohjelman toimintaa, katso luku 5.3 Transpositiotaulukko. 78
Kuva 2: Shakkilaudan esittäminen bittikarttojen avulla [Wel84]. 4 Pelitilanteen arviointi Kun tietokone liikuttaa nappulaa pelilaudalla, tietokone ei tiedä onko siirto hyvä, vai huono. Tietokone tarvitsee pelitilanteen arviointia varten avukseen funktion, joka kertoo pelitilanteen hyvyyden. Pelitilanteen hyvyyttä mittaavaa funktiota kutsutaan arviointifunktioksi (evaluation function) [Wel84]. Arviointifunktio palauttaa kokonaisluvun, joka mittaa pelitilanteen hyvyyttä. Yksinkertaisimmillaan arviointifunktio voi palauttaa arvon 1, jos tietokone voittaa, arvon 0, jos peli päättyy tasapeliin ja arvon -1, jos tietokone häviää. Shakkiohjelman laatu riippuu paljon arviointifunktion tarkkuudesta, koska huono arviointifunktio voi ohjata peliä huonoon tulokseen. Pelilaudalla vallitsevaa tilannetta voidaan mitata useilla eri tavoilla. Arviointifunktio mittaa pelitilannetta usein materiaalin (material), liikkuvuuden (mobility), asetelman kehityksen (development) ja kuninkaan suojaamisen (king safety) avulla [Lar00, Wel84]. Materiaalia mitataan nappuloiden määrän avulla. Jokaiselle erityyppiselle nappulalle annetaan jokin arvo, lasketaan molempien pelaajien nappuloiden arvot yhteen ja vähennetään toisistaan. Suuremman materiaalisen tuloksen omaava pelaaja on materiaalin kannalta paremmassa asemassa. Liikkuvuudella mitataan kuinka paljon siirtoja pelaajalla on käytettävissä tietyssä pelitilanteessa. Shakkimattitilanteessa pelaajalla ei ole yhtään siirtoa käytettävissä, joten liikkuvuutta voidaan käyttää yhtenä mittarina [Lar00]. Osa siirroista on usein kuitenkin täysin hyödyttömiä. Liikkuvuuden mittaamisessa lasketaan pelaajalla käytössä olevat siirrot. Se pelaaja, jolla on käytössään enemmän siirtoja on liikkuvuuden kannalta paremmassa asemassa. 79
Pelitilanteen kehittämisessä mitataan kuinka pelaaja on liikuttanut nappuloitaan. Esimerkiksi sotilaat, ratsut ja lähetit on hyvä siirtää ennen torneja ja kuningatarta, tukemaan tornien ja kuningattaren hyökkäyksiä. Sotilaiden liikuttaminen antaa lisäksi tilaa tornien ja kuningattaren liikuttamiseen. Pelitilanteen kehityksen mittaamisessa voidaan esimerkiksi rangaista pelaajaa, jos pelaaja ei ole liikuttanut sotilaita, ratsuja ja lähettejä. Pelitilanteen kehittämisen painoarvo on suurempi pelin alkuvaiheessa ja vähenee pelin edetessä. Esimerkiksi kymmenen siirron jälkeen sotilaat, ratsut ja lähetit on jo siirretty ja pelin kehitys on mitattu [Lar00]. Kuninkaan suojaamista mitataan pelin alku- ja keskivaiheissa. Loppupelissä kuninkaan suojaamisella ei ole väliä, jos molemmilla pelaajilla on vähän nappuloita, jolloin kuningasta käytetään hyökkäämiseen. Kuninkaan suojaamista voidaan mitata esimerkiksi tornituksella (castling), jossa kuningasta siirretään kaksi ruutua oikealle, tai vasemmalle ja tornia siirretään kuninkaan yli sen vieressä olevaan ruutuun [Lar00, Wel84]. Mikäli tornitus on tehty, arviointifunktio antaa tornituksesta tietyn määrän pisteitä. Arviointifunktio antaa pelitilanteen hyvyydelle arvon materiaalista, liikkuvuudesta, asetelman kehityksestä ja kuninkaan suojaamisesta saatujen tulosten perusteella. Oikeiden painoarvojen löytäminen eri ominaisuuksien välille on vaikeaa. Lisäksi pelin eri vaiheissa toiset mittarit ovat toisia parempia. Materiaalin ja liikkuvuuden mittaaminen sopii kaikkiin pelivaiheisiin. Pelitilanteen kehittämisen mittaaminen sopii hyvin alku- ja keskipeliin, mutta ei loppupeliin. Myös kuninkaan suojaus sopii hyvin alku- ja keskipeliin, mutta ei loppupeliin. 5 Pelipuu Tietokone voi arvioida seuraavan siirron hyvyyttä esimerkiksi arviointifunktion avulla, joka mittaa pelitilanteen hyvyyttä. Arviointifunktio tosin antaa hyvyyden vain yhdelle pelitilanteelle, eikä näe, mikä tilanne voi olla kahden siirron jälkeen. Arviointifunktio voi esimerkiksi antaa hyvän tuloksen vastustajan kuningattaren lyömisestä, mutta mitä jos vastapelaaja voi oman kuningattaren uhraamalla tehdä seuraavalla siirrolla shakkimatin? Tällaista tilannetta kutsutaan horisontaaliseksi seuraukseksi (horizontal effect) [Wal97, Wel84]. Kahden pelaajan mahdollisista siirroista voi luoda pelipuun (game tree). Pelipuu luodaan siten, että aloitustilanne asetetaan juurisolmuksi ja lapsisolmuiksi laitetaan kaikki ne pelitilanteet, joihin päästään pelaajan tehtyä yhden sallitun siirron. Lapsisolmuille laitetaan edelleen lapsisolmuiksi vastapelaajan kaikki sallitut siirrot. Lapsisolmujen lisäämistä jatketaan rekursiivisesti, kunnes kaikissa haaroissa tullaan lopputiloihin. Tällöin pelipuu sisältää kaikki mahdolliset siirrot. Pelitilanne voidaan arvioida jokaisessa solmussa ja arvion perusteella voidaan valita se siirto, joka johtaa parhaaseen lopputilaan. Yhdellä siirtovuorolla on noin 35 erilaista siirtomahdollisuutta ja yksi peli kestää noin 50 siirtovuoroa, eli 100 siirtoa. [Wel84]. Pelipuun läpikäytäviä haaroja olisi tällöin 35 100. Nykyisillä tietokoneilla ei voida käydä läpi koko pelipuuta kerralla aika- ja tilavaativuuden takia. Pelipuun hakusyvyys voidaan katkaista tiettyyn määrään siirtoja, esimerkiksi kahdeksaan siirtoon. Tällöin läpikäytäviä haaroja on 35 8 = 2251875390625. Pelipuun luontiin ja läpikäyntiin käytetään usein minmax-algoritmia. Minmax-algoritmin toimintaa voidaan nopeuttaa esimerkiksi alpha-beta-karsinnalla ja transpositiotaulukoilla. 80
5.1 Minmax-algoritmi Pelipuu voidaan luoda ja läpikäydä esimerkiksi minmax-algoritmin avulla. Minmax-algoritmin toiminta perustuu siihen, että se käy rekursiivisesti läpi tiettyyn hakusyvyyteen asti kaikki mahdolliset siirrot ja valitsee parhaan mahdollisen siirron siirtovuorossa olevalle pelaajalle. Pelitilanteen hyvyys arvioidaan jokaisessa pelitilanteessa kokonaisluvulla. Valkoisilla nappuloilla pelaavalle pelaajalle hyviä pelitilanteita ovat positiiviset kokonaisluvut, suurempien kokonaislukujen tulkitaan esittävän parempia siirtoja. Mustilla nappuloilla pelaavalle pelaajalle hyviä pelitilanteita ovat vastaavasti negatiiviset kokonaisluvut. Tasapelitilanteessa minmax-algoritmi palauttaa arvon 0. Kuvissa 3 ja 4 esitellään minmax-algoritmin toimintaa ristinollapelissä, koska ristinolla on yksinkertaisempi peli kuin shakki. Minmax-algoritmi toimii vastaavalla tavalla shakissa. Ristinollaa pelataan yhdeksän ruudun muodostamalla 3 x 3 kokoisella ruudukolla. Peliä pelaa kaksi pelaajaa, joista toinen pelaa ristimerkeillä ja toinen nollamerkeillä. Pelaajat asettavat merkkinsä ruudukkoon vuoron perään. Pelin tavoitteena on saada kolme omaa merkkiä samalle pysty-, vaaka-, tai vinoriville. Kuvassa 3 esitellään minmax-algoritmin toiminta ristinollapelissä. Kuvassa 3 on ristin vuoro tehdä siirto. Pelipuuhun on kirjattu kaikki ristin siirrot, nollan vastasiirrot ja loppupelit näistä siirtopareista eteenpäin [LuN05]. Ristin voittoa merkitään kuvassa 3 numerolla 1, tasapeliä numerolla 0 ja nollan voittoa numerolla -1. Pelipuuta lähdetään arvioimaan lehdistä juureen. Kun on ristin vuoro siirtää, valitaan se siirto, joka johtaa ristille parhaaseen mahdolliseen pelitilanteeseen. Kun on nollan vuoro siirtää, valitaan vastaavasti se siirto, joka johtaa nollalle parhaaseen mahdolliseen pelitilanteeseen. Ristin siirrot ovat ns. max-siirtoja ja nollaan siirrot min-siirtoja. Kuva 3: Minmax-algoritmin toiminta ristinollapelissä [LuN05]. Kuvassa 4 esitellään esimerkki min- ja max-funktioista ristinollapelissä, jossa risti(v) kuvaa max-funktiota ja nolla(v) kuvaa min-funktiota. Aluksi kutsutaan risti-funktiota, joka saa arvokseen nykyisen pelitilanteen muuttujassa v. Rivillä 1 tutkitaan onko peli ohi. Jos risti voitti, palautetaan arvo 1 (rivi 2). Jos nolla voittaa palautetaan arvo -1 (rivi 3) ja tasapelitilanteessa palautetaan arvo 0 (rivi 4). Jos peli jatkuu, käydään läpi kaikki mahdolliset siirrot (rivi 6). Rivillä 7 arvioidaan, kuinka peli jatkuu yhden siirron seurauksena. Funktio risti palauttaa parhaan löytämänsä siirron antaman arvon (rivit 5, 8 ja 9) ja funktio 81
nolla vastaavasti huonoimman [LuN05]. Minmax-algoritmin toimintaa voidaan nopeuttaa esimerkiksi alpha-beta-karsinnalla ja transpositiotaulukoilla, jotka esitellään luvuissa 5.2 ja 5.3. Kuva 4: Minmax-algoritmi [LuN05]. 5.2 Alpha-beta-karsinta Shakissa on paljon turhia siirtoja, joita voidaan karsia. Turhien siirtojen karsiminen nopeuttaa minmax-algoritmin toimintaa. Usein käytetty algoritmi minmax-algoritmin nopeuttamiseen on alpha-beta-karsinta. Alpha-beta-karsinta katkoo pelipuusta pois sellaisia haaroja, joista ei voi saada parhaita, tai huonoimpia pisteitä. Alpha-beta-karsinta ei muuta minmaxalgoritmin lopputulosta, vaan nopeuttaa minmax-algoritmin laskenta-aikaa. Kuvassa 5 esitellään esimerkkitilanne alpha-beta-karsinnan toiminnasta. Kuvan 5 pelipuuta lähdetään arvioimaan lehdistä juureen ja vasemmalta oikealle. Max-tasoilla valitaan parhaaseen pelitilanteeseen johtava haara ja vastaavasti min-tasoilla valitaan huonoimpaan pelitilanteeseen johtava haara. Minmax-algoritmin ei tarvitse tutkia harmaalla korostettuja solmuja, koska minmax-algoritmi on jo löytänyt parempaan, tai huonompaan pelitilanteeseen johtavan siirron. Alpha-beta-karsinta voidaan toteuttaa esimerkiksi niin, että minmax-algoritmissa pidetään kirjaa kahdesta muuttujasta, alpha:sta ja beta:sta. Muuttuja alpha alustetaan arvolla ja beta arvolla +. Muuttujaan alpha tallennetaan suurin tähän mennessä löydetty maksimiarvo ja muuttujaan beta tallennetaan pienin tähän mennessä löydetty minimiarvo [Wel84]. Maksimiarvoa hakevassa funktiossa tarkastellaan onko alpha >= beta. Jos yhtälö 82
Kuva 5: Alpha-beta-karsinta [Wik08a]. on tosi, haku voidaan katkaista. Vastaavasti minimiarvoa hakevassa funktiossa tarkastellaan onko alpha <= beta. Jos yhtälö on tosi, haku voidaan katkaista. 5.3 Transpositiotaulukko Samoihin pelipuun pelitilanteisiin voidaan päästä useamman eri haaran kautta. Mikäli sama tilanne on pelattu aiemmin, voidaan aiemmin pelattua pelitilannetta käyttää hyväksi. Taulukkoa, johon tallennetaan pelatut pelitilanteet, kutsutaan transpositiotaulukoksi (transposition table). Minmax-algoritmia voidaan nopeuttaa tallentamalla jo pelattuja pelitilanteita taulukkoon ja jokaisen solmun kohdalla voidaan tarkastaa, löytyykö taulukosta nykyistä pelitilannetta vastaava pelitilanne [Wal97]. Kun käytetään esimerkiksi alpha-beta-karsintaa, pelitilanteelle saatu arvo ei aina ole tarkka, vaan se voi olla pelitilanteen ylä-, tai alaraja. Tästä on silti apua, jos transpositiotaulukkoon merkitään myös pelitilanteen arvon tyyppi. Jos alpha-beta-karsinnassa pelitilanteen yläraja on huonompi kuin tämän hetkinen alpha, voidaan haku tuosta asemasta eteenpäin katkaista [Num03, Wal97]. Pelitilanteet tallennetaan transpositiotaulukkoon hajautusfunktion avulla [Num03, Wal97]. Transpositiotaulukko nollataan usein ennen uutta siirtoa. Hajautusfunktion käyttäminen aiheuttaa yhteentörmäysten vaaran, eli kaksi eri pelitilannetta voi viitata samaan taulukon alkioon. Yhteentörmäysten vuoksi hajautusfunktio ja taulukon koko on valittava tarkkaan. Liian suuren taulukon nollaus aina siirron jälkeen olisi raskas operaatio ja lisäksi suurien muistialueiden osoittaminen saattaa olla hidasta. Liian pienessä taulukossa yhteentörmäyksiä tapahtuisi liikaa, ja sen hyöty menisi hukkaan [Num03]. 6 Alku- ja loppupelien tietokannat Shakkiohjelmat ovat huonoja alku- ja loppupeleissä, koska niissä on tärkeämpää ymmärtää pelinappuloiden aseman vahvuus, kuin laskea erikseen jokainen pelitilanne. Lisäksi shakkiohjelmien laskentasyvyys on lyhyt suhteessa siirtovuorojen ja siirtomahdollisuuksien määrään. Esimerkiksi IBM:n kehittämän Deep Blue -shakkitietokoneen laskentasyvyys on 6-12 siirtoa, riippuen pelitilanteesta, ja yksi shakkipeli kestää noin 100 siirtoa [Hsu99]. Alku- ja loppupelien mahdollisia tilanteita on tutkittu ihmispelaajien ja tietokoneen toimesta. Tutkituista alku- ja loppupeleistä on tehty tietokantoja, joita voidaan käyttää shakkiohjelmien apuna nopeuttamaan siirtojen laskentaa [Num03, Wal97]. Alku- ja loppupelien tietokannat ovat kokoelmia pelitilanteista ja parhaista siirroista vastaavissa pelitilanteissa. 83
Alku- ja loppupelivaiheet voidaan rajata helposti erilleen keskipelistä. Kun alkupelin tietokannan siirrot loppuvat, siirrytään pelipuun läpikäyntiin, esimerkiksi minmax-algoritmin avulla. Vastaavasti, kun nappuloita on tarpeeksi vähän, siirrytään pelipuun läpikäynnistä tietokantahakuun [Num03]. 7 Yhteenveto Toisin kuin ihminen, tietokone ei osaa pelata shakkia älyllään. Tietokoneen shakin pelaaminen perustuu laskemiseen. Tietokone laskee erilaiset pelitilanteet, arvioi pelitilanteet ja valitsee parhaaseen tulokseen johtavan siirron. Shakkiohjelma koostuu usein arviointifunktiosta, joka arvioi pelitilanteen hyvyyttä ja hakualgoritmista, joka käy läpi tulevat siirrot. Shakkiohjelmien luomisen vaikeutena on nopeasti kasvava pelipuu, joka syntyy tulevien siirtojen läpikäymisen yhteydessä. Yhden shakkipelin kesto on keskimäärin 50 siirtoparia, eli 100 siirtoa. Yhdessä pelitilanteessa on keskimäärin 35 erilaista siirtomahdollisuutta. Jos avaussiirron yhteydessä luotaisiin pelipuu, joka sisältää kaikki mahdolliset siirrot alusta loppuun, pelipuun koko olisi 35 100 haaraa. Pelitilanteet tallennetaan tietokoneen muistiin usein kahdentoista 64-bittisen muuttujan listana. Jokainen muuttuja sisältää yhden nappulan (sotilaiden, tornien, ratsujen, lähettien, kuningattaren, tai kuninkaan) eri ilmentymien sijainnit pelilaudalla. Tulevien siirtojen läpikäynnissä syntyvän pelipuun läpikäyntiin käytetään usein minmax-algoritmia. Minmaxalgoritmi käy tiettyyn hakusyvyyteen asti kaikki mahdolliset siirrot läpi ja valitsee parhaan mahdollisen siirron siirtovuorossa olevalle pelaajalle. Minmax-algoritmia voidaan nopeuttaa esimerkiksi alpha-beta-karsinnalla ja transpositiotaulukoilla. Alpha-beta-karsinta katkoo pelipuusta pois sellaisia haaroja, joista ei voi saada parhaita, tai huonoimpia pisteitä. Transpositiotaulukkoon tallennetaan jokainen pelitilanne, jonka pelipuunläpikäyntialgoritmi käy läpi. Jokaisen solmun kohdalla tarkastetaan löytyykö transpositiotaulukosta nykyistä pelitilannetta vastaava pelitilanne. Jos löytyy, vastaavaa pelitilannetta voidaan käyttää hyväksi. Alku- ja loppupeleissä voidaan lisäksi käyttää hyväksi tietokantoja, joihin on tallennettu kokoelmia pelitilanteista ja parhaista siirroista vastaavissa pelitilanteissa. Tulevaisuudessa tietokoneet tulevat todennäköisesti pelaamaan shakkia paremmin kuin nykyään. Syy parempaan shakin pelaamiseen perustuu kasvavaan laskentatehoon, koska tietokone pelaa shakkia laskemalla. 84
Viitteet [Hsu99] F. Hsu. IBM s Deep Blue Chess Grandmaster Chips. IEEE Micro, 19(2):70 81, 1999. [Myös http://ieeexplore.ieee.org/iel4/40/16354/00755469.pdf, 5.10.2008]. [Hya04] R. Hyatt. Chess Program Board Representations, Robert Hyatt:n kotisivu, 2004. http://www.cis.uab.edu/hyatt/boardrep.html [5.10.2008]. [Lar00] [LN05] F. Laramée. Chess Programming Part VI: Evaluation Functions, GameDev.netverkkosivusto, 2000. http://www.gamedev.net/reference/articles/ article1208.asp [5.10.2008]. M. Luukkainen and M. Nykänen. Tietorakenteet. Tietorakenteet-kurssiin liittyvä moniste, tietojenkäsittelytieteen laitos, Helsinki, 2005. [Myös http://www.cs. helsinki.fi/matti.nykanen/tira/s05/syksy05.pdf, 5.10.2008]. [Num00] A. Nummiaho. Shakkisivut, Antti Nummiahon kotisivu, 2000. http://koti. kapsi.fi/ anummiah/files/portfolio/t-111 361/index.html [5.10.2008]. [Suh05] [Wal97] [Wel84] E. Suh. Introduction to Chess Board Representation, AI Horizon -verkkosivusto, 2005. http://www.aihorizon.com/essays/chessai/boardrep.htm [5.10.2008]. A. Walker. Game Theory. Game Theory -kurssiin liittyvä verkkosivusto, School of Mathematical Sciences, Nottingham, Englanti, 1997. http://www.maths.nott. ac.uk/personal/anw/g13gam [5.10.2008]. D. Welsh. Computer Chess. Wm. C. Brown Publishers, Dubuque, Iowa, USA, 1984. [Wik08a] Wikipedia. Alpha-beta pruning, 2008. http://en.wikipedia.org/wiki/alpha beta pruning [5.10.2008]. [Wik08b] Wikipedia. Shakki, 2008. http://fi.wikipedia.org/wiki/shakki [5.10.2008]. 85