%---------------------------------------------------------------------------- % program NIM % Martin Dvorak I5 % Vyhledavanim strategickych pozic ... %---------------------------------------------------------------------------- % sude(+Cislo),liche(+Cislo) sude(A):-V is (2*( A // 2)),A=V. liche(A):-not(sude(A)). %---------------------------------------------------------------------------- % min(+Cislo1,+Cislo2,-Minimum) min(A,B,V):-A=<B,V is A. min(A,B,V):-A>B,V is B. %---------------------------------------------------------------------------- % strategy(+Stav,Pocet_k*(min+max)+min+s,+P,+R,-Je_vyhr) strategy([],C,_,_,V):-((sude(C),V=1); (liche(C),V=0)). strategy([H|T],C2,P,R,V):-H<P,strategy(T,C2,P,R,V). strategy([H|T],C2,P,R,V):-H>=P, C is (H mod (P+R)),C =< (P-1), strategy(T,C2,P,R,V). strategy([H|T],C2,P,R,V):-H>=P,C is (H mod (P+R)), C =< (P+P-1),C >= P, C2O is C2+1, strategy(T,C2O,P,R,V). strategy([H|_],_,P,R,0):-H>=P,C is (H mod (P+R)), C > (P+P-1). %---------------------------------------------------------------------------- % uber(+Stav,+Kde,+Kolik,-Uspech,-Vysl,Pozice) , uspech 1 , neuspech 0 uber([H|T],C,P,1,[OH|T],InC):-InC = C,H >= P, % uspesne da 1 OH is H - P. uber([H|_],C,P,0,_,InC ):-InC = C,H<P. % neuspesne da 0 uber([H|T],C,P,U,[H|OT],InC):-InC < C,MInC is InC+1, % posun na dalsi uber(T,C,P,U,OT,MInC). %----------------------------------------------------------------------------% % udela seznam vsech moznych tahu % moznosti(+Stav,+K,+P,+R,-Moznosti) moznosti(Sez,K,SP,R,Vysl):-P is SP-1, % SP - pravne P moznosti(Sez,1,K,P,SP,R,[],Vysl). moznosti(_,MK,K,MR,_,R,V,V):-MR=R,MK=K. moznosti(Sez,MK,K,MR,P,R,MV,V):-MR=R,MK<K, NK is MK+1,NR is P, % dalsi hrom uber(Sez,NK,NR,OK,OSez,1), ((OK=0,!,moznosti(Sez,NK,K,NR,P,R,MV,V)); (OK=1,!, moznosti(Sez,NK,K,NR,P,R,[OSez|MV],V))). moznosti(Sez,MK,K,MR,P,R,MV,V):-MR<R,MK=<K, NR is MR+1, % dalsi sirka uber(Sez,MK,NR,OK,OSez,1), ((OK=0,!,moznosti(Sez,MK,K,NR,P,R,MV,V)); (OK=1,!, moznosti(Sez,MK,K,NR,P,R,[OSez|MV],V))). %----------------------------------------------------------------------------% % zkontroluje zda nektera z mych moznosti jak tahnout vede dle strategie % na vyhru ve hre. % check(+Moznosti,+P,+R,-Opt.Pos) check([],_,_,[]). check([H|T],P,R,V):-strategy(H,0,P,R,C), ((C=0,!,check(T,P,R,V)); (C=1,!,V=H)). %----------------------------------------------------------------------------% % vybere ze seznamu stav , z ktereho nejde hrat na vyhravajici pozici % vyber(+Stavy,K,P,R,-Tah) vyber([],_,_,_,[]). vyber([H|T],K,P,R,V):-moznosti(H,K,P,R,Moz), check(Moz,P,R,Out), ((Out=[],V=H); % z H nejde hrat na strategii (Out\=[],vyber(T,K,P,R,V))). %----------------------------------------------------------------------------% % byla nalezena vyhr. pozice , vzda uzivatel ? % vzdej(-OK) vzdej(OK):-nl,write(' Nalezl jsem pozici vedouci na vitezstvi!'), nl,write(' Chcete pokracovat ve hre (a/n) :'),read(Volba), ((Volba=a,OK=1);(Volba\=a,OK=0,write(' Vyhral jsem !'))). %---------------------------------------------------------------------------- % nachazi optimalni tah ze stavu stav % tah(+Stav,+K,+P,+R,-Opt,-Konec) tah(Sez,K,P,R,OptTah,OK):-moznosti(Sez,K,P,R,Moz), check(Moz,P,R,Opt), % muzu tahnout na o.p. ? ((Opt=[],OK1 is 1,vyber(Moz,K,P,R,V), % nemohu ((V=[],[A|_]=Moz,OptTah=A); (V\=[],OptTah=V)) ); (Opt\=[],vzdej(OK1),OptTah=Opt)), % mohu nl,write(' MUJ TAH: '),write(OptTah), konec(OptTah,P,R,ja,OK2), % neni tah , vyhravam min(OK1,OK2,OK). % priznak konce hry %----------------------------------------------------------------------------% % ohodnot(+Stav,+P,+R,-Vyhodnost) ,1/-1,0 znamena ze nejde ohodnotit. ohodn([],_,_,0,Hodn):-Hodn is -1. % soucet 0 - prohravam ohodn([],_,_,1,Hodn):-Hodn is 1. % soucet 1 - vyhravam ohodn([],_,_,MH,Hodn):-MH\=0,MH\=1,Hodn is 0. % soucet vetsi - nelze ohodn([H|_],_,R,_,Hodn):-H > R,Hodn is 0. % mimo obor - nelze ohodn([H|T],P,R,MH,Hodn):-H < P,H < R, % nemohou brat => posun ohodn(T,P,R,MH,Hodn). ohodn([H|T],P,R,MH,Hodn):-H >= P,H =< R, % mohu dobrat hromadku MOH is MH + 1, % pridam do souctu ohodn(T,P,R,MOH,Hodn). %----------------------------------------------------------------------------% % test konce hry,chyby : konec(+Stav,+P,+R,+Odkud_volam,-Priznak) konec(Tah,P,R,ja,0):-ohodn(Tah,P,R,0,Hodn),Hodn = -1, nl,write(' Vyhral jsem ! '),!. konec(Tah,P,R,on,0):-ohodn(Tah,P,R,0,Hodn),Hodn = -1, nl,write(' Gratuluji , vyhral jste !'),!. konec(Tah,P,R,test,0):-ohodn(Tah,P,R,0,Hodn),Hodn = -1, nl,write(' Nesmyslne zadani !'),!. konec(_,_,_,_,1). %----------------------------------------------------------------------------% % kdo vyhraje pri predem rozhodnute hre : kdo(+Stav,+P,C) kdo([],_,C):-((liche(C),nl,write(' Vyhral by jste !')); (sude(C),nl,write(' Prohral by jsem !'))). kdo([H|T],P,C):-CO is (C+(H//P)),kdo(T,P,CO). %---------------------------------------------------------------------------- % test zda je hra predem rozhodnuta: smysl(+Stav,+P,+R,-Priznak) smysl(Sez,P,R,OK):-((P=R,nl,write(' Toto je predem rozhodnuta hra .'), kdo(Sez,P,0),OK = 0); (P\=R,OK = 1)). %---------------------------------------------------------------------------- % testuje koreknost zadani : test_zac(+Stav,+P,+R) test_zac(Sez,P,R):-((lst(Sez),length(Sez,K),K>0,P=<R,integer(P),integer(R)); (nl,write(' Nesmyslne zadani! Vlozte prosim nove.'),fail)). %---------------------------------------------------------------------------- % vstup zadani : zacatek(-Stav,-K,-P,-R,-Priznak) zacatek(Sez,K,P,R,OK):- repeat, nl,write(' Vlozte pocatecni stav: '),read(Sez), write(' Odebrat minimalne: '),read(P), write(' Odebrat maximalne: '),read(R), test_zac(Sez,P,R),length(Sez,K), konec(Sez,P,R,test,OK),!. %----------------------------------------------------------------------------% % test korektnosti pri odebirani: test_vstup(+K,+P,+R,+Hrom,+Sir) test_vstup(K,P,R,Hrom,Sir):-((integer(Hrom),integer(Sir),Hrom=<K,Sir>=P, Sir=<R); (nl,write(' Nesmyslne zadani! Vlozte prosim nove.'), fail)). %---------------------------------------------------------------------------- % tah soupere : vstup(+Stav,+K,+P,+R,-Jeho_tah,-Priznak) vstup(Sez,K,P,R,OSez,OOK):- repeat, nl,write(' Vlozte cislo hromadky :'),read(Hrom), write(' Pocet odebiranych sirek :'),read(Sirky), test_vstup(K,P,R,Hrom,Sirky), uber(Sez,Hrom,Sirky,OK,OSez,1),nonvar(OK),OK=1, !, write(' VAS TAH: '),write(OSez), konec(OSez,P,R,on,OOK). %----------------------------------------------------------------------------% % pokud neuspeje OK = 1 hra konci. %---------------------------------------------------------------------------- % tah_hrace(+Stav,+K,+P,+R) tah_hrace(Sez,K,P,R):-vstup(Sez,K,P,R,OSez,OK),nonvar(OK),OK = 1, tah_programu(OSez,K,P,R). %----------------------------------------------------------------------------% % tah_programu(+Stav,+K,+P,+R) tah_programu(Sez,K,P,R):-tah(Sez,K,P,R,OSez,OK),nonvar(OK),OK = 1, tah_hrace(OSez,K,P,R). %----------------------------------------------------------------------------% % spusteni hry nim:-nl,nl,nl,nl,nl,tab(32),write('NIM'),nl, tab(19),write(' Prohrava hrac , ktery nema tah .'),nl, zacatek(Sez,K,P,R,OK1),smysl(Sez,P,R,OK2), % kor. a smysl zadani min(OK1,OK2,OK),nonvar(OK),OK=1, tah_hrace(Sez,K,P,R). %--------------------------- Konec programu ---------------------------------%