Różnice

Różnice między wybraną wersją a wersją aktualną.

Odnośnik do tego porównania

pl:prolog:pllib:nim_game [2019/06/27 15:50] (aktualna)
Linia 1: Linia 1:
 +====== Nim game ======
 +{{tag>​game}}
 +===== Description =====
 +A program for playing a winning game of Nim
 +
 +
 +**Source**: ​ The Art of Prolog
 +===== Download =====
 +Program source code: {{nim_game.pl}}
 +
 +===== Listing =====
 +<code prolog>
 +/*   The play framework  ​  */
 +
 +
 +
 +:-  op(900,​fy,​not).
 +
 +
 +
 +     ​play(Game) :- 
 +
 + initialize(Game,​Position,​Player), ​
 +
 + display_game(Position,​Player),​
 +
 + play(Position,​Player,​_).
 +
 +
 +
 +     ​play(Position,​Player,​Result) :- 
 +
 +        game_over(Position,​Player,​Result),​ !, announce(Result).
 +
 +     ​play(Position,​Player,​Result) :-
 +
 +        choose_move(Position,​Player,​Move),​
 +
 +        move(Move,​Position,​Position1),​
 +
 +        display_game(Position1,​Player), ​
 +
 +        next_player(Player,​Player1),​
 +
 +        !, 
 +
 +        play(Position1,​Player1,​Result).
 +
 +
 +
 +/*  Filling in the game-playing framework */​
 +
 +
 +
 +     ​initialize(nim,​[1,​3,​5,​7],​opponent).
 +
 +
 +
 +     ​display_game(Position,​_) :- write(Position),​ nl.
 +
 +
 +
 +     ​game_over([],​Player,​Player).
 +
 +
 +
 +     ​announce(computer) :- write('​You won! Congratulations.'​),​ nl.
 +
 +     ​announce(opponent) :- write('​I won.'​),​ nl.
 +
 +
 +
 +/*  Choosing moves */
 +
 +
 +
 +     ​choose_move(Position,​opponent,​Move) :- 
 +
 + writeln(['​Please make move'​]),​ read(Move), legal(Move,​Position).
 +
 +
 +
 +legal((_,​N),​Position) :- nth_member(N,​Position,​M),​ N =< M.
 +
 +
 +
 +nth_member(1,​[X|_],​X).
 +
 +nth_member(N,​[_|Xs],​Y) :- N > 1, N1 is N-1, nth_member(N1,​Xs,​Y).
 +
 +
 +
 +     ​choose_move(_,​computer,​Move) :- 
 +
 + evaluate(Position,​Safety,​Sum),​
 +
 + decide_move(Safety,​Position,​Sum,​Move).
 +
 +
 +
 +evaluate(Position,​Safety,​Sum) :-
 +
 +   ​nim_sum(Position,​[],​Sum),​ safety(Sum,​Safety).
 +
 +
 +
 +safety(Sum,​safe) :- zero(Sum), !.
 +
 +safety(Sum,​unsafe) :- not zero(Sum), !.
 +
 +
 +
 +decide_move(safe,​_,​_,​(1,​1)). ​ % The computer'​s arbitrary move
 +
 +decide_move(unsafe,​Position,​Sum,​Move) :-
 +
 +   ​safe_move(Position,​Sum,​Move).
 +
 +
 +
 +/​*  ​
 +
 +    move(Move,​Position,​Position1) :-
 +
 + Position1 is the result of executing the move Move
 +
 + from the current Position.
 +
 +*/
 +
 +     ​move((K,​M),​[N|Ns],​[N|Ns1]) :- 
 +
 + K > 1, K1 is K - 1, move((K1,​M),​Ns,​Ns1).
 +
 +     ​move((1,​N),​[N|Ns],​Ns).
 +
 +     ​move((1,​M),​[N|Ns],​[N1|Ns]) :- 
 +
 + N > M, N1 is N - M.
 +
 +
 +
 +     ​next_player(computer,​opponent). ​   next_player(opponent,​computer).
 +
 +
 +
 +/​*  ​
 +
 +    nim_sum(Position,​SoFar,​Sum) :-
 +
 + Sum is the nim-sum of the current Position,
 +
 + and SoFar is an accumulated value.
 +
 +*/
 +
 +     ​nim_sum([N|Ns],​Bs,​Sum) :- 
 +
 +         ​binary(N,​Ds),​ nim_add(Ds,​Bs,​Bs1),​ nim_sum(Ns,​Bs1,​Sum).
 +
 +     ​nim_sum([],​Sum,​Sum).
 +
 +
 +
 + nim_add(Bs,​[],​Bs).
 +
 + nim_add([],​Bs,​Bs).
 +
 +        nim_add([B|Bs],​[C|Cs],​[D|Ds]) :- 
 +
 +           D is (B+C) mod 2, nim_add(Bs,​Cs,​Ds).
 +
 +
 +
 + binary(1,​[1]).
 +
 + binary(N,​[D|Ds]) :-
 +
 +      N > 1, D is N mod 2, N1 is N/2, binary(N1,​Ds).
 +
 +
 +
 + ​ decimal(Ds,​N) :- decimal(Ds,​0,​1,​N).
 +
 + decimal([],​N,​_,​N).
 +
 + decimal([D|Ds],​A,​T,​N) :- A1 is A+D*T, T1 is T*2, decimal(Ds,​A1,​T1,​N).
 +
 +
 +
 +          zero([]).
 +
 +          zero([0|Zs]) :- zero(Zs).
 +
 +
 +
 +/*    ​
 +
 +    safe_move(Position,​NimSum,​Move) :-
 +
 + Move is a move from the current Position with 
 +
 + the value NimSum which leaves a safe position.
 +
 +*/
 +
 +     ​safe_move(Piles,​NimSum,​Move) :- 
 +
 + safe_move(Piles,​NimSum,​1,​Move).
 +
 +
 +
 +     ​safe_move([_|_],​NimSum,​K,​(K,​M)) :- 
 +
 +        binary(_,​Bs),​ can_zero(Bs,​NimSum,​Ds,​0),​ decimal(Ds,​M).
 +
 +     ​safe_move([_|Piles],​NimSum,​K,​Move) :- 
 +
 + K1 is K + 1, safe_move(Piles,​NimSum,​K1,​Move).
 +
 +
 +
 +     ​can_zero([],​NimSum,​[],​0) :-
 +
 +        zero(NimSum).
 +
 +     ​can_zero([_|Bs],​[0|NimSum],​[C|Ds],​C) :- 
 +
 + can_zero(Bs,​NimSum,​Ds,​C).
 +
 +     ​can_zero([B|Bs],​[1|NimSum],​[D|Ds],​C) :- 
 +
 +    D is 1 - B*C,
 +
 +C1 is 1 - B, can_zero(Bs,​NimSum,​Ds,​C1).
 +
 +
 +
 +%  Program 21.2   A program for playing a winning game of Nim
 +
 +</​code>​
 +===== Comments =====
  
pl/prolog/pllib/nim_game.txt · ostatnio zmienione: 2019/06/27 15:50 (edycja zewnętrzna)
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0