Vaiheittainen opas yksinkertaisen shakki-AI: n rakentamiseksi

Tutkitaan joitain peruskäsitteitä, jotka auttavat meitä luomaan yksinkertaisen shakki-AI: n:

  • liikkua sukupolven
  • hallituksen arviointi
  • minimax
  • ja alfa-beetaleikkaus.

Jokaisessa vaiheessa parannamme algoritmiamme yhdellä näistä aika-testatuista shakkiohjelmointitekniikoista. Esitän kuinka kukin vaikuttaa algoritmin pelityyliin.

Voit tarkastella lopullista AI-algoritmia täällä GitHubissa.

Vaihe 1: Siirrä sukupolven ja taulun visualisointi

Käytämme chess.js-kirjastoa siirtojen luomiseen ja chessboard.js -taulua taulun visualisointiin. Move-sukupolven kirjasto toteuttaa periaatteessa kaikki shakkisäännöt. Tämän perusteella voimme laskea kaikki lailliset siirrot tietylle hallituksen tilaan.

Visuaalinen siirtojen luontitoiminto. Lähtöasentoa käytetään tulona ja lähtö on kaikki mahdolliset liikkeet siitä paikasta.

Näiden kirjastojen käyttö auttaa meitä keskittymään vain mielenkiintoisimpaan tehtävään: parhaan liikkeen löytävän algoritmin luomiseen.

Aloitamme luomalla funktion, joka vain palauttaa satunnaisen siirron kaikista mahdollisista siirroista:

Vaikka tämä algoritmi ei ole kovin vakaa shakkipelaaja, se on hyvä lähtökohta, koska voimme tosiasiallisesti pelata sitä vastaan:

Musta pelaa satunnaisia ​​liikkeitä. Toistettavissa osoitteessa https://jsfiddle.net/lhartikk/m14epfwb/4

Vaihe 2: Sijainnin arviointi

Yritetään nyt ymmärtää, mikä puoli on vahvempi tietyssä asennossa. Yksinkertaisin tapa saavuttaa tämä on laskea levyllä olevien kappaleiden suhteellinen lujuus seuraavan taulukon avulla:

Arviointitoiminnolla pystymme luomaan algoritmin, joka valitsee siirron, joka antaa korkeimman arvioinnin:

Ainoa konkreettinen parannus on, että algoritmimme nyt vangitsee kappaleen, jos se pystyy.

Musta leikkii yksinkertaisen arviointitoiminnon avulla. Toistettavissa osoitteessa https://jsfiddle.net/lhartikk/m5q6fgtb/1/

Vaihe 3: Hae puuta Minimax-sovelluksella

Seuraavaksi aiomme luoda hakupuun, josta algoritmi voi valita parhaan siirron. Tämä tehdään käyttämällä Minimax-algoritmia.

Tässä algoritmissa tutkitaan kaikkien mahdollisten siirtojen rekursiivinen puu tiettyyn syvyyteen ja sijainti arvioidaan puun loppupäässä.

Sen jälkeen palautamme lapsen pienimmän tai suurimman arvon vanhemmasolmulle riippuen siitä, onko kyseessä valkoinen tai musta liikkua. (Eli yritämme joko minimoida tai maksimoida lopputuloksen kullakin tasolla.)

Minimax-algoritmin visualisointi keinotekoisessa asennossa. Paras siirto valkoiselle on b2-c3, koska voimme taata, että pääsemme tilanteeseen, jossa arviointi on -50

Kun minimax on paikoillaan, algoritmimme on alkamassa ymmärtämään joitain shakin perustaktiikoita:

Minimax syvyystasolla 2. Toistettava: https://jsfiddle.net/k96eoq0q/1/

Minimix-algoritmin tehokkuus perustuu suuresti etsinnän syvyyteen, jonka voimme saavuttaa. Tätä parannamme seuraavassa vaiheessa.

Vaihe 4: Alfa-beeta-karsinta

Alfa-beeta-karsinta on minimax-algoritmin optimointimenetelmä, jonka avulla voimme jättää huomioimatta jotkut haut puussa. Tämä auttaa meitä arvioimaan minimax-hakupuun paljon syvemmältä samalla, kun käytetään samoja resursseja.

Alfa-beeta-karsinta perustuu tilanteeseen, jossa voimme lopettaa hakupuun osan arvioinnin, jos löydämme siirron, joka johtaa huonompaan tilanteeseen kuin aiemmin havaittu siirto.

Alfa-beeta-karsinta ei vaikuta minimax-algoritmin lopputulokseen - se vain nopeuttaa sitä.

Myös alfa-beeta-algoritmi on tehokkaampi, jos tapaamme ensin ne polut, jotka johtavat hyviin liikkeisiin.

Paikat, joita meidän ei tarvitse tutkia, onko alfa-beeta-karsinta käytössä ja puuta käydään kuvatussa järjestyksessä.

Alfa-beetaa käyttämällä saamme merkittävän lisäyksen minimax-algoritmiin, kuten seuraava esimerkki osoittaa:

Paikkojen lukumäärä, joka vaaditaan arvioitaessa, haluammeko suorittaa haun syvyydellä 4 ja

Seuraa tätä linkkiä ja kokeile shakin AI: n parannettua alfa-beeta-versiota.

Vaihe 5: Parannettu arviointitoiminto

Alkuperäinen arviointitoiminto on melko naiivi, koska laskemme vain taululta löytyvän materiaalin. Tämän parantamiseksi lisäämme arviointiin tekijän, joka ottaa huomioon kappaleiden sijainnin. Esimerkiksi, ritari levyn keskellä on parempi (koska sillä on enemmän vaihtoehtoja ja on siten aktiivisempi) kuin ritari levyn reunalla.

Käytämme hiukan mukautettua kappaletta neliötaulukoita, jotka on alun perin kuvattu shakki-ohjelmointi-wikissä.

Visualisoidut neliöpöydät visualisoitiin. Voimme vähentää tai lisätä arviointia kappaleen sijainnista riippuen.

Seuraavan parannuksen avulla saamme algoritmin, joka pelaa "kunnollista" shakkia, ainakin rento pelaajan näkökulmasta:

Parannettu arviointi ja alfa-beeta-karsinta etsintasyvyydellä 3. Voidaan toistaa osoitteessa https://jsfiddle.net/q76uzxwe/1/

johtopäätökset

Jopa yksinkertaisen shakkipelialgoritmin vahvuus on, että se ei tee tyhmiä virheitä. Siitä puuttuu vielä strateginen ymmärrys.

Täällä esitteleilläni menetelmillä olemme pystyneet ohjelmoimaan shakin pelaamista-algoritmin, jolla voidaan pelata shakkia. Lopullisen algoritmin ”AI-osa” (siirrä sukupolvi pois) on vain 200 koodiriviä, mikä tarkoittaa, että peruskäsitteet ovat melko yksinkertaisia ​​toteuttaa. Voit tarkistaa lopullisen version GitHubista.

Joitakin lisäparannuksia, joita voimme tehdä algoritmiin, olisi esimerkiksi:

  • move-tilaus
  • nopeampi siirto sukupolvi
  • ja loppupääkohtainen arviointi.

Jos haluat oppia lisää, tutustu shakin ohjelmointiwikiin. Se on hyödyllinen resurssi tutkittaessa näitä peruskäsitteitä pidemmälle.

Kiitos lukemisesta!