Prolog: Monkey and Banana, Two Boxes - prolog

Instructions: Modify the attached program so that in order for the monkey to reach the bananas, he has to stand on a smaller box, which he has placed on top of a bigger one. At the beginning of the program, the boxes should be in two different locations in the room. Display on the screen the activities of the monkey.
I've been reading through the textbook (Prolog Programming for Artificial Intelligence), and Prolog is definitely proving difficult to pick up. While the book goes over how to solve the problem if there is one box, it does not mention how to begin to tackle this problem if there is more than one box. Any guidance / suggestions would be greatly appreciated.
move(state(middle, onbox, middle, hasnot), grasp, state(middle, onbox, middle, has)).
move(state(Pos, onfloor, Pos, H), climb, state(Pos, onbox, Pos, H)).
move(state(P1, onfloor, P1, H), push(P1, P2), state(P2, onfloor, P2, H)).
move(state(P1, onfloor, P, H), walk(P1, P2), state(P2, onfloor, P, H)).
canget(state(_ ,_ ,_ , has)).
canget(state1) :-
move(State1, Move, State2),
canget(State2).
Question:
canget(state(atdoor, onfloor, atwindow, hasnot)). % (monkey's horizontal position, monkey's vertical position, position of the box, and whether or not the monkey has the banana).
Only thing I can think of is to add another field to every clause for the second box's position, e.g., state(horizontal pos, vertical pos, pos for box1, pos for box2, and banana status).

Your suggested solution is one way to solve this: You can indeed simply add one more argument to the term that represents the state.
However, let us aim for something more general: How would you go about this if there are not only one or two, but n boxes in the room? Further, let us suppose the boxes are of sizes S_1, ..., S_n (S_i not necessarily distinct), and can only be stacked when the box on top is smaller than the one on which it is placed.
I suggest the following representation to denote such states:
We will use a pair Pos-Size to denote the position and size of each box. This is just infix notation for the term -(Pos, Size), i.e., functor - and arity 2.
We will use a list of such pairs, i.e., [Pos1-Size1, Pos2-Size2, ..., Pos_n-Size_n] to represent all boxes.
When stacking boxes at the same position, we need to ensure that the boxes that are already located at the same position allow such stacking. I leave this is an exercise for you.
Further, canget/1 is not really that interesting, is it? What we actually care about is the list of moves that take us to the solution! Hence, we extend the predicate with one argument that actually lets us see all moves on the toplevel, and use a more speaking name to denote what we are actually describing:
moves(state(_ ,_ ,_ , has), []).
moves(State0, [Move|Moves]) :-
move(State0, Move, State),
moves(State, Moves).
Now we can use iterative deepening to find concrete solutions:
?- length(Ms, _), moves(State0, Ms).
where State0 is the initial state of the puzzle.
When you become more experienced with Prolog, you will increasingly use dcg notation to describe lists, in order to simplify the code. I leave this version here for you to study later:
moves(state(_ ,_ ,_ , has)) --> [].
moves(State0) --> [Move],
{ move(State0, Move, State) },
moves(State).
Usage example, again using iterative deepening to find a shortest solution:
?- length(Ms, _), phrase(moves(State0), Ms).
Have fun, and also try The Art of Prolog!

Related

Prolog - Check winning condition in X and O game

I have a simple game of tic tac toe, there are many examples of this online that use min maxing however I just want to use a simple example for my own understanding.
I have displayed the board in a 3x3 box that have numbering system that users can pick from, in the following way:
:- dynamic o/1.
:- dynamic x/1.
% The computer has made a turn, print O
printBox(N) :- o(N), write('[o]').
% The player makes a turn, print X
printBox(N) :- x(N), write('[x]').
% We just want to print the empty board
printBox(N) :- blankSpace(N), write('[_]').
buildBoard :- printBox(1),printBox(2),printBox(3),nl,
printBox(4),printBox(5),printBox(6),nl,
printBox(7),printBox(8),printBox(9),nl.
playersMove :-
read(X),
blankSpace(X),
assert(x(X)).
When a user select from the above options (1-9) the board is filled with an X for the human player and O for the computer.
Now I also have facts for the winning lines:
winningLine(1,2,3).
winningLine(4,5,6).
winningLine(7,8,9).
%Winning rows from left to right
winningLine(1,4,7).
winningLine(2,5,8).
winningLine(3,6,9).
%Winning diagnolly
winningLine(7,5,3).
winningLine(9,5,1).
So after each move I want to check if one of the winning line combinations has been played ie does the board contain any of the winningLine combinations and with player has that combination. I have been thinking about it and a findall method could be used here however I would be open to suggestion.
My Question: How do I check the board for the winning conditions?
The simple answer
Since you are working with a global game position, we can assume the existence of a predicate checked(Player, Square) which holds iff player Player has checked the square Square.
Then all you need to check in order to see if a player has won the game is to ask whether there is a winning line where all three squares are checked by the same player:
is_win(Player) :-
winning_line(P1,P2,P3),
checked(Player,P1),
checked(Player,P2),
checked(Player,P3).
You can generate checked/2 by use of assertz:
:- dynamic checked/2.
player_move(Player, Square) :- assertz(checked(Player, Square)).
The better Way
However, if you want to go beyond simulating a simple game you should represent your state in a single data item and not put in in the global database, for example:
initial_state(board([empty, empty, empty],
[empty, empty, empty],
[empty, empty, empty]).
and adjust player_move and checked accordingly:
/* Should make a new board from Position0 by adding the move */
player_move(Player, Square, Position0, Position) :- ...
/* Should check if a player has checked a square inside Position */
checked(Player, Square, Position) :- ...
With the above global state representation, you basically have to call the winningLine(I, J, K) to obtain a triple of indices, then for all these indices, either x(X) (with X replaced by I, J and K) should hold; or for all indices o(X) should hols, like:
xwin :-
winningLine(I, J, K),
x(I),
x(J),
x(K).
nwin :-
winningLine(I, J, K),
o(I),
o(J),
o(K).
win :-
xwin.
win :-
owin.
So here xwin/0 is satisfied, given the player for x has a winning line, owin/0 is satisfied, given the player for o has a winning line, and win/0 is satisfied if any of the players has won.
But personally I think using a global state is not an elegant way to solve problems (actually in most, if not all programming paradigms). Here you can not make use of Prolog's powerful backtracking mechanism, and furthermore if you for example would like to search if there still exists a way how a user can win, you can thus not simply duplicate the board, and run a solver on the duplicated board.

Akkoy solver - prolog

i'm new to prolog and I want to solve the puzzle Akkoy with restrictions.
So far, i've been able to implement wich cells can be painted but i don't know how to force the white areas to have all the same area.
For now when solving the problem, prolog gives two answers, but I want only the first one.
Right Answer
Wrong Answer
akkoy_solver(Rows, Cols) :-
length(Rows, X),
length(Cols, Y),
make_grid(Grid, X, Y, Vars),
reset_timer,
solver(Rows, Cols, Grid),
label(Vars),
printAkkoy(Grid, Rows, Cols),
print_time,
statistics, nl.

Check if a country is needed for a critical amount of votes

Hey guys I'm new to prolog and learning it myself.
I found this question on the internet but without any answers.
I have this database
countries([belgium, france, germany, italy, luxembourg, netherlands]).
weight(france, 4).
weight(germany, 4).
weight(italy, 4).
weight(belgium, 2).
weight(netherlands, 2).
weight(luxembourg, 1).
threshold(12).
Now I made this program to see if a list of countries have enough votes to get over the threshold.
winning([], 0).
winning([Head | Tail], N):-
weight(Head, N1),
winning(Tail, N2),
N is N1 + N2.
winning(Y):-
winning(Y, N),
threshold(X),
N >= X.
Now I need to write a program critical/2, first argument a country, second argument a list of countries. Is the first country needed to get over the threshold or not.
example:
?- critical(netherlands, [belgium, france, germany]).
True
?- critical(netherlands, [france, germany, italy]).
False
for this program I need to check first, if the second argument is winning already. And if so it will fail. If not i need to get the value of the first argument add it to the second value and then check if its over the threshold. If it won't be enough it will fail. If it is enough it will succeed.
critical(X,Y):-
winning(Y,N),
weight(X,Value),
N1 is N+Value,
threshold(X),
N1 >= X.
I'm doing alot of things wrong here but I have no idea how to fix it.
You are quite close to the solution. A few hints:
First, a good naming convention helps you keep track of which argument is what:
critical(C, Cs) :-
This makes clear that the first argument is a single country, and the second is a list of zero or more countries.
So, let us first relate Cs to their total weight. Again, it helps to have a good naming convention, making clear which argument is what:
country_weight(france, 4).
country_weight(germany, 4).
country_weight(italy, 4).
country_weight(belgium, 2).
country_weight(netherlands, 2).
country_weight(luxembourg, 1)
Now, to relate multiple countries to their respective weights, we use the meta-predicate maplist/3:
maplist(country_weight, Cs, Ws)
and to sum the weights, we use sum_list/2:
sum_list(Ws, Sum)
It is obvious how to describe that Sum must be below the threshold (left as an exercise).
Finally, to denote that the sum plus the weight of the country denoted by the first argument is greater than the threshould, we use:
country_weight(C, W),
W + Sum > Threshold
This completes the definition. Notice that it was not necessary to describe which countries exist at all. Therefore, you can omit the first predicate of your program.

Write a Prolog program to model a gorilla moving across a grid

I have done very little programming in Prolog and find it quite difficult so far.
I was given the question: A gorilla moves along an 8x8 grid and can only move right or up. it has to remain within the grid and must finish at (8,8) starting at any arbitrary location.
Write a move predicate that describes all the possible moves.
My attempt:
move(X,Y,X+1,Y).
move(X,Y,X,Y+1).
Write a path predicate that uses the move predicate to determine the path thte robot shuld take.
My attempt:
path('right'):-
move(X,Y,X+1,Y).
path('up'):-
move(X,Y,X,Y+1).
Write prolog predicates that model blockages at (1,2), (4,2), and (4,1).
So far, from what I have found it seems I need to set up a list that would give all possible positions.
I have written a list of the possible positions but do not understand how to implement it:
[(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8),
(2,1),(2,2),(2,3),(2,4),(2,5),(2,6),(2,7),(2,8),
(3,1),(3,2),(3,3),(3,4),(3,5),(3,6),(3,7),(3,8),
(4,1),(4,2),(4,3),(4,4),(4,5),(4,6),(4,7),(4,8),
(5,1),(5,2),(5,3),(5,4),(5,5),(5,6),(5,7),(5,8),
(6,1),(6,2),(6,3),(6,4),(6,5),(6,6),(6,7),(6,8),
(7,1),(7,2),(7,3),(7,4),(7,5),(7,6),(7,7),(7,8),
(8,1),(8,2),(8,3),(8,4),(8,5),(8,6),(8,7),(8,8)]
This seems like it would be a simple program but I cannot seem to grasp the concepts or at least put them all together into a workable program.
Any help in direction would be greatly appreciated.
There are quite some issues with your code. Let's go through it one at a time.
1. Possible positions
Although your list of possible positions is OK, I wouldn't hard-code it like that. It's very easy to do a check if a position is on the grid:
grid_position(X, Y) :-
X >= 1,
X =< 8,
Y >= 1,
Y =< 8.
Do note that this can only be used to verify a given position. If you want to be able to generate all possible positions, you can use in/2 from library(clpfd).
2. Allowed positions
If there is no simple logic as above for positions that are blocked, there is no other way than to enumerate them yourself.
blocked(1, 2).
blocked(4, 2).
blocked(4, 1).
Using this, we can determine which are the allowed positions for our gorilla: any position that is on the grid, but is not blocked.
allowed_position(X, Y) :-
grid_position(X, Y),
\+blocked(X, Y).
3. move
The main problem here is that writing X+1 in the head of the clause doesn't do what you think it does. To evaluate arithmetic expressions, you need to use the is predicate.
Additionally, I would only allow a move if the next location is allowed. Since the gorilla is already at the current location, I don't include a check to see if this location is actually allowed.
move(X, Y, X2, Y) :-
X2 is X + 1,
allowed_position(X2, Y).
move(X, Y, X, Y2) :-
Y2 is Y + 1,
allowed_position(X, Y2).
4. path
Here's how I interpret the requirement: given a start position, return the list of moves used to reach the end position.
To do this, we're going to need 3 arguments: the X and Y positions, and the output. The output here will be a list of positions rather than a list of moves, I'll leave it up to you to change that if needed.
So what makes up our path? Well, first you make one move, and then you find the rest of the path from the next position.
path(X, Y, [(X,Y)|Ps]) :-
move(X, Y, X2, Y2),
path(X1, Y1, Ps).
Of course we have to make sure this ends at the target position, so for base case we can use:
path(8, 8, (8, 8)).
You may also want to verify that the initial position is an allowed position, which I have left out.
Combine everything, and you get output such as below.
?- path(5,6,L).
L = [(5,6),(6,6),(7,6),(8,6),(8,7)|(8,8)] ? ;
L = [(5,6),(6,6),(7,6),(7,7),(8,7)|(8,8)] ? ;
L = [(5,6),(6,6),(7,6),(7,7),(7,8)|(8,8)] ? ;
...
This may not be exactly what you're looking for, but I hope it helps you well on the way.
So you might want to say where you are moving while you're doing that. So I'll suggest a predicate move/3 like this:
% move(From_Position, To_Position, Direction).
move((X,Y),(X,Y1), up) :-
grid(G),
member((X,Y1),G),
Y1 is Y + 1.
move((X,Y),(X1,Y), rigth):-
grid(G),
member((X1,Y),G),
X1 is X + 1.
The grid calls are there to ensure that you'll always stay on the grid. you also could use a smarter predicate in_grid and avoid the member call (which is quite time consuming).
grid([(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8),
(2,1),(2,2),(2,3),(2,4),(2,5),(2,6),(2,7),(2,8),
(3,1),(3,2),(3,3),(3,4),(3,5),(3,6),(3,7),(3,8),
(4,1),(4,2),(4,3),(4,4),(4,5),(4,6),(4,7),(4,8),
(5,1),(5,2),(5,3),(5,4),(5,5),(5,6),(5,7),(5,8),
(6,1),(6,2),(6,3),(6,4),(6,5),(6,6),(6,7),(6,8),
(7,1),(7,2),(7,3),(7,4),(7,5),(7,6),(7,7),(7,8),
(8,1),(8,2),(8,3),(8,4),(8,5),(8,6),(8,7),(8,8)]).
A path should probably be a list of directions:
path((8,8), []).
path(Position, [Direction| Before]):-
\+ Position = (8,8),
move(Position, NewPosition, Direction),
path(NewPosition,Before).
To Accumulate, you can use bagof or setof
all_paths(Position,Paths):-
setof(Path,path(Position,Path),Paths).

SWI-Prolog depth-first search?

My aim is to develop a simple program to run a game called 'Kayles' which is similar to Skittles. You have a row of bottles, 2 players knock them down in turns, and the player to knock the last bottle(s) down wins. You can knock 1 or 2 bottles down only, and they have to be next to each other.
The first part of this program was to decide how to represent a bottle, and an empty space. I have decided to use a list, where 1 represents a bottle and 0 represents an empty space.
The second part of this program was to print the current state to the terminal where a bottle is represented by an asterisk * and an empty space is represented by a gap.
The third part of this program was to list and print all the possible next states reachable from a current state. For example, if you have 3 bottles [1,1,1], one possible next state is [0,1,1] as the first bottle was knocked down. So this predicate is supposed to print a list of all possible next states, again represented by * and space.
I have successfully done the above, and this is my code so far:
printstate([]) :- nl.
printstate([B|L]) :- (B=0 -> write(' '); write('*')), printstate(L).
next([1|S], [0|S]).
next([1,1|S], [0,0|S]).
next([0|S], [0|T]) :- next(S,T).
next([1|S], [1|T]) :- next(S,T).
printnextstates(S,T) :- next(S,T), printstate(T), fail.
The next bit is the bit I am stuck on! So the aim is to define the value of a state to be 1 if the first player to move can force a win, and 0 otherwise. I am to write a predicate value(S,X) which will compute the value X of any game state S by a depth-first search through the game tree. I should use assert if possible to avoid the search exploring any position more than once.
I have no idea how to do this!
So far this is what I can come up with:
value(S,X) :- S = 1, ([S,T] = 1); 0.
But I'm sure it's not that simple, yet I have no idea how to begin this question! I've researched depth-first search but I don't really understand it enough to write this... does anyone have any idea how one may go about in starting this question?
Any help is much appreciated!
Since a player is free to pick elements at any position, a remarkable simplification results from an appropriate data representation of the problem: let's say that we keep a list of available bottles. Then you could do just declaring the logic:
win(P) :-
move(P, P1),
\+ win(P1).
win(P) :- move(P, []).
move([_|R], R).
move([_,_|R], R).
Here a dumb test, up to some arbitrary length, without noting that a simple recurrence formula gives the result
?- setof(N, L^(between(1,20,N),length(L,N),win(L)), Wins).
Wins = [1, 2, 4, 5, 7, 8, 10, 11, 13|...].

Resources