Similar topics
User Yang Sedang Online
Total 3 uses online :: 0 Terdaftar, 0 Tersembunyi dan 3 Tamu Tidak ada
User online terbanyak adalah 34 pada Tue Oct 22, 2024 10:15 pm
Archieve
"Sleepy" -- Contoh Game Pertuanlangan Dari SWI PROLOG
2 posters
Halaman 1 dari 1
"Sleepy" -- Contoh Game Pertuanlangan Dari SWI PROLOG
:- dynamic at/2, i_am_at/1, i_am_holding/1, alive/1,
lit/1, visible_object/1.
/* This routine is purely for debugging purposes. */
dump :- listing(at), listing(i_am_at), listing(i_am_holding),
listing(alive), listing(lit), listing(visible_object).
/* This defines my current location. */
i_am_at(bedroom).
/* These facts describe how the rooms are connected. */
path(bedroom, n, den) :- lit(bedroom).
path(bedroom, n, den) :-
write('You trip over something in the dark.'), nl,
!, fail.
path(den, s, bedroom).
path(bedroom, d, bed).
path(bed, u, bedroom).
/* These facts tell where the various objects in the game
are located. */
at(flyswatter, den).
at(fly, bedroom).
at('light switch', den).
at('light switch', bedroom).
/* These facts specify some game-specific information. */
alive(fly).
lit(bedroom).
lit(den).
visible_object('light switch').
/* These rules describe how to pick up an object. */
take(fly) :-
write('It''s too fast for you!'), nl,
!, fail.
take('light switch') :-
take(switch).
take(switch) :-
write('It''s firmly embedded in the wall!'), nl,
!, fail.
take(X) :-
i_am_holding(X),
write('You''re already holding it!'),
nl.
take(X) :-
i_am_at(Place),
at(X, Place),
retract(at(X, Place)),
assert(i_am_holding(X)),
write('OK.'),
nl.
take(_) :-
write('I don''t see it here.'),
nl.
/* These rules describe how to put down an object. */
drop(X) :-
i_am_holding(X),
i_am_at(Place),
retract(i_am_holding(X)),
assert(at(X, Place)),
write('OK.'),
nl.
drop(_) :-
write('You aren''t holding it!'),
nl.
/* These rules define the six direction letters as calls to go/1. */
n :- go(n).
s :- go(s).
e :- go(e).
w :- go(w).
u :- go(u).
d :- go(d).
/* This rule tells how to move in a given direction. */
go(Direction) :-
i_am_at(Here),
path(Here, Direction, There),
retract(i_am_at(Here)),
assert(i_am_at(There)),
look.
go(_) :-
write('You can''t go that way.').
/* This rule tells how to look about you. */
look :-
i_am_at(Place),
describe(Place),
nl,
notice_objects_at(Place),
nl.
/* These rules set up a loop to mention all the objects
in your vicinity. */
notice_objects_at(Place) :-
lit(Place),
at(X, Place),
visible_object(X),
write('There is a '), write(X), write(' here.'), nl,
fail.
notice_objects_at(_).
/* These rules are specific to this particular game. */
use(flyswatter) :-
swat(fly).
use(bed) :-
i_am_at(bedroom),
d.
use(bed) :-
write('It''s in the bedroom!'), nl,
!, fail.
use(switch) :-
i_am_at(Place),
lit(Place),
off.
use(switch) :-
on.
on :-
i_am_at(bed),
write('You can''t reach the light switch from here.'), nl,
!, fail.
on :-
i_am_at(Place),
lit(Place),
write('The lights are already on.'), nl.
on :-
i_am_at(Place),
assert(lit(Place)),
write('The room lights come on.'), nl,
optional_buzz_off,
look.
off :-
i_am_at(bed),
write('You can''t reach the light switch from here.'), nl,
!, fail.
off :-
i_am_at(Place),
retract(lit(Place)),
optional_buzz_off,
write('It is now dark in here.'), nl.
off :-
write('The lights are already off.'), nl.
sleep :-
\+ i_am_at(bed),
write('You find it hard to sleep standing up.'), nl,
!, fail.
sleep :-
lit(bedroom),
write('You can''t get to sleep with the light on.'), nl,
!, fail.
sleep :-
lit(den),
write('The light from the den is keeping you awake.'), nl,
!, fail.
sleep :- (i_am_holding(flyswatter) ; at(flyswatter, bed)),
write('What? Sleep with a dirty old flyswatter?'), nl,
!, fail.
sleep :-
alive(fly),
write('As soon as you start to doze off, a fly lands'), nl,
write('on your face and wakes you up again.'), nl,
make_visible(fly),
make_visible(flyswatter),
!, fail.
sleep :-
write('Ahhh...you (yawn) made...it...zzzzzzzz.'), nl, nl,
finish.
swat(fly) :-
swat.
swat :-
i_am_at(Place),
\+ lit(Place),
write('You flail aimlessly in the dark!'), nl.
swat :-
\+ i_am_holding(flyswatter),
write('You aren''t holding the flyswatter.'), nl,
!, fail.
swat :-
\+ alive(fly),
write('He''s dead, Jim.'), nl.
swat :-
i_am_at(Place),
\+ at(fly, Place),
write('You swish the flyswatter through the air.'), nl.
/* Have flyswatter, room is lit, fly is here and alive. */
swat :-
buzz_off,
write('The fly escapes into the other room.'), nl.
swat :-
write('Success! You killed that pesky fly!'), nl,
retract(alive(fly)).
swat :- /* For debugging... */
write('You must have forgotten a case!', nl).
make_visible(X) :-
visible_object(X).
make_visible(X) :-
assert(visible_object(X)).
buzz_off :-
at(fly, bedroom),
lit(den),
retract(at(fly, bedroom)),
assert(at(fly, den)).
buzz_off :-
at(fly, den),
lit(bedroom),
retract(at(fly, den)),
assert(at(fly, bedroom)).
optional_buzz_off :-
buzz_off.
optional_buzz_off.
/* Under UNIX, the "halt." command quits Prolog but does not
remove the output window. On a PC, however, the window
disappears before the final output can be seen. Hence this
routine requests the user to perform the final "halt." */
finish :-
nl,
write('The game is over. Please enter the "halt." command.'),
nl.
/* This rule just writes out game instructions. */
instructions :-
nl,
write('Enter commands using standard Prolog syntax.'), nl,
write('Available commands are:'), nl,
write('start. -- to start the game.'), nl,
write('n. s. e. w. u. d. -- to go in that direction.'), nl,
write('take(Object). -- to pick up an object.'), nl,
write('drop(Object). -- to put down an object.'), nl,
write('use(Object). -- to manipulate an object.'), nl,
write('look. -- to look around you again.'), nl,
write('on. off. -- to control the room lights.'), nl,
write('sleep. -- to try to go to sleep.'), nl,
write('instructions. -- to see this message again.'), nl,
write('halt. -- to end the game and quit.'), nl,
nl.
/* This rule prints out instructions and tells where you are. */
start :-
instructions,
look.
/* These rules describe the various rooms. Depending on
circumstances, a room may have more than one description. */
describe(bedroom) :-
lit(bedroom),
write('You are in a bedroom with a large, comfortable bed.'), nl,
write('It has been a long, tiresome day, and you would like'), nl,
write('nothing better than to go to sleep.'), nl.
describe(bedroom) :-
write('You are in your bedroom. It is nice and dark.'), nl.
describe(bed) :-
write('You are in bed, and it feels great!'), nl.
describe(den) :-
lit(den),
write('You are in your den. There is a lot of stuff here,'), nl,
write('but you are too sleepy to care about most of it.'), nl.
describe(den) :-
write('You are in your den. It is dark.'), nl.
/* This is a special form, to call predicates during load time. */
:- retractall(i_am_holding(_)), start.
SUMBER
David Matuszek, Villanova University
lit/1, visible_object/1.
/* This routine is purely for debugging purposes. */
dump :- listing(at), listing(i_am_at), listing(i_am_holding),
listing(alive), listing(lit), listing(visible_object).
/* This defines my current location. */
i_am_at(bedroom).
/* These facts describe how the rooms are connected. */
path(bedroom, n, den) :- lit(bedroom).
path(bedroom, n, den) :-
write('You trip over something in the dark.'), nl,
!, fail.
path(den, s, bedroom).
path(bedroom, d, bed).
path(bed, u, bedroom).
/* These facts tell where the various objects in the game
are located. */
at(flyswatter, den).
at(fly, bedroom).
at('light switch', den).
at('light switch', bedroom).
/* These facts specify some game-specific information. */
alive(fly).
lit(bedroom).
lit(den).
visible_object('light switch').
/* These rules describe how to pick up an object. */
take(fly) :-
write('It''s too fast for you!'), nl,
!, fail.
take('light switch') :-
take(switch).
take(switch) :-
write('It''s firmly embedded in the wall!'), nl,
!, fail.
take(X) :-
i_am_holding(X),
write('You''re already holding it!'),
nl.
take(X) :-
i_am_at(Place),
at(X, Place),
retract(at(X, Place)),
assert(i_am_holding(X)),
write('OK.'),
nl.
take(_) :-
write('I don''t see it here.'),
nl.
/* These rules describe how to put down an object. */
drop(X) :-
i_am_holding(X),
i_am_at(Place),
retract(i_am_holding(X)),
assert(at(X, Place)),
write('OK.'),
nl.
drop(_) :-
write('You aren''t holding it!'),
nl.
/* These rules define the six direction letters as calls to go/1. */
n :- go(n).
s :- go(s).
e :- go(e).
w :- go(w).
u :- go(u).
d :- go(d).
/* This rule tells how to move in a given direction. */
go(Direction) :-
i_am_at(Here),
path(Here, Direction, There),
retract(i_am_at(Here)),
assert(i_am_at(There)),
look.
go(_) :-
write('You can''t go that way.').
/* This rule tells how to look about you. */
look :-
i_am_at(Place),
describe(Place),
nl,
notice_objects_at(Place),
nl.
/* These rules set up a loop to mention all the objects
in your vicinity. */
notice_objects_at(Place) :-
lit(Place),
at(X, Place),
visible_object(X),
write('There is a '), write(X), write(' here.'), nl,
fail.
notice_objects_at(_).
/* These rules are specific to this particular game. */
use(flyswatter) :-
swat(fly).
use(bed) :-
i_am_at(bedroom),
d.
use(bed) :-
write('It''s in the bedroom!'), nl,
!, fail.
use(switch) :-
i_am_at(Place),
lit(Place),
off.
use(switch) :-
on.
on :-
i_am_at(bed),
write('You can''t reach the light switch from here.'), nl,
!, fail.
on :-
i_am_at(Place),
lit(Place),
write('The lights are already on.'), nl.
on :-
i_am_at(Place),
assert(lit(Place)),
write('The room lights come on.'), nl,
optional_buzz_off,
look.
off :-
i_am_at(bed),
write('You can''t reach the light switch from here.'), nl,
!, fail.
off :-
i_am_at(Place),
retract(lit(Place)),
optional_buzz_off,
write('It is now dark in here.'), nl.
off :-
write('The lights are already off.'), nl.
sleep :-
\+ i_am_at(bed),
write('You find it hard to sleep standing up.'), nl,
!, fail.
sleep :-
lit(bedroom),
write('You can''t get to sleep with the light on.'), nl,
!, fail.
sleep :-
lit(den),
write('The light from the den is keeping you awake.'), nl,
!, fail.
sleep :- (i_am_holding(flyswatter) ; at(flyswatter, bed)),
write('What? Sleep with a dirty old flyswatter?'), nl,
!, fail.
sleep :-
alive(fly),
write('As soon as you start to doze off, a fly lands'), nl,
write('on your face and wakes you up again.'), nl,
make_visible(fly),
make_visible(flyswatter),
!, fail.
sleep :-
write('Ahhh...you (yawn) made...it...zzzzzzzz.'), nl, nl,
finish.
swat(fly) :-
swat.
swat :-
i_am_at(Place),
\+ lit(Place),
write('You flail aimlessly in the dark!'), nl.
swat :-
\+ i_am_holding(flyswatter),
write('You aren''t holding the flyswatter.'), nl,
!, fail.
swat :-
\+ alive(fly),
write('He''s dead, Jim.'), nl.
swat :-
i_am_at(Place),
\+ at(fly, Place),
write('You swish the flyswatter through the air.'), nl.
/* Have flyswatter, room is lit, fly is here and alive. */
swat :-
buzz_off,
write('The fly escapes into the other room.'), nl.
swat :-
write('Success! You killed that pesky fly!'), nl,
retract(alive(fly)).
swat :- /* For debugging... */
write('You must have forgotten a case!', nl).
make_visible(X) :-
visible_object(X).
make_visible(X) :-
assert(visible_object(X)).
buzz_off :-
at(fly, bedroom),
lit(den),
retract(at(fly, bedroom)),
assert(at(fly, den)).
buzz_off :-
at(fly, den),
lit(bedroom),
retract(at(fly, den)),
assert(at(fly, bedroom)).
optional_buzz_off :-
buzz_off.
optional_buzz_off.
/* Under UNIX, the "halt." command quits Prolog but does not
remove the output window. On a PC, however, the window
disappears before the final output can be seen. Hence this
routine requests the user to perform the final "halt." */
finish :-
nl,
write('The game is over. Please enter the "halt." command.'),
nl.
/* This rule just writes out game instructions. */
instructions :-
nl,
write('Enter commands using standard Prolog syntax.'), nl,
write('Available commands are:'), nl,
write('start. -- to start the game.'), nl,
write('n. s. e. w. u. d. -- to go in that direction.'), nl,
write('take(Object). -- to pick up an object.'), nl,
write('drop(Object). -- to put down an object.'), nl,
write('use(Object). -- to manipulate an object.'), nl,
write('look. -- to look around you again.'), nl,
write('on. off. -- to control the room lights.'), nl,
write('sleep. -- to try to go to sleep.'), nl,
write('instructions. -- to see this message again.'), nl,
write('halt. -- to end the game and quit.'), nl,
nl.
/* This rule prints out instructions and tells where you are. */
start :-
instructions,
look.
/* These rules describe the various rooms. Depending on
circumstances, a room may have more than one description. */
describe(bedroom) :-
lit(bedroom),
write('You are in a bedroom with a large, comfortable bed.'), nl,
write('It has been a long, tiresome day, and you would like'), nl,
write('nothing better than to go to sleep.'), nl.
describe(bedroom) :-
write('You are in your bedroom. It is nice and dark.'), nl.
describe(bed) :-
write('You are in bed, and it feels great!'), nl.
describe(den) :-
lit(den),
write('You are in your den. There is a lot of stuff here,'), nl,
write('but you are too sleepy to care about most of it.'), nl.
describe(den) :-
write('You are in your den. It is dark.'), nl.
/* This is a special form, to call predicates during load time. */
:- retractall(i_am_holding(_)), start.
SUMBER
David Matuszek, Villanova University
DJ_and- Posts : 61
Reputasi : 95
Cendol : 2
Join date : 28.10.09
coding FOurrows Game SWI PROLOG ( pEcah kepala )
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Section 1 : Game's Facts
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% These two numbers set how clever the AI is
% (how many levels will it scan)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
win_deep(2). % Attack rating
nolose_deep(2). % Defence rating
random_factor(3). % AI random factor. chance of success is 1/(X-1)
player_human(h).
player_ai(c).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% board_sign facts are used to determin the game sign
% of the guman and computer:
% h - Human, c - Computer, f - Empty.
% This rules are created dynamically at the setup
% phase of the game.
%
% Example:
% board_sign(h,x).
% board_sign(c,o).
% board_sign(f,f).
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Game board description
% ----------------------
% The game's board is represented by dynamic facts:
% game(Board).
% Board representation: f - empty spot
% h - human's spot
% c - computer's spot
% Row = [lowers,...,highest], lowest var index number is 1
% Each sublist represents 1 column.
% The board size if represented by board_size(N).
%
% Example:
% board_size(.
% game([[f,f,f,f],
% [f,f,f,f],
% [f,f,f,f],
% [f,f,f,f]]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Section 2 : Game's Execution statement.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
main:- write_help,game_start.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% game_start is divided to 3 rules:
% 1. Setup game - create board, assign which player starts
% 2. Id human starts get input from human
% 3. If computer starts have the computer make his move
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
game_start:-setup, nl, fail.
game_start:-board_sign(h,x),game(Board), show_board(Board), get_input(Board),!. % Player starts, Cut prevents backtracing
game_start:-board_sign(h,o),game(Board),think(Board),!. % Computer starts, Cut prevents backtracing
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Section 3 : Game's Rules
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% go(X).
% go performs the player's move and call the computer.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% first check the move is legal (Column not full)
go(X):- game(Pos),
not(get_y(X,Y)), % continue if column is full, else fail
say(Pos, $Move Illegal! You cant move to the specified column. Choose again...$, yes).
go(X):- get_y(X,Y), % Get Y value for X
game(Current_Pos), % Get current board position
member(Current_Pos, L, X), % Get the X list - L
member(L, f, Y),
!, % This cut is used to prevent prolog from backtracing into previous turns
player_human(HSign), % Get the sign of human player
replace(L2, L, HSign, Y), % Put human's sign at its place in the X column
replace(Current_Pos2, Current_Pos, L2, X), % Update the board
think(Current_Pos2). % Call AI with updated board
% think is the AI rule. the AI tries to do certain actions
% by their priority.
% 1 - Check if it has been defeated.
% 2 - Check if there's a move that will make him win
% 3,4 - Prevent player from winning. Block player if he's about to win.
% 5 - Make a move without allowing the player to make a winning move afterwards
% 6 - Make any move
%
% The cuts in each rule's end are used to prevent prolog from backtracing to
% previous, already played, turns.
think(Pos) :-
player_human(H), victory(H, Pos), !,
say(Pos, $Unbelievable! You are the winner.$, no).
think(Pos) :-
try_to_win(Pos), !.
think(Pos) :-
retractall(last_good_move(_)),
try_nolose(Pos).
think(_) :-
last_good_move(Pos2), !, % prevents backtracking that will cause the
% computer to change a move he had
% already done and look for a new one.
say(Pos2, $It's your move.$, yes).
think(Pos) :-
player_ai(AI), player_human(H),
move(AI, Pos, Pos2),
nolose(H, Pos2, 0), !, % Tries to advance toward winning
say(Pos2, $Go on, you have some chance in this game.$, yes).
think(Pos) :-
player_ai(AI),
move(AI, Pos, Pos2),
say(Pos2, $Go on, you have some chance in this game.$, yes).
try_nolose(Pos) :- player_ai(AI),
move(AI, Pos, Pos2),
nolose_deep(Deep),
player_human(H),
nolose(H, Pos2, Deep),
retractall(last_good_move(_)),assert(last_good_move(Pos2)),
random_factor(F), random_number(X,F), X == 1, !, fail. % Make AI's move more inetersting
try_to_win(Pos) :- player_ai(AI),
move(AI, Pos, Pos2),
is_it_win(Pos2).
is_it_win(Pos2) :-
player_ai(AI),
victory(AI, Pos2),
say(Pos2, $Sorry, you cannot win against the AI.$, no).
is_it_win(Pos2) :-
win_deep(Deep),
player_human(H),
win(H, Pos2, Deep),
say(Pos2, $Give up. Don't lose my time.$, yes).
% AI scanning rules
% -----------------------------
% AI is trying to win
win(c, Pos, Deep) :- move(c, Pos, Pos2), win(h, Pos2, Deep).
win(h, Pos, _) :- victory(c, Pos). % AI Wins
win(h, Pos, 0) :- !, fail. % Cant go any deeper
win(h, Pos, Deep) :- Deep1 is Deep - 1, not(nowin(h, Pos, Deep1)). % find a move that will not cause X (Player) to win
nowin(h, Pos, _) :- not(move(Pos)).
nowin(h, Pos, Deep) :- move(h, Pos, Pos2), nowin(c, Pos2, Deep).% Check if after this move X (Player) will be able to make a winning move
nowin(c, Pos, _) :- victory(h, Pos). % move caused X (Player) to win
nowin(c, Pos, Deep) :- not(win(c, Pos, Deep)).
%%%
lose(h, Pos, Deep) :- move(h, Pos, Pos2), lose(c, Pos2, Deep).
lose(c, Pos, _) :- victory(h, Pos). % Check if AI lost bcz of Player's move
lose(c, Pos, 0) :- !, fail. % Cant go any deeper
lose(c, Pos, Deep) :- Deep1 is Deep - 1, not(nolose(c, Pos, Deep1)). % AI's move
% nolose(o, Pos, Deep) - finds a move that will not cause AI to loose.
nolose(c, Pos, Deep) :- move(c, Pos, Pos2), nolose(h, Pos2, Deep).
nolose(h, Pos, _) :- victory(c, Pos). % Check if this board will cause O (AI) to win
nolose(h, Pos, _) :- not(move(Pos)). % The last move belongs to O
nolose(h, Pos, Deep) :- not(lose(h, Pos, Deep)). % check that a move by Player wont cause AI to lose
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% say(Board_Position, Message, Continue).
% This is the computer's play result, it shows the
% board position and a nasty remark from the AI
% Continue signals if the game is over or not.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
show_board(Pos):-
write_board(Pos).
say(Pos, Message, Continue) :-
write(Message),
nl,
show_board(Pos),
say_continue(Pos, Continue).
say_continue(Pos, yes) :-
get_input(Pos).
say_continue(Pos, no) :-quit,!. % The cut is used in order to stop the program's running
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% member determines Element's position in the list
% member(List, Element, N).
% first var is marked as N=1
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
member([Element|_],Element,1):-!.
member([_|Tail],Element,N):-
M is (N-1),
member(Tail,Element,M).
% same as member 1 but without the cut
% example of use: member2([1,2,3,4],X,N).
member2([Element|_],Element,1).
member2([_|Tail],Element,N):-
member2(Tail,Element,N1),
N is (N1+1).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% replace(NewList, List, Element, N).
% replaces the N item of List (leftest=1) with Element
% and results NewList
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
replace([Element|Tail],[_|Tail],Element,1).
replace([Head|TailNew],[Head|Tail],Element,N):-
M is (N-1),
replace(TailNew,Tail,Element,M).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% check_four(Who, Board).
%% Checks Board to see if player Who won using
%% one of the states that requires 4 colums:
%% Horizonal, Right\Left slash - -,/,\
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
horiz_checkup(Who, Col1, Col2, Col3, Col4):-
member2(Col1, Who, N),
member2(Col2, Who, N),
member2(Col3, Who, N),
member2(Col4, Who, N).
rightslash_checkup(Who, Col1, Col2, Col3, Col4):-
member2(Col1, Who, N1),
N2 is N1+1,
N3 is N2+1,
N4 is N3+1,
member2(Col2, Who, N2),
member2(Col3, Who, N3),
member2(Col4, Who, N4).
leftslash_checkup(Who, Col1, Col2, Col3, Col4):-
member2(Col1, Who, N4),
N3 is N4-1,
N2 is N3-1,
N1 is N2-1,
member2(Col2, Who, N3),
member2(Col3, Who, N2),
member2(Col4, Who, N1).
four_checkup(Who,Col1,Col2,Col3,Col4) :- horiz_checkup(Who,Col1,Col2,Col3,Col4),!.
four_checkup(Who,Col1,Col2,Col3,Col4) :- leftslash_checkup(Who,Col1,Col2,Col3,Col4),!.
four_checkup(Who,Col1,Col2,Col3,Col4) :- rightslash_checkup(Who,Col1,Col2,Col3,Col4).
% collect the board's columns to facts
check_four_process(Who, Board, N1):-
N2 is N1+1,
N3 is N2+1,
N4 is N3+1,
member2(Board, Col1, N1),
member2(Board, Col2, N2),
member2(Board, Col3, N3),
member2(Board, Col4, N4),
four_checkup(Who,Col1,Col2,Col3,Col4),
assert(game_won(Who)).
check_four(Who, Board):-
board_size(BSize),
Top is BSize-3,
for(X,1,Top,1),
check_four_process(Who,Board,X),
fail.
check_four(Who, Board):-
game_won(Who),
retractall(game_won(Who)).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% check_vert(Who, Board).
%% Checks Board to see if player Who won vertically.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
check_vert(Who,Board):-
member2(Board, Col, N),
sublist([Who,Who,Who,Who],Col).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% victory(Who, Board).
%% Checks Board to see if player Who won.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
victory( Who, Board ):-check_four(Who,Board).
victory( Who, Board ):-check_vert(Who,Board).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% get_y(X)
% gets Y value for given X. Y is the lowest availble
% item in the X column (availble=marked with f)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
get_y(X,Y) :- game(Board),
member(Board, XList, X), % Get the list for X
find_first_free(XList,Y).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% find_first_free(List, N).
% Find the first free pos in List (marked by f) and
% return its position to N
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
find_first_free([f|Tail],1):-!. % the ! is meant so there will be only 1 result
find_first_free([Head|Tail],N):-find_first_free(Tail, M),
N1 is M+1,
N is N1.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% move puts P on a place on an availble place on the board
% (an availble place is a place marked with f)
% P - value (o\x) , Pos - original board , Pos2 - new board
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
move(P, Pos, Pos2) :-
member2(Pos, L, X), % gets column
find_first_free(L,Y),
replace(L2, L, P, Y),
replace(Pos2, Pos, L2, X).
% checks that row isnt full (still have spots marked with f)
move(Pos) :-
member2(Pos, L, _),
member2(L,f,_).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% write_board(Pos) - outputs the board Pos.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
write_item(Item):-
board_sign(Item, Out),
write(Out).
write_col(Col,N):-
member(Col, Item, N),
write(' '),write_item(Item).
write_board_process(Pos,N):-
board_size(BSize),
for(X,1,BSize,1),
member(Pos, Col, X), % Get the X column
write_col(Col, N),
fail.
write_board(Pos):-
board_size(BSize),
BSize1 is BSize+1,
for(X,1,BSize,1),
X1 is BSize1-X,
not(write_board_process(Pos,X1)),
nl,
fail.
write_board(Pos):-
board_size(BSize),
for(X,1,BSize,1),
write(' '),write(X), % write the column's numbers
fail.
write_board(Pos):-nl.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Section 4 : Interface Rules
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% get_input(Pos) gets input gets the input from
% the human player
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
get_input(Pos):-
nl,
assert(current_position(Pos)), % save current position
get_command(X),
do(X).
% The cuts in the do() rules prevent prolog from backtracing back to the command prompt
do(makemove(X)):-makemove(X),!.
do(set(GameVar,Value)):-set(GameVar,Value),!.
do(show_gamevars):-show_gamevars,!.
do(help):-help,!.
do(show):-show,!.
do(quit):-quit,!.
do(reset):-game_start.
% makemove(X) makes the player's move
makemove(X):-
string_atom(String, X),
string_integer(String, N),
current_position(Pos),
retractall(game(_)),retractall(current_position(_)),
assert(game(Pos)),
go(N).
% help shows the help screen
help:- write_help, show.
% show output the current board
show:- current_position(Pos), nl,show_board(Pos),
retractall(current_position(_)),
get_input(Pos).
write_help:-
writeln('FOUR IN A ROW - Prolog final project'),
writeln('Made By Eran Kampf'),
writeln(''),
writeln('GAME DESCRIPTION:'),
writeln('The game board is at size N*N which represent N columns on which each'),
writeln('player can slide his sign. Each player, at his turn, puts his sign on'),
writeln('one of the columns at it "slides" down the colums to the lowest place possible.'),
writeln('In order to win the game a play must have 4 signs placed together horizonally,'),
writeln('vertically, or slash shape (/ or \).'),
writeln(''),
writeln('GAME CONTROL:'),
writeln('At the beginning of the game you will be ask to enter the board size.'),
writeln('The game itself is controlled using simple English commands.'),
writeln(''),
writeln('- Type ''go'',''goto'',''move'',etc and the column number to make your move.'),
writeln(' You can also just type a number. Example: ''go 2'', ''2'',''goto 2''.'),
writeln('- Type ''help'' to read these instructions again.'),
writeln('- Type ''quit'' in order to finish the game.'),
writeln('- Type ''show'',''board'',''pos'' to review the current Board position'),
writeln('- Type ''reset'' to reset the game.'),
writeln('- Type ''set <game var> <value>'' to change the value of one of the game vars.'),
writeln(' The game vars are : random_factor, win_deep, nolose_deep.'),
writeln(' Example: ''set random_factor 3'' '),
writeln('- Type ''gamevars'' in order to see the current values of the game vars'),
writeln(''),
writeln('Hit any key to continue.'),get0(_).
% Sets the random_factor value
set(random_factor, Value):-
atom_number(Value, IntValue),
IntValue>2, % factor of 2 means 1/1 chance to miss the move - computer wont move
retractall(random_factor(_)),assert(random_factor(IntValue)),
respond(['random_factor value set to ',IntValue]),
show.
% Sets the win_deep value
set(win_deep, Value):-
atom_number(Value, IntValue),
retractall(win_deep(_)), assert(win_deep(IntValue)),!,
respond(['win_deep value set to ',IntValue]),
show.
% Sets the nolose_deep value
set(nolose_deep, Value):-
atom_number(Value, IntValue),
retractall(nolose_deep(_)),assert(nolose_deep(IntValue)),
respond(['nolose_deep value set to ',IntValue]),
show.
% Outputs the values of the game vars
show_gamevars:-
random_factor(RandFac),
win_deep(Win),
nolose_deep(Nolose),
respond(['win_deep :',Win]),
respond(['nolose_deep :',Nolose]),
respond(['random_factor :',RandFac]),show.
% quits game
quit:-
nl,
writeln('Quiting program.'),
retractall(current_position(_)),
retractall(game(_)).
%%%%%%%%%%%%%%%%%%%
get_command(C):-
read_list(L), % reads sentence and put in list.
command(X,L,[]), % call the grammar for command
C =.. X,!. % make the command list a structure
get_command(C):-
respond(['I don''t understand, try again or type help']),get_command(C).
% The grammar doesn't have to be real English.
% There are two types of commands , those with and without a
% single argument.
% A special case is also made for the command makemove which can be
% activated simply by typing a number.
command([Pred,Arg]) --> verb(Type,Pred),
nounphrase(Type,Arg). % command + argument
command([Pred,Arg1,Arg2]) -->
verb(Type,Pred),
nounphrase(Type,Arg1,Arg2). % command + 2 arguments
command([Pred]) --> verb(misc,Pred). % command only (no arguments)
command([makemove,Arg]) --> noun(make_move,Arg).% special case - makemove command
nounphrase(Type,Noun) --> noun(Type,Noun).
nounphrase(Type,Noun1,Noun2) --> noun(Type,Noun1,Noun2).
verb(make_move,makemove) --> go_verb.
verb(misc,V) --> misc_verb(V).
verb(set, V) --> set_verb(V).
% define the verbs that will cause execusion of the makemove
go_verb --> [go].
go_verb --> [go,to].
go_verb --> [move].
go_verb --> [move,to].
go_verb --> [g].
% other commands
misc_verb(help) --> [help]. % Show Help
misc_verb(show) --> [show]. % Show Board
misc_verb(show) --> [show,board].% Show Board
misc_verb(show) --> [board]. % Show Board
misc_verb(show) --> [pos]. % Show Board
misc_verb(reset) --> [reset]. % Reset game
misc_verb(reset) --> [startover].% Reset game
misc_verb(quit) --> [quit]. % Quit Game
misc_verb(quit) --> [exit]. % Quit Game
misc_verb(quit) --> [end]. % Quit Game
misc_verb(quit) --> [bye]. % Quit Game
misc_verb(show_gamevars) --> [gamevars]. % show the game vars
set_verb(set) --> [set].
set_verb(set) --> [config].
noun(make_move,N) --> [N].
noun(set, Var, Value) --> [Var,Value].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% read_list(L) - reads a normal sentence from the user and puts
%% it into a list. It is composed of two parts:
%% 1. Reads a line of ASCII characters from the user, using the
%% built-in predicate get0/1, which reads a single ASCII character.
%% The line should be terminated by one of the lastword(X) keys.
%% 2. Part uses DCG to parse the list of characters into a list
%% of words, using another built-in predicate name/2, which
%% converts a list of ASCII characters into an atom.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
read_list(L) :-
write('Enter Command: '),
read_line(CL),
wordlist(L,CL,[]), !.
read_line(L) :-
get0(C),
buildlist(C,L).
buildlist(C,[]) :- lastword(C),!. % Cut is used to stop when reached to a terminal char
buildlist(C,[C|X]) :-
get0(C2),
buildlist(C2,X).
wordlist([X|Y]) --> word(X), whitespace, wordlist(Y).
wordlist([X]) --> whitespace, wordlist(X).
wordlist([X]) --> word(X).
wordlist([X]) --> word(X), whitespace.
word(W) --> charlist(X), {name(W,X)}.
charlist([X|Y]) --> chr(X), charlist(Y).
charlist([X]) --> chr(X).
chr(X) --> [X],{X>=48}.
whitespace --> whsp, whitespace.
whitespace --> whsp.
whsp --> [X], {X<48}.
lastword(10). % end if new line entered
lastword(`.).
lastword(`!).
lastword(`?).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Section 4 : Program Setup rules
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Reads an integer input
read_int(X):-read(X),integer(X),!. % Cut used to stop when an integer is read
read_int(X):-writeln('Error'),read_int(X).
% read a y\n input
yesno(`y).
yesno(`n).
read_yn(X):-get(X), yesno(X),!. % Cut is used to stop when a yesno(X) char
% is read
read_yn(X):-writeln('Error'), read_yn(X).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% setup rule is the rule that setups the game.
% It is divided into 2 parts:
% 1. Create the board according to user input
% 2. Assign the player's signs where the player
% who opens the game is X and the other is O
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
setup:- write('Enter Board Size: '),
read_int(BSize),
create_board(BSize,Board),
nl, fail.
setup:- retractall(board_sign(_,_)),
write('Do you want to start? (y / n) - '), read_yn(Chr),
set_players(Chr).
% set_players set the players signs according to who opens the game.
set_players(`y):- % Human opens - X
assert(board_sign(h,x)),
assert(board_sign(c,o)),
assert(board_sign(f,f)),!.
set_players(`n):- % Computer opens - X
assert(board_sign(h,o)),
assert(board_sign(c,x)),
assert(board_sign(f,f)),!.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% create_board(N,Board)
% This rule creates an N*N sizes board.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
create_col(N,Col):-
for(X,1,N,1),
assert(col_item(X,f)),
fail.
create_col(N,Col):-
findall(Item, col_item(_,Item), Col),
retractall(col_item(_,_)).
create_board_process(N,Board,Col):-
for(X,1,N,1),
assert(board_item(X,Col)),
fail.
create_board(N,Board):-
retractall(board_size(_)),assert(board_size(N)),
create_col(N,Col),
not(create_board_process(N,Board,Col)),
findall(Item, board_item(_,Item), Board),
retractall(board_item(_,_)),
retractall(game(_)),assert(game(Board)).
%%%%%%%%%%%%%%%%%%%%%%%%
%% Misc Utility Rules
%%%%%%%%%%%%%%%%%%%%%%%%
% random_number(X,Lim) gets a limit Lim and gives a random
% number X which is from 1 to Lim-1
random_number(X,Lim):-X is integer(random*(Lim-1))+1.
% writeln(X) outputs X and then does nl.
writeln(X):-write(X),nl.
% respond simplifies writing a mixture of literals and variables
% Example: respond(['The value of X is: ',X])
respond([]):-
write('.'),nl,nl.
respond([H|T]):-
write(H),
respond(T).
% Concates 2 lists
conc([],L,L).
conc([X|L1], L2, [X|L3]):-
conc(L1,L2,L3).
% Finds sublist S in the list L
sublist(S,L):-
conc(L1,L2,L),
conc(S,L3,L2).
%% Section 1 : Game's Facts
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% These two numbers set how clever the AI is
% (how many levels will it scan)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
win_deep(2). % Attack rating
nolose_deep(2). % Defence rating
random_factor(3). % AI random factor. chance of success is 1/(X-1)
player_human(h).
player_ai(c).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% board_sign facts are used to determin the game sign
% of the guman and computer:
% h - Human, c - Computer, f - Empty.
% This rules are created dynamically at the setup
% phase of the game.
%
% Example:
% board_sign(h,x).
% board_sign(c,o).
% board_sign(f,f).
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Game board description
% ----------------------
% The game's board is represented by dynamic facts:
% game(Board).
% Board representation: f - empty spot
% h - human's spot
% c - computer's spot
% Row = [lowers,...,highest], lowest var index number is 1
% Each sublist represents 1 column.
% The board size if represented by board_size(N).
%
% Example:
% board_size(.
% game([[f,f,f,f],
% [f,f,f,f],
% [f,f,f,f],
% [f,f,f,f]]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Section 2 : Game's Execution statement.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
main:- write_help,game_start.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% game_start is divided to 3 rules:
% 1. Setup game - create board, assign which player starts
% 2. Id human starts get input from human
% 3. If computer starts have the computer make his move
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
game_start:-setup, nl, fail.
game_start:-board_sign(h,x),game(Board), show_board(Board), get_input(Board),!. % Player starts, Cut prevents backtracing
game_start:-board_sign(h,o),game(Board),think(Board),!. % Computer starts, Cut prevents backtracing
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Section 3 : Game's Rules
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% go(X).
% go performs the player's move and call the computer.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% first check the move is legal (Column not full)
go(X):- game(Pos),
not(get_y(X,Y)), % continue if column is full, else fail
say(Pos, $Move Illegal! You cant move to the specified column. Choose again...$, yes).
go(X):- get_y(X,Y), % Get Y value for X
game(Current_Pos), % Get current board position
member(Current_Pos, L, X), % Get the X list - L
member(L, f, Y),
!, % This cut is used to prevent prolog from backtracing into previous turns
player_human(HSign), % Get the sign of human player
replace(L2, L, HSign, Y), % Put human's sign at its place in the X column
replace(Current_Pos2, Current_Pos, L2, X), % Update the board
think(Current_Pos2). % Call AI with updated board
% think is the AI rule. the AI tries to do certain actions
% by their priority.
% 1 - Check if it has been defeated.
% 2 - Check if there's a move that will make him win
% 3,4 - Prevent player from winning. Block player if he's about to win.
% 5 - Make a move without allowing the player to make a winning move afterwards
% 6 - Make any move
%
% The cuts in each rule's end are used to prevent prolog from backtracing to
% previous, already played, turns.
think(Pos) :-
player_human(H), victory(H, Pos), !,
say(Pos, $Unbelievable! You are the winner.$, no).
think(Pos) :-
try_to_win(Pos), !.
think(Pos) :-
retractall(last_good_move(_)),
try_nolose(Pos).
think(_) :-
last_good_move(Pos2), !, % prevents backtracking that will cause the
% computer to change a move he had
% already done and look for a new one.
say(Pos2, $It's your move.$, yes).
think(Pos) :-
player_ai(AI), player_human(H),
move(AI, Pos, Pos2),
nolose(H, Pos2, 0), !, % Tries to advance toward winning
say(Pos2, $Go on, you have some chance in this game.$, yes).
think(Pos) :-
player_ai(AI),
move(AI, Pos, Pos2),
say(Pos2, $Go on, you have some chance in this game.$, yes).
try_nolose(Pos) :- player_ai(AI),
move(AI, Pos, Pos2),
nolose_deep(Deep),
player_human(H),
nolose(H, Pos2, Deep),
retractall(last_good_move(_)),assert(last_good_move(Pos2)),
random_factor(F), random_number(X,F), X == 1, !, fail. % Make AI's move more inetersting
try_to_win(Pos) :- player_ai(AI),
move(AI, Pos, Pos2),
is_it_win(Pos2).
is_it_win(Pos2) :-
player_ai(AI),
victory(AI, Pos2),
say(Pos2, $Sorry, you cannot win against the AI.$, no).
is_it_win(Pos2) :-
win_deep(Deep),
player_human(H),
win(H, Pos2, Deep),
say(Pos2, $Give up. Don't lose my time.$, yes).
% AI scanning rules
% -----------------------------
% AI is trying to win
win(c, Pos, Deep) :- move(c, Pos, Pos2), win(h, Pos2, Deep).
win(h, Pos, _) :- victory(c, Pos). % AI Wins
win(h, Pos, 0) :- !, fail. % Cant go any deeper
win(h, Pos, Deep) :- Deep1 is Deep - 1, not(nowin(h, Pos, Deep1)). % find a move that will not cause X (Player) to win
nowin(h, Pos, _) :- not(move(Pos)).
nowin(h, Pos, Deep) :- move(h, Pos, Pos2), nowin(c, Pos2, Deep).% Check if after this move X (Player) will be able to make a winning move
nowin(c, Pos, _) :- victory(h, Pos). % move caused X (Player) to win
nowin(c, Pos, Deep) :- not(win(c, Pos, Deep)).
%%%
lose(h, Pos, Deep) :- move(h, Pos, Pos2), lose(c, Pos2, Deep).
lose(c, Pos, _) :- victory(h, Pos). % Check if AI lost bcz of Player's move
lose(c, Pos, 0) :- !, fail. % Cant go any deeper
lose(c, Pos, Deep) :- Deep1 is Deep - 1, not(nolose(c, Pos, Deep1)). % AI's move
% nolose(o, Pos, Deep) - finds a move that will not cause AI to loose.
nolose(c, Pos, Deep) :- move(c, Pos, Pos2), nolose(h, Pos2, Deep).
nolose(h, Pos, _) :- victory(c, Pos). % Check if this board will cause O (AI) to win
nolose(h, Pos, _) :- not(move(Pos)). % The last move belongs to O
nolose(h, Pos, Deep) :- not(lose(h, Pos, Deep)). % check that a move by Player wont cause AI to lose
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% say(Board_Position, Message, Continue).
% This is the computer's play result, it shows the
% board position and a nasty remark from the AI
% Continue signals if the game is over or not.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
show_board(Pos):-
write_board(Pos).
say(Pos, Message, Continue) :-
write(Message),
nl,
show_board(Pos),
say_continue(Pos, Continue).
say_continue(Pos, yes) :-
get_input(Pos).
say_continue(Pos, no) :-quit,!. % The cut is used in order to stop the program's running
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% member determines Element's position in the list
% member(List, Element, N).
% first var is marked as N=1
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
member([Element|_],Element,1):-!.
member([_|Tail],Element,N):-
M is (N-1),
member(Tail,Element,M).
% same as member 1 but without the cut
% example of use: member2([1,2,3,4],X,N).
member2([Element|_],Element,1).
member2([_|Tail],Element,N):-
member2(Tail,Element,N1),
N is (N1+1).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% replace(NewList, List, Element, N).
% replaces the N item of List (leftest=1) with Element
% and results NewList
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
replace([Element|Tail],[_|Tail],Element,1).
replace([Head|TailNew],[Head|Tail],Element,N):-
M is (N-1),
replace(TailNew,Tail,Element,M).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% check_four(Who, Board).
%% Checks Board to see if player Who won using
%% one of the states that requires 4 colums:
%% Horizonal, Right\Left slash - -,/,\
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
horiz_checkup(Who, Col1, Col2, Col3, Col4):-
member2(Col1, Who, N),
member2(Col2, Who, N),
member2(Col3, Who, N),
member2(Col4, Who, N).
rightslash_checkup(Who, Col1, Col2, Col3, Col4):-
member2(Col1, Who, N1),
N2 is N1+1,
N3 is N2+1,
N4 is N3+1,
member2(Col2, Who, N2),
member2(Col3, Who, N3),
member2(Col4, Who, N4).
leftslash_checkup(Who, Col1, Col2, Col3, Col4):-
member2(Col1, Who, N4),
N3 is N4-1,
N2 is N3-1,
N1 is N2-1,
member2(Col2, Who, N3),
member2(Col3, Who, N2),
member2(Col4, Who, N1).
four_checkup(Who,Col1,Col2,Col3,Col4) :- horiz_checkup(Who,Col1,Col2,Col3,Col4),!.
four_checkup(Who,Col1,Col2,Col3,Col4) :- leftslash_checkup(Who,Col1,Col2,Col3,Col4),!.
four_checkup(Who,Col1,Col2,Col3,Col4) :- rightslash_checkup(Who,Col1,Col2,Col3,Col4).
% collect the board's columns to facts
check_four_process(Who, Board, N1):-
N2 is N1+1,
N3 is N2+1,
N4 is N3+1,
member2(Board, Col1, N1),
member2(Board, Col2, N2),
member2(Board, Col3, N3),
member2(Board, Col4, N4),
four_checkup(Who,Col1,Col2,Col3,Col4),
assert(game_won(Who)).
check_four(Who, Board):-
board_size(BSize),
Top is BSize-3,
for(X,1,Top,1),
check_four_process(Who,Board,X),
fail.
check_four(Who, Board):-
game_won(Who),
retractall(game_won(Who)).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% check_vert(Who, Board).
%% Checks Board to see if player Who won vertically.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
check_vert(Who,Board):-
member2(Board, Col, N),
sublist([Who,Who,Who,Who],Col).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% victory(Who, Board).
%% Checks Board to see if player Who won.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
victory( Who, Board ):-check_four(Who,Board).
victory( Who, Board ):-check_vert(Who,Board).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% get_y(X)
% gets Y value for given X. Y is the lowest availble
% item in the X column (availble=marked with f)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
get_y(X,Y) :- game(Board),
member(Board, XList, X), % Get the list for X
find_first_free(XList,Y).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% find_first_free(List, N).
% Find the first free pos in List (marked by f) and
% return its position to N
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
find_first_free([f|Tail],1):-!. % the ! is meant so there will be only 1 result
find_first_free([Head|Tail],N):-find_first_free(Tail, M),
N1 is M+1,
N is N1.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% move puts P on a place on an availble place on the board
% (an availble place is a place marked with f)
% P - value (o\x) , Pos - original board , Pos2 - new board
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
move(P, Pos, Pos2) :-
member2(Pos, L, X), % gets column
find_first_free(L,Y),
replace(L2, L, P, Y),
replace(Pos2, Pos, L2, X).
% checks that row isnt full (still have spots marked with f)
move(Pos) :-
member2(Pos, L, _),
member2(L,f,_).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% write_board(Pos) - outputs the board Pos.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
write_item(Item):-
board_sign(Item, Out),
write(Out).
write_col(Col,N):-
member(Col, Item, N),
write(' '),write_item(Item).
write_board_process(Pos,N):-
board_size(BSize),
for(X,1,BSize,1),
member(Pos, Col, X), % Get the X column
write_col(Col, N),
fail.
write_board(Pos):-
board_size(BSize),
BSize1 is BSize+1,
for(X,1,BSize,1),
X1 is BSize1-X,
not(write_board_process(Pos,X1)),
nl,
fail.
write_board(Pos):-
board_size(BSize),
for(X,1,BSize,1),
write(' '),write(X), % write the column's numbers
fail.
write_board(Pos):-nl.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Section 4 : Interface Rules
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% get_input(Pos) gets input gets the input from
% the human player
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
get_input(Pos):-
nl,
assert(current_position(Pos)), % save current position
get_command(X),
do(X).
% The cuts in the do() rules prevent prolog from backtracing back to the command prompt
do(makemove(X)):-makemove(X),!.
do(set(GameVar,Value)):-set(GameVar,Value),!.
do(show_gamevars):-show_gamevars,!.
do(help):-help,!.
do(show):-show,!.
do(quit):-quit,!.
do(reset):-game_start.
% makemove(X) makes the player's move
makemove(X):-
string_atom(String, X),
string_integer(String, N),
current_position(Pos),
retractall(game(_)),retractall(current_position(_)),
assert(game(Pos)),
go(N).
% help shows the help screen
help:- write_help, show.
% show output the current board
show:- current_position(Pos), nl,show_board(Pos),
retractall(current_position(_)),
get_input(Pos).
write_help:-
writeln('FOUR IN A ROW - Prolog final project'),
writeln('Made By Eran Kampf'),
writeln(''),
writeln('GAME DESCRIPTION:'),
writeln('The game board is at size N*N which represent N columns on which each'),
writeln('player can slide his sign. Each player, at his turn, puts his sign on'),
writeln('one of the columns at it "slides" down the colums to the lowest place possible.'),
writeln('In order to win the game a play must have 4 signs placed together horizonally,'),
writeln('vertically, or slash shape (/ or \).'),
writeln(''),
writeln('GAME CONTROL:'),
writeln('At the beginning of the game you will be ask to enter the board size.'),
writeln('The game itself is controlled using simple English commands.'),
writeln(''),
writeln('- Type ''go'',''goto'',''move'',etc and the column number to make your move.'),
writeln(' You can also just type a number. Example: ''go 2'', ''2'',''goto 2''.'),
writeln('- Type ''help'' to read these instructions again.'),
writeln('- Type ''quit'' in order to finish the game.'),
writeln('- Type ''show'',''board'',''pos'' to review the current Board position'),
writeln('- Type ''reset'' to reset the game.'),
writeln('- Type ''set <game var> <value>'' to change the value of one of the game vars.'),
writeln(' The game vars are : random_factor, win_deep, nolose_deep.'),
writeln(' Example: ''set random_factor 3'' '),
writeln('- Type ''gamevars'' in order to see the current values of the game vars'),
writeln(''),
writeln('Hit any key to continue.'),get0(_).
% Sets the random_factor value
set(random_factor, Value):-
atom_number(Value, IntValue),
IntValue>2, % factor of 2 means 1/1 chance to miss the move - computer wont move
retractall(random_factor(_)),assert(random_factor(IntValue)),
respond(['random_factor value set to ',IntValue]),
show.
% Sets the win_deep value
set(win_deep, Value):-
atom_number(Value, IntValue),
retractall(win_deep(_)), assert(win_deep(IntValue)),!,
respond(['win_deep value set to ',IntValue]),
show.
% Sets the nolose_deep value
set(nolose_deep, Value):-
atom_number(Value, IntValue),
retractall(nolose_deep(_)),assert(nolose_deep(IntValue)),
respond(['nolose_deep value set to ',IntValue]),
show.
% Outputs the values of the game vars
show_gamevars:-
random_factor(RandFac),
win_deep(Win),
nolose_deep(Nolose),
respond(['win_deep :',Win]),
respond(['nolose_deep :',Nolose]),
respond(['random_factor :',RandFac]),show.
% quits game
quit:-
nl,
writeln('Quiting program.'),
retractall(current_position(_)),
retractall(game(_)).
%%%%%%%%%%%%%%%%%%%
get_command(C):-
read_list(L), % reads sentence and put in list.
command(X,L,[]), % call the grammar for command
C =.. X,!. % make the command list a structure
get_command(C):-
respond(['I don''t understand, try again or type help']),get_command(C).
% The grammar doesn't have to be real English.
% There are two types of commands , those with and without a
% single argument.
% A special case is also made for the command makemove which can be
% activated simply by typing a number.
command([Pred,Arg]) --> verb(Type,Pred),
nounphrase(Type,Arg). % command + argument
command([Pred,Arg1,Arg2]) -->
verb(Type,Pred),
nounphrase(Type,Arg1,Arg2). % command + 2 arguments
command([Pred]) --> verb(misc,Pred). % command only (no arguments)
command([makemove,Arg]) --> noun(make_move,Arg).% special case - makemove command
nounphrase(Type,Noun) --> noun(Type,Noun).
nounphrase(Type,Noun1,Noun2) --> noun(Type,Noun1,Noun2).
verb(make_move,makemove) --> go_verb.
verb(misc,V) --> misc_verb(V).
verb(set, V) --> set_verb(V).
% define the verbs that will cause execusion of the makemove
go_verb --> [go].
go_verb --> [go,to].
go_verb --> [move].
go_verb --> [move,to].
go_verb --> [g].
% other commands
misc_verb(help) --> [help]. % Show Help
misc_verb(show) --> [show]. % Show Board
misc_verb(show) --> [show,board].% Show Board
misc_verb(show) --> [board]. % Show Board
misc_verb(show) --> [pos]. % Show Board
misc_verb(reset) --> [reset]. % Reset game
misc_verb(reset) --> [startover].% Reset game
misc_verb(quit) --> [quit]. % Quit Game
misc_verb(quit) --> [exit]. % Quit Game
misc_verb(quit) --> [end]. % Quit Game
misc_verb(quit) --> [bye]. % Quit Game
misc_verb(show_gamevars) --> [gamevars]. % show the game vars
set_verb(set) --> [set].
set_verb(set) --> [config].
noun(make_move,N) --> [N].
noun(set, Var, Value) --> [Var,Value].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% read_list(L) - reads a normal sentence from the user and puts
%% it into a list. It is composed of two parts:
%% 1. Reads a line of ASCII characters from the user, using the
%% built-in predicate get0/1, which reads a single ASCII character.
%% The line should be terminated by one of the lastword(X) keys.
%% 2. Part uses DCG to parse the list of characters into a list
%% of words, using another built-in predicate name/2, which
%% converts a list of ASCII characters into an atom.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
read_list(L) :-
write('Enter Command: '),
read_line(CL),
wordlist(L,CL,[]), !.
read_line(L) :-
get0(C),
buildlist(C,L).
buildlist(C,[]) :- lastword(C),!. % Cut is used to stop when reached to a terminal char
buildlist(C,[C|X]) :-
get0(C2),
buildlist(C2,X).
wordlist([X|Y]) --> word(X), whitespace, wordlist(Y).
wordlist([X]) --> whitespace, wordlist(X).
wordlist([X]) --> word(X).
wordlist([X]) --> word(X), whitespace.
word(W) --> charlist(X), {name(W,X)}.
charlist([X|Y]) --> chr(X), charlist(Y).
charlist([X]) --> chr(X).
chr(X) --> [X],{X>=48}.
whitespace --> whsp, whitespace.
whitespace --> whsp.
whsp --> [X], {X<48}.
lastword(10). % end if new line entered
lastword(`.).
lastword(`!).
lastword(`?).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Section 4 : Program Setup rules
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Reads an integer input
read_int(X):-read(X),integer(X),!. % Cut used to stop when an integer is read
read_int(X):-writeln('Error'),read_int(X).
% read a y\n input
yesno(`y).
yesno(`n).
read_yn(X):-get(X), yesno(X),!. % Cut is used to stop when a yesno(X) char
% is read
read_yn(X):-writeln('Error'), read_yn(X).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% setup rule is the rule that setups the game.
% It is divided into 2 parts:
% 1. Create the board according to user input
% 2. Assign the player's signs where the player
% who opens the game is X and the other is O
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
setup:- write('Enter Board Size: '),
read_int(BSize),
create_board(BSize,Board),
nl, fail.
setup:- retractall(board_sign(_,_)),
write('Do you want to start? (y / n) - '), read_yn(Chr),
set_players(Chr).
% set_players set the players signs according to who opens the game.
set_players(`y):- % Human opens - X
assert(board_sign(h,x)),
assert(board_sign(c,o)),
assert(board_sign(f,f)),!.
set_players(`n):- % Computer opens - X
assert(board_sign(h,o)),
assert(board_sign(c,x)),
assert(board_sign(f,f)),!.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% create_board(N,Board)
% This rule creates an N*N sizes board.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
create_col(N,Col):-
for(X,1,N,1),
assert(col_item(X,f)),
fail.
create_col(N,Col):-
findall(Item, col_item(_,Item), Col),
retractall(col_item(_,_)).
create_board_process(N,Board,Col):-
for(X,1,N,1),
assert(board_item(X,Col)),
fail.
create_board(N,Board):-
retractall(board_size(_)),assert(board_size(N)),
create_col(N,Col),
not(create_board_process(N,Board,Col)),
findall(Item, board_item(_,Item), Board),
retractall(board_item(_,_)),
retractall(game(_)),assert(game(Board)).
%%%%%%%%%%%%%%%%%%%%%%%%
%% Misc Utility Rules
%%%%%%%%%%%%%%%%%%%%%%%%
% random_number(X,Lim) gets a limit Lim and gives a random
% number X which is from 1 to Lim-1
random_number(X,Lim):-X is integer(random*(Lim-1))+1.
% writeln(X) outputs X and then does nl.
writeln(X):-write(X),nl.
% respond simplifies writing a mixture of literals and variables
% Example: respond(['The value of X is: ',X])
respond([]):-
write('.'),nl,nl.
respond([H|T]):-
write(H),
respond(T).
% Concates 2 lists
conc([],L,L).
conc([X|L1], L2, [X|L3]):-
conc(L1,L2,L3).
% Finds sublist S in the list L
sublist(S,L):-
conc(L1,L2,L),
conc(S,L3,L2).
DJ_and- Posts : 61
Reputasi : 95
Cendol : 2
Join date : 28.10.09
Re: "Sleepy" -- Contoh Game Pertuanlangan Dari SWI PROLOG
kena virus nih filenya.....masa source codenya ga ada yg gw ngerti....wkwkwkwkwk
fadhil_edogawa- Posts : 4
Reputasi : 6
Cendol : 0
Join date : 29.10.09
Re: "Sleepy" -- Contoh Game Pertuanlangan Dari SWI PROLOG
hahahahah.. nama juga swi prolog model kyk gini sintaksnya
DJ_and- Posts : 61
Reputasi : 95
Cendol : 2
Join date : 28.10.09
Similar topics
» Contoh BAB II IMK dari Ka Septian
» Contoh Proposal... RPL
» [Help] source coude python game puzzle 15 for blender
» Contoh Proposal... RPL
» [Help] source coude python game puzzle 15 for blender
Halaman 1 dari 1
Permissions in this forum:
Anda tidak dapat menjawab topik