Tanácsok a kötelező programhoz
Az alapoktól az erős programokig.
- Célszerű egy játékfát bejáró algoritmust használni (pl. MiniMax, AlphaBeta), a jelenlegi játékállásból, mint gyökérből kiindulva, és végül a legkedvezőbb értékű gyereknek megfelelő lépést meglépni.
- Nem szükséges a játékgráfot vagy egy részét előre kiszámítani és eltárolni, hiszen ezen algoritmusoknak elegendő az, ha az aktuális állás gyerekeit le tudjuk generálni, amikor szükség van rá.
- Mivel a játékfa túl nagy ahhoz, hogy teljes mértékben kiértékeljük, csak korlátozott mélységig vizsgáljuk. A meghatározott mélység elérésekor, ha még nem végállapotban vagyunk, egy heurisztikus értékkel kell visszatérnünk.
- A heurisztikus helyzetértékelésnek egy, a (legjobb) nyerésnek ill. (legrosszabb) vesztésnek megfelelő értékek közötti értéket kell visszaadnia, és minél jobban kell tükröznie az erőviszonyokat (~nyerési esély), de az sem jó, ha sok időt igényel a kiszámítása. (Egy egyszerű heurisztika lehet pl. malomban a korongkülönbség.) A heurisztika igen nagy mértékben befolyásolhatja a program erejét, érdemes kísérletezni, több feature-t is figyelni!
- Hasznos lehet (illetve bizonyos játékoknál kulcsfontosságú) többféle értéket rendelni a nyeréshez ill. vesztéshez aszerint, hogy az mennyi idő múlva következik be. Minél hamarabbi egy nyerés, annál jobb, és minél hamarabbi egy vesztés, annál rosszabb.
- Mivel nehéz lehet megbecsülni, mekkora mélység kiértékelése fér bele az időbe, használhatunk iteratív mélyítést is. A hátralévő idő függvényében dönthetünk, hogy nagyobb és nagyobb mélység kiértékelésébe is belekezdünk-e. (Érdemes lehet egy adott bejárás közben is figyelni az időt, és esetlegesen megállni.)
- Az implementáció egyszerűbbé válhat, ha MiniMax helyett NegaMax-ot használunk. Ekkor nem két függvényünk lesz (minimalizáló ill. maximalizáló játékos), hanem csak egy, mely a soron következő játékos szemszögéből számol (tehát maximalizál). Ehhez negálni kell az értéket, amikor szintet (így nézőpontot) váltunk. Ugyanez megtehető az AlphaBeta-val is.
- Érdemes MiniMax helyett AlphaBeta-t használni, mivel kevesebb csúcsot vizsgál meg, így gyorsabb, azaz ugyanannyi idő alatt nagyobb mélységet járhatunk be, ami pontosabb értékekhez, és így jobban játszó programhoz vezet.
- Az AlphaBeta többet tud vágni, ha megfelelő sorrendben vizsgálja az adott csúcs gyerekeit. A lépéslehetőségeket érdemes úgy rendezni, hogy a legjobbnak tűnőek kerüljenek előre. (pl. sakkban ütés)
- Nagyban gyorsítható a program transposition table használatával. A megvizsgált játékállásokról információkat tárolunk egy hash-táblába, így bizonyos esetekben megspórolhatjuk a hozzájuk tartozó részfa újbóli kiértékelését. Tipikusan tárolt adatok: a helyzet értéke; a mélység, amelyben vizsgálva volt; információ a hash-ütközés detektálására.
- Táblás játékoknál jól jöhet a Zobrist hashing a hash-függvény elkészítéséhez.
- A hash-táblában tárolt adatok felhasználhatóak a lépésrendezéshez is (főként iteratív mélyítés esetén).
- Ha elég jó a lépésrendezésünk, a NegaScout az AlphaBeta-nál is gyorsabb.
- A horizont effektus elkerülésére használhatunk quiescence search-öt. (Az érdekesebbnek tűnő állásokat nagyobb mélységben vizsgáljuk.)
- Megtehetjük, hogy még offline kiszámítjuk nagy mélységben néhány, a játékfa gyökeréhez közeli állás értékét, és ezt letárolva a megnyitások könyvét hozhatjuk létre, mely a játék elején segíti a programot.
- Megtehetjük, hogy még offline kiszámítunk egy végjáték-adatbázist a játék végéhez valamilyen szempontból közel lévő állások pontos értékéről, mely a játék végéhez közeledve segíti a programot.