{"id":15411456,"url":"https://github.com/thorium/thomoku","last_synced_at":"2025-10-18T15:21:40.887Z","repository":{"id":139751898,"uuid":"66688981","full_name":"Thorium/thomoku","owner":"Thorium","description":null,"archived":false,"fork":false,"pushed_at":"2016-08-27T01:31:14.000Z","size":3380,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-21T20:30:37.436Z","etag":null,"topics":["algorithms","artificial-intelligence","game","gomoku","gomoku-game"],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Thorium.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-08-27T01:21:00.000Z","updated_at":"2017-07-27T12:53:54.000Z","dependencies_parsed_at":null,"dependency_job_id":"32bb86ea-da6b-4228-ba86-108ccf28a231","html_url":"https://github.com/Thorium/thomoku","commit_stats":{"total_commits":2,"total_committers":2,"mean_commits":1.0,"dds":0.5,"last_synced_commit":"48e8ac833898f93c06558ebcb8db7a7cc68d5a90"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Thorium%2Fthomoku","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Thorium%2Fthomoku/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Thorium%2Fthomoku/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Thorium%2Fthomoku/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Thorium","download_url":"https://codeload.github.com/Thorium/thomoku/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243685587,"owners_count":20330983,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorithms","artificial-intelligence","game","gomoku","gomoku-game"],"created_at":"2024-10-01T16:49:09.884Z","updated_at":"2025-10-18T15:21:40.783Z","avatar_url":"https://github.com/Thorium.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"\r\n![thomoku.jpg][1]\r\n\r\nThis is very old stuff!\r\n\r\n![pelitapa.jpg][2]\r\n\r\n![pelityyli.jpg][3]\r\n\r\n## TEKOÄLY RISTINOLLASSA\r\n\r\n### 1. Tiivistys                \r\n\r\nTämä asiakirja sisältää erittäin lyhyesti selitettynä pääpiirteissään ristinollan säännöt, pelissä käytettävät algoritmit ja algoritmien sovelluksen tietokoneelle.\r\n\r\n \r\n\r\n### 2. Ristinollan säännöt \r\n\r\nRistinollan säännöt vaihtelevat hieman, mutta perussääntönä voidaan pitää, että pelaajat laittavat pelilaudalle ruudukkoon oman pelimerkkinsä vuorotellen ja se joka saa n kpl omia pelimerkkejään peräkkäin suoraan voittaa. Välissä ei saa olla vastustajan pelimerkkejä. Suora voidaan muodostaa joko pystysuunnassa, vaakasuunnassa tai viistoon (sekä vasemmalle, että oikealle). Jos lauta on 3x3 mallinen niin nolla ei voi voittaa. Todistus www-sivulla:\r\n\r\nhttp://tuli.cc.lut.fi/~hietanen/lunchbox/tictac/1.htm\r\n\r\nNäin ollen laudan pitää olla suurempi. Yleensä pelilautana käytetään ruutupaperia, joten pelilauta on suuri. Suurella laudalla pelaajan pitää saada 5 pelimerkkiä peräkkäin. Tämä johtuu siitä, että jos pelimerkkejä pitäisi saada alle 5, ei nolla voi voittaa. Ja taas jos pelimerkkejä pitäisi saada 6, ei peli päättyisi välttämättä koskaan. Koska ristillä on aina yksi pelimerkki enemmän kuin nollalla, on risti varsin suuressa etulyöntiasemassa.\r\n\r\n### 3. Ristinollan kansainvälisyys\r\n\r\nRistinolla on englanniksi tic-tac-toe, mutta se tarkoittaa vain 3x3-laudalla pelattavaa versiota. Isommalla laudalla tunnetaan toki samanlainen peli, nimellä Go-moku. Go-mokun alkuperä on aasiasta. Laudan koko on siinä kiinteä 15x15 ja pelimerkkeinä pelaajilla on mustat kivet ja valkoiset kivet, jotka sijoitetaan laudan viivojen leikkauspisteisiin. Muuten peli on sama kuin ristinolla, kuitenkin sillä erotuksella, että yli 5 pelimerkkiä peräkkäin ei voita. (Normaalisti ristinollassa katsotaan usein 6 suoran sisältävän 5 suoran.) Koska go-mokukin suosii aloittavaa puolta, eli mustaa kiveä, on luotu lisäksi erilaisia sääntöjä. Esimerkiksi Renju on muuten samanlainen peli, mutta aloittajan saadessa 2 kpl kummastakin päästä torjumattomia 3 suoria tai 2 kpl toisesta päästä torjuttuja 4 suoria hän häviää. Peli on silloin vaikeampi kuin ristinolla, mutta aloittajalla on yhä suuri etu puolellaan. \r\n\r\n### 4. Algoritmi    \r\n\r\nJos pelaajalla on neljän suora jonka jommassakummassa päässä on tyhjä ruutu, eikä vastustaja torju sitä, hän saa seuraavalla vuorolla 5 suoran ja voittaa pelin. Näin ollen 4 suora on pakko torjua, eli se on uhka, josta voittaa 1 siirron päästä. Vastaavasti jos pelaajalla on kummastakin päästä torjumaton 3 suora, eikä vastustaja torju sitä kummastakaan päästä, saa pelaaja seuraavalla siirrolla torjumattoman 4 suoran, jota vastustajan on mahdoton enää estää muodostumasta 5 suoraksi. Näin ollen 3 suora on pakko torjua toisesta päästä. 3 suora on uhka,  josta vastustaja voittaa 2 siirron päästä. Näin ollen pelaaja voi halutessaan pelata ensin oman 4 suoransa (voitto 1 siirron päässä) ennen kuin torjuu vastustajan 3 suoran (vastustajan voitto 2 siirron päässä).\r\n\r\n\r\nJos pelaaja onnistuu rakentamaan kaksi uhkaa samaan aikaan, ei vastustaja voi torjua kumpaakin, vaan pelaaja voittaa pelin. Näin ollen mahdolliset voitot ovat:\r\n\r\n - Viiden suora, voitto oitis. ( xxxxx )\r\n\r\n - Torjumaton 4 suora, voitto seuraavalla siirrolla ( _xxxx_ )\r\n\r\n - Kaksi kappaletta 4 suoria, voitto seuraavalla siirrolla. ( oxxxx_ ja oxxxx_ ) \r\n\r\n - Neljän suora ja 3 suora, voitto viimeistään kahden vuoron päästä. ( oxxxx_ ja _xxx_ )\r\n\r\n - Kaksi 3 suoraa, voitto kahden vuoron päästä ( _xxx_ ja _xxx_ )\r\n\r\nNäistä on tärkeää huomata, että kaksi kappaletta torjumattomia 3 suoria ei auta, jos vastustajalla on jo 4 suora ja torjumaton 3 suora.\r\n\r\nJos saadaan pakotettua vastustaja torjumaan uhka kunnes saadaan paikka josta saadaan kaksi uhkaa, on pelin voitto selvä.\r\n\r\n### 5. Pelin muunto tietokoneelle \r\n\r\nPelilauta on jokin kaksiulotteinen taulukko. Pelilaudalla voi olla kolmea eri tyyppiä merkkejä: risti, nolla tai tyhjä. Tietyn rivin hakeminen laudalta (esim. etsitään onko laudalla oxxxx_ ) tapahtuu yksinkertaisena tekstihakuna. Tekstihaku pitää tietysti suorittaa joka ilmansuuntaan, eli 8 kertaa. Näin ollen hakuun tulee 8*(laudankoko_x)*(laudankoko_y) kertaa suoritettava hakuoperaatio, joka sisältää haettavan rivin pituuden verran vertailuja. Tämä joudutaan tekemään jokaista erilaista haettavaa riviä kohden. \r\n\r\nTekemäni ristinolla käyttää lähinnä Knuthin, Morrisin ja Prattin tapaista tekstihakua. Monimutkaisemmat tekstihaut (esim. Bayerin, Mooren ja Horspoolin algoritmi) perustuvat siihen, että tekstissä on satoja erityylisiä merkkejä. (Tekstihauista erittäin hyvät selostukset Martti Penttosen kirjassa Johdatus Algoritmien Suunnitteluun ja Analysointiin.) Valitettavasti ristinollalaudalla ei ole kuin kolmea tyyppiä merkkejä. Lisäksi samankaltaisia rivejä on kymmeniä (eli myöskään Ahon ja Chorasickin algoritmi ei sovellu).\r\n\r\n### 6. Algoritmin muunto tietokoneelle \r\n\r\nKaikki pelin siirrot voidaan ajatella muodostavan yhdessä pelistä suuren puurakenteen. Jokainen erilainen seuraava siirto johtaa puun solmun eri lapsisolmuun. Puusta tapahtuvat haut tehdään rekursiivisesti.\r\n\r\nParas tilanne saavutetaan kun saadaan vastustaja pakotettua torjumaan. Tällöin vastustajan siirrot voidaan yhdistää omiin siirtoihin ja puusta karsiutuu puolet pois. Silloin voidaan vain etsiä mitkä omat siirrot johtavat voittoon, eli mitä polkua pitkin puusta voittaa.\r\n\r\nAlgoritmi on yksinkertainen, mutta erittäin raskas, ottaen huomioon, että tekstihaut joka riville joudutaan suorittamaan jokaisessa puun solmussa, koska pelilaudalla olevat rivit muuttuvat joka tilanteessa.\r\n\r\nKun tietokone aloittaa paikkansa laskemisen, haetaan ensin voitot samalla siirrolla:\r\n \r\n```\r\n\t\txx_xx \r\n\r\n\t\txxx_x \r\n\r\n\t\txxxx_  \r\n\r\n\t\tja\r\n\r\n\t\too_oo\r\n\r\n\t\tooo_o\r\n\r\n\t\toooo_\r\n```\r\n \r\nJos tällainen rivi löytyy, on aivan ilmeistä mihin kohtaan tietokoneen pitää laittaa oma pelinappinsa. Olettaen että kummallakin pelaajalla on tällainen rivi, niin kone laittaa tietysti omaan paikkaansa. \r\n\r\nSeuraavaksi haettavat rivit, joilla muodostuu pelaajalle 4 suora (joka vastustajan on pakko torjua) ja niiden löytyessä korvattava uusi rivi (nyt oletetaan että pelaaja on X, jos hän on 0 niin merkit ovat tietysti päinvastoin):\r\n\r\n```\r\n\t\txx_x_ -\u003e xxoxx\r\n\r\n\t\txx_x_ -\u003e xxxxo\r\n\r\n\t\tx_x_x -\u003e xxxox\r\n\r\n\t\txx__x -\u003e xxxox\r\n\r\n\t\txx__x -\u003e xxoxx\r\n\r\n\t\txxx__ -\u003e xxxxo\r\n\r\n\t\txxx__ -\u003e xxxox\r\n\r\n\t\tx_xx_ -\u003e xoxxx\r\n\r\n\t\tx_xx_ -\u003e xxxox\r\n``` \r\n\r\nJos tällainen paikka löytyy, mennään hakupuussa seuraavaan solmuun alaspäin. Solmuja käydään läpi, kunnes löytyy haluttu maali tai kunnes puussa ei ole enää solmuja tai kunnes haluttu puun maksimihakusyvyys saavutetaan. (Pitää myös tarkistaa, ettei vastustaja saa voittoa saman tien…) Jos maalia ei löydy, pitää rivi korvata takaisin alkuperäisen laudan rivillä ja peruuttaa yksi solmu ylöspäin. Maalin löytyminen tarkoittaa, että pelaaja on saanut kaksi uhkaa ja voittaa pelin. Maalit joissa lopetetaan puusta hakeminen:\r\n\r\n```\r\n\t\t xx_xx\r\n\r\n\t\t xxx_x\r\n\r\n\t\t xxxx_\r\n```\r\n\r\nTällöin puun maksimihakusyvyydeksi vaihdetaan yhtä pienemmäksi kuin löytyneen maalin syvyys ja talletetaan löytyneen haun ensimmäisen solmun koordinaattit (x,y) ylös, eli paikka, josta laudalla voittaa.\r\n\r\nKun haku on suoritettu loppuun, niin vaihdetaan puolet ja kutsutaan uudestaan äskeistä tarkistusta, jotta saadaan selville, ettei vastustajalla ole voittoa 1. siirron päässä. Jos ei ole, niin voidaan jatkaa hauilla joissa voitto saavutetaan 2 siirron päästä kun laitetaan tiettyyn paikkaan:\r\n\r\n```\t\t \r\n\t\t_xx___ -\u003e oxxxoo\r\n\r\n\t\t_xx___ -\u003e oxxoxo\r\n\r\n\t\t_x_x__ -\u003e oxxxoo\r\n\r\n\t\t_x_x__ -\u003e oxoxxo\r\n\r\n\t\t_x__x_ -\u003e oxxoxo\r\n```\r\n\r\nTässä vastustajan pelimerkkejä voi nyt olla useampia, koska vastustaja voi torjua useaan eri paikkaan. Vastustajan liikamerkit eivät haittaa, koska jo edellisessä haussa tarkistettiin, ettei vastustaja voi voittaa suoraa ja tässä haussa ei käsitellä vastustajan merkkejä.\r\n\r\nMaalit ovat nyt rivit:\r\n\r\n```\r\n\t\t_xxx__\r\n\r\n\t\t_xx_x_\r\n```\r\n\r\nMaalien löytyminen tarkoittaa, että pelaaja saa jostain kaksi kolmen suoraa, kun on pelannut oikeista kohdista kaikki kahden paikkansa kolmen suoriksi.\r\n\r\n\r\n\r\n### 7. Heurastiset haut \r\n\r\nKoska haku on erittäin raskas, ei pelaaja jaksa odottaa yli n kpl siirron laskentasyvyyttä enempää (nykytietokoneilla n on noin 3-5). Se takaa kuitenkin jo ihan hyvän tuloksen, koska näissä siirroissa on vastustajan siirrot mukana, eli oikeasti siirtomäärä on n*2 ja parhaat ihmispelaajatkin pystyvät laskemaan keskimäärin vain 5 siirtoa eteenpäin.\r\n\r\nKuitenkin on kehitettävä malli joka antaa parhaan paikan kun voittoa ei saavuteta käytetyllä laskentasyvyydellä. Tämä toteutetaan heurastiikalla, joka ennakoi parhaan paikan ilman siirtojen laskemista eteenpäin. Periaatteessa ristinolla pelaa varsin hyvin jo pelkällä heurastisella haulla, mutta valitettavasti se saattaa antaa väärän tuloksen joissain tapauksissa, varsinkin kun hyvä ristinollan pelaaja (tai rekursiivisesti laskeva tietokone) rakentaa ilkeän ansan parin siirron päähän.\r\n\r\nHeurastinen malli on myös hyvä pelin aivan alussa. Toinen vaihtoehto on opettaa pelille mallialkuja, joista saadaan erittäin hyvät lähtökohdat. Valmiilla aloituksilla voidaan parantaa varsinkin ristin jo muutenkin hyvää etulyöntiasemaa.\r\n\r\nHyvä heurastinen haku saavutetaan antamalla tärkeimmille riveille pisteytukset, joka annetaan rivin tietylle tyhjälle kohdalle. Kun rivien pisteytykset paikalle lasketaan yhteen, voidaan paikkojen pisteytykset tallentaa prioriteettimatriisiin (eli taulukkoon joka vastaa pelilautaa kooltaan). Näin ollen prioriteettimatriisin suurin luku on suoraa paikka mihin kannattaa pelimerkki pistää. Paikkojen pisteytykset ovat suhteessa toisiinsa ja peliin voidaan haluttaessa lisätä pientä satunnaisuutta lisäämällä jokin pieni satunnaisluku paikan prioriteetin kokonaisarvoon.\r\n\r\nAlla on esimerkki prioriteeteista (THO-MOKU 0.995 Agressive Attacker), mutta tätä tarkasteltaessa on hyvä pitää mielessä, että esim. suora voitto tarkistettiin jo rekursiivisen haun alussa, joten sitä ei tässä tarvitse tässä tarkistaa uudestaan. Lisäksi nämä arvot määräävät pelityylin, eivätkä ole mitään absoluuttisesti parhaita vaan suurpiirteisiä arvoja. Paremmat arvot saataisiin esim. rakentamalla pieni silmukka, jossa ohjelma muuttaa hieman arvoja ja pelaa vanhoja arvoja vastaan 15 peliä (sekä ristillä, että nollalla), ja jos uudet arvot voittivat suurimman osan, niin tallennetaan uudet arvot. Sitten muutetaan arvoja ja mennään silmukan alkuun. Koneella menee muutama päivä laskiessa ja saadaan erittäin hyvät prioriteettiarvot. Optimaalisessa tapauksessahan koko heurastisuutta ei kuitenkaan tarvita.\r\n\r\n                                             \r\n```\r\n\t\t_ = tyhjä paikka laudalla, mihin lisätään prioriteetti\r\n\r\n\t\t* = tyhjä paikka laudalta, mihin ei kuitenkaan lisätä prioriteettia\r\n\r\n\t\tHaettava rivi / Prioriteetti\r\n\r\n\r\n\t\t*XX_X      5000\r\n\r\n\t\tXX_X*      5000\r\n\r\n\t\tXXX_*      5000\r\n\r\n\t\t0XXX*_     5000\r\n\r\n\t\tXX*X_      3000\r\n\r\n\t\tX*XX_      3000\r\n\r\n\t\tXX__X      2900\r\n\r\n\t\tX_X_X      2900\r\n\r\n\t\tX_000__    2000\r\n\r\n\t\t*_000_*    2000\r\n\r\n\t\t_0_00_     2000\r\n\r\n\t\t**0_00**     30   (=2000+30)\r\n\r\n\t\t**00_0**     30   (=2000+30)\r\n\r\n\t\tX*000_*      30   (=2000+30)\r\n\r\n\t\t*XX_*       500\r\n\r\n\t\t*X_X*       500/2 (Symmetriasyistä /2,\r\n\r\n\t\t*X__X*      490    nämähän haetaan\r\n\r\n\t\t*X*X_*      490    kahteen suuntaan,\r\n\r\n\t\t*XX*_*      490    esim. ylös ja alas)\r\n\r\n\t\tX000__      350\r\n\r\n\t\tX00_0_      350\r\n\r\n\t\tX0_00_      350\r\n\r\n\t\tX_000_      350\r\n\r\n\t\t*OO_*       200\r\n\r\n\t\t*O_O*       200\r\n\r\n\t\t*O__O*      190\r\n\r\n\t\t*O*O_*      190\r\n\r\n\t\t*OO*_*      80\r\n\r\n\t\t*XX**_*     80\r\n\r\n\t\t*X_*        60 \r\n\r\n\t\t*X*_*       50\r\n\r\n\t\t*O_*        40\r\n\r\n\t\t*O*_*       25\r\n\r\n\t\t*X*_*X*     16/2\r\n\r\n\t\t*X**_X*     10\r\n\r\n\t\t*X**_*      10\r\n\r\n\t\t*OO**_*     10\r\n\r\n\t\t*0*_*0*      6/2\r\n\r\n\t\t*0**_0*      2\r\n\r\n\t\t0_0_0_0   14000/2\r\n```\r\n \r\n### 8. THO-MOKU \r\n\r\nNämä edellä lyhyesti selostetut tekoälyn kannalta mielenkiintoiset algoritmit ovat käytössä THO-MOKU Ristinollaaja v0.995B ohjelmassa. Niillä muodostetaan pääpiirteittäin ristinollan tietokoneen tekoäly, jonka toteutus, c-kielinen muutaman tuhannen rivin koodi (ei sis. käyttöliittymää) on saatavilla THO-MOKU:n kotisivulta. Koodi lukee tiedostosta pelilaudan taulukon (0 = tyhjä, 1 = risti, 2 = nolla) ja ottaa syötteeksi tietokonepelaajan parametrit (puoli, tyyli, yms), laskee parhaan paikan ja palauttaa sen pelilaudan muotoisena prioriteettimatriisina käyttöliittymälle. Jos löytyy voittava paikka, on muiden paikkojen prioriteetti 0. Käyttöliittymän tehtävä on piirtää pelilautaruudukko (40x40) ja antaa pelaajien laittaa pelimerkkinsä ruudukkoon.\r\n\r\n\r\nKoko pelin saa käännettynä WIN/DOS-versiona kotisivulta.\r\n\r\nLisäksi kotisivulla on ohjelman käyttöohjeet (readme.txt) ja linkkejä aiheesta, yms.\r\n\r\nhttp://www.lut.fi/~hietanen/thomoku/\r\n\r\n\r\n- Tuomas Hietanen, (c) 1998 - ...\r\n\r\n![screensht1.gif][4]\r\n![screensht2.gif][5]\r\n![screensht3.gif][6]\r\n \r\n\r\n   [1]: https://raw.github.com/Thorium/Thomoku/master/thomoku.jpg\r\n   [2]: https://raw.github.com/Thorium/Thomoku/master/pelitapa.jpg\r\n   [3]: https://raw.github.com/Thorium/Thomoku/master/pelityyli.jpg\r\n   [4]: https://raw.github.com/Thorium/Thomoku/master/screensht1.gif\r\n   [5]: https://raw.github.com/Thorium/Thomoku/master/screensht2.gif\r\n   [6]: https://raw.github.com/Thorium/Thomoku/master/screensht3.gif\r\n\r\n \r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthorium%2Fthomoku","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthorium%2Fthomoku","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthorium%2Fthomoku/lists"}