Jak naučit počítač hrát šachy, piškvorky nebo Go? Počítač nehraje intuicí. Počítač počítá. Představuje si budoucnost. "Když já zahraju sem, on zahraje tam, a pak já..." Tímto způsobem si v hlavě staví obrovský strom možností a hledá cestu k vítězství. V této kapitole naučíme Prolog hrát piškvorky, a to tak, že ho jen tak neporazíte.
Základem herní AI je algoritmus zvaný Minimax.
Pro jednoduché piškvorky 3x3 nemusíme stavět celý strom (i když bychom mohli). Stačí nám sada chytrých pravidel seřazených podle priority:
% Reprezentace desky: Seznam 9 prvků [1,2,3, 4,5,6, 7,8,9]
% Prázdné pole je proměnná nebo speciální atom 'e' (empty).
% Hráč je 'x', počítač je 'o'.
% --- Výherní kombinace ---
% Řádky
vyhra([H,H,H, _,_,_, _,_,_], H).
vyhra([_,_,_, H,H,H, _,_,_], H).
vyhra([_,_,_, _,_,_, H,H,H], H).
% Sloupce
vyhra([H,_,_, H,_,_, H,_,_], H).
vyhra([_,H,_, _,H,_, _,H,_], H).
vyhra([_,_,H, _,_,H, _,_,H], H).
% Diagonály
vyhra([H,_,_, _,H,_, _,_,H], H).
vyhra([_,_,H, _,H,_, H,_,_], H).
% --- Pomocné predikáty ---
% Zjistí, zda je pole prázdné
je_volny(Deska, Index) :-
nth1(Index, Deska, e).
% Zahraje na dané pole
zahraj(Deska, Index, Hrac, NovaDeska) :-
nth1(Index, Deska, e, Zbytek), % Najdi prázdné pole a odstraň ho
nth1(Index, NovaDeska, Hrac, Zbytek). % Vlož na stejné místo hráče
% Najde možný tah pro daného hráče
najdi_tah(Deska, Hrac, NovaDeska) :-
between(1, 9, Index), % Zkus indexy 1 až 9
je_volny(Deska, Index),
zahraj(Deska, Index, Hrac, NovaDeska).
% --- Strategie počítače (prioritní pravidla) ---
% 1. Zkus vyhrát
tah_pocitace(Deska, NovaDeska) :-
najdi_tah(Deska, o, NovaDeska), % Zkus dát 'o' někam
vyhra(NovaDeska, o), !. % Pokud to vede k výhře, BEREME TO a končíme (!).
% 2. Zabraň prohře (blokuj soupeře)
tah_pocitace(Deska, NovaDeska) :-
najdi_tah(Deska, x, TestDeska), % Co by zahrál soupeř ('x')?
vyhra(TestDeska, x), % Vyhrál by tím?
% Pokud ano, musíme zahrát na TO SAMÉ místo my ('o')
zablokuj(Deska, TestDeska, NovaDeska), !.
% Pomocný predikát pro zablokování
zablokuj(Deska, TestDeska, NovaDeska) :-
% Najdi rozdíl mezi Deska a TestDeska (to je tah soupeře)
nth1(Index, Deska, e),
nth1(Index, TestDeska, x),
zahraj(Deska, Index, o, NovaDeska). % Zahraj tam 'o'
% 3. Obsaď střed (index 5)
tah_pocitace(Deska, NovaDeska) :-
je_volny(Deska, 5),
zahraj(Deska, 5, o, NovaDeska), !.
% 4. Obsaď roh (indexy 1, 3, 7, 9)
tah_pocitace(Deska, NovaDeska) :-
member(RohIndex, [1, 3, 7, 9]),
je_volny(Deska, RohIndex),
zahraj(Deska, RohIndex, o, NovaDeska), !.
% 5. Jinak hraj náhodně na volné místo
tah_pocitace(Deska, NovaDeska) :-
najdi_tah(Deska, o, NovaDeska).
To, co dělá AI "inteligentní", je schopnost simulace. Prolog si v paměti "zkusí" zahrát tah, podívá se na výsledek (vyhraju?), a pokud se mu nelíbí, vrátí se zpět (backtracking) a zkusí jiný. To vše se děje ve zlomku vteřiny, než se na obrazovce objeví křížek.
vyhra/2 správně napsána (3 řádky, 3 sloupce, 2 diagonály).random_member(Tah, [kamen, nuzky, papir]).