Dokumentace programu piskvorek Zápočtového programu z Programování II PRM045 Ondřej Vostal 20. září 2011, Letní semestr, 2010/2011 1 Stručné zadání Napsat textovou hru piškvorky se soupeřem s umělou inteligencí. 2 Přesnější zadání Program bude interaktivní. Rozhraní programu bude textové. Po spuštění program začne v nekonečném cyklu pracovat následujícím způsobem: 1) vypíše stav hracího pole a vyzve hráče na taku k zadání dalšího tahu; 2) pokud je na tahu počítač, pak dojde k automatickému vygenerování tahu; 3) pokud žádný z kráčů nevyhrál a hrací pole ještě není zaplněné, pokračuje se bodem 1). Velikost herního pole jde nastavit. Po jejím nastavení je program nutno překompilovat. Stejně tak bude možné nastavit v jistém smyslu pravidla. Ondřej Vostal je studentem Matematiky, 4. semestr, Matematicko-fyzikální fakulta Univerzity Karlovy v Praze. mailto:ondrej.vostal@vostal.net. 1
2.1 Popis parametrů určujících pravidla hry Následující parametry lze nastavit v hlavičce zdrojového souboru programu. Program je nutné překompilovat. To lze udělat na standartním GNU systému (testováno na Gentoo GNU/Linux) pomocí (máme-li v aktuálním adresáři distribuční soubor piskvorek.tar) $ tar xf piskvorek.tar $ cd piskvorek $ make $./piskvorek BOARD_WIDTH. Šířka hracího pole. BOARD_HEIGHT. Výška hracího pole. WS. Kolik kamenů nepřetržitě v jednom ze směrů definovaném v DIR vyhrává hru. DIR. Pole, které určuje výherní směry, ve smyslu předchozího bodu. 3 Prostředky implementace a použité algoritmy Program budu impletovat v Pascalu. Testování bude probíhat v gpc (GNU Pascal compiler, gcc-3.4.5). Pro implementaci umělé inteligence použiji negamaxovou modifikaci megamaxového algoritmu s alfa-beta ořezáváním. Jako hodnotící funkci použiji maximum z maximálních počet po sobě jdoucích kamenů v jednotlivých směrech definovaných v pravidlech (konstanta DIR). 3.1 Umělá inteligence pro konečné hry s nulovým součtem a úplnou informací Hra piškvorky, pro kterou chci implementovat umělou intelogenci je konečnou hrou s nulovým součtem a úplnou informací. Podle Shannonovy věty je možné 2
tedy hledat pro počítačového hráče neprohrávající strategii. Takovou strategii je možné hledat pomocí negamaxového algoritmu. Já jsem použil pro hledání vhodného dalšího pohybu pro počítačového protivníka algoritmus negamaxu s alfa-beta ořezáváním a prohledáváním stromu možných tahů pouze do omezené úrovně. 3.1.1 Reprezentace hry pomocí stromu možných tahů a jejich hodnot Každému hracímu poli, reprezentovanému maticí čísel B = (b yx ) typu H W (BOARD_HEIGHT BOARD_WIDTH), kde b yx {0, 1, 2} značící, který hráč má pole obsazené, příp. 0, je-li pole neobsazeno, přiřadím přirozené číslo c(b). Hodnoty c(b) lze uspořádat do stromu, ve kterém každá úroveň odpovídá jistému kolu hry. Hodnoty c(b) odrážejí vhodnost pozice pro hráče 1. Čím vyšší hodnota, tím je situace pro hráče 1 výhodnější; aby vyhrál, snaží se je maximalizovat. Jelikož jde o hru s nulovým součtem hodnoty c(b) odrážejí i nevýhodnost pozice pro hráče 2, který se je bude zase snažit minimalizovat. Strom možných tahů s ohodnoceními je možné vygenerovat v každém stavu hry B = (b yx ), kdy je na tahu hráč p {1, 2}. Strom S = (V, E) (V budiž jeho vrcholy a E jeho hrany) lze generovat rekurzivně následujícím algoritmem. Algoritmus 1. 1. Vygeneruj možné tahy M = {(y, x); 1 y H, 1 x H, b yx = 0}. 2. Polož V = {B} {B yx ; B yx je matice stejná jako B, až na to, že na místě (y, x) je číslo p a ne 0, (x, y) M} a E = {(B, v); v V } 3. Pro každý vrchol z V spočítej podle Algoritmu 1 graf S = (V, E ). Výsledkem je V = V V, E = E E. 3
V tomto stromu se pak hráč na tahu vydá takovým směrem, aby maximalizoval minimální ohodnocení v listech, do kterých se v tomto směru může dostat (ohodnotit je tedy potřeba jen listy). 3.2 Herní horizont Výpočty herního stromu/hodnotící funkce končí v listech, ve kterých jeden z kráčů vyhraje, nebo dojde k remíze. I bez prořezávání je tedy výpočet konečný. 3.3 Prohledávané tahy Množinu prohledávaných tahů (v Algoritmu 1, bod 1, M) jsem pro zrychlení výpočtu zmenšil. Výhodné tahy jsou intuitivně vždy jen takové, které jsou poblíž již položených buď mých, nebo soupeřových kamenů. Množina M v programu piskvorek tedy obsahuje pouze takové dvojice (y, x), které jsou na hracím poli a ještě k tomu jsou od posledního mého (počítačový hráč), nebo protivníkova tahu v nějakém z herních směrů vzdálena o ne více, než WS políček. 3.4 Alfa-beta prořezávání negamax Výpočet kompletního stromu podle Algoritmu 1 by byl náročný. Práci si ale můžeme ušetřit prořezáváním. Hodnotící funkce v listech budeme vyhodnocovat stále ve stejném směru posloupnost herních směrů, podle kterých se generují prohledávané tahy je stále stejná. V každém z vrcholů stromu pak budeme definovat dvě hodnoty: α a β pro hráče na tahu. α je minimální hodnota hodnotící funkce, kterou hráč na tahu může dosáhnout v některém z do teď prohledaných listů. β je minimální hodnota hodnotící funkce, kterou může dosáhnout protivník v některém z do teď prohledaných listů. Dojde-li k tomu, že je pro vrchol V β < α je možné zpracovávání potomků V ukončit, neboť pak mají oba hráči lepší možnosti v jiných tazích. 4
Negamaxový algoritmus pak využívá toho, že pro α a β ve vrcholu V a pro α a β ve vrcholu V, který je potomkem V a ve kterém ještě nebylo nic prohledáno platí: α = β a β = α. 3.5 Hodnotící funkce Funkci c nazývám hodnotící funkcí. Její hodnoty určuji v programu piskvorek podle následujícího předpisu: Hodnota c(b) je délka nejdelšího retězce (po sobě jdoucích kamenů bez soupeřova, nebo prázdného pole) hráče 1, plus WS*WS, pokud hráč 1 má řetězec délky WS, mínus délka nejdelšího retězce kamenů hráče 2, mínus WS*WS, pokud hráč 2 má řetězec délky WS. 3.6 Postupný výpočet hodnotící funkce Hodnotící funkci počítám postupně s použitím podkladů o výpočtech z minulých kol. Pro každý směr a každého hráče vytvořím další hrací pole na kterém je při každém tahu v každém jeho políčku, číslo udávající jaká je délka nejdelšího souvislého řetězce kamenů daného hráče končícího na daném poli při postupu v daném směru. Čísla v těchto pomocných polích se pochopitelně mohou pouze zvětšovat, neboť kameny nelze odebírat. Při každém tahu stačí upravit hodnotu pouze políček, která mohla být ovlivněna. Protože mě zajímá délka řetězců v daném směru, stačí se nejprv podívat na délku řetězce končícího na poli proti směru; ta nám umožní spočítat a zaznamenat délky řetězců na poly posledního taku a po směru zájmu až k poly s nulou - nejdelší řetězec končící na takovém poli má délku nula, tedy na daném poli není kámen žádného hráče. Délku řetězce si pro každý směr a hráče označíme l i,d, kde i značí hráče a d směr. Pro výpočet vlastní hodnoty c(b) potřebuji znát hodnotu nejdelšího řetězce na hracím poli. Jediné řetězece, které se však mohou v jednom tahu prodloužit jsou ty, na které navazuje právě položený kámen. Délka nejdelšího řetězce pro hráče i v tahu t je tedy L i,t = max{max (d) l i,d, L i,t 1 }. 5
4 Zhodnocení Úkol, ač se zdál zpočátku triviální, překvapil svojí obtížností. Hodnotící funkci bylo nutné počítat postupně a výpočet si co nejvíce zjednodušovat. Když jsem s programováním a návrhem začínal, nemyslel jsem si, že by pro počítače dnešního výkonu měl být ne příliš optimalozovaný alpha-beta ořezávací algoritmus pro umělou inteligenci k piškvorkům oříšek. Ukázalo se však, že s nepromyšleným programem se ani výkonný počítač ve výpočtu daleko nedostane. 6