Reputation: 75
So I have a prolog program here that takes an input like this:
mazepath(X,Y,Maze,Path,Score)
mazepath( 1, 1, [[ o, e, j, p, o],
[ o, j, o, o, o],
[ o, j, mt, j, o],
[ o, o, e, o, o],
[ p, o, j, mb, o]], Path, Score).
Where pretty much all you need to know is j's are walls basically. What I need to do is from starting in the top right of the map (1,1) I need to find a p, an e, then find the mb, then find the mt in that order. Here is my current code:
mazePath(X,Y,Maze,Path,Score) :-
curVal(X,Y,Maze,V0), %Get the value of the starting point
findMasterball(X,Y,V0,Maze,Path,PathMB), %Find a path to the Masterball.
nth1(1,PathMB,Room0), %Use the path generated by findMasterball to get the starting point for findMewtoo
nth1(1,Room0,Xk),
nth1(1,Room0,Yk),
curVal(Xk,Yk,Maze,V1), %Get the value of the Masterball point
findMewtoo(Xk,Yk,V1,Maze,[[Xk,Yk]],PathM), %Found masterball, starting for Mewtoo
nth1(1,PathM,Room1), %Now find pika
nth1(1,Room1,Xs),
nth1(1,Room1,Ys),
curVal(Xs,Ys,Maze,V2), %Get the value of the
findPika(Xs,Ys,V2,Maze,[[Xs,Ys]]). %Find pika
% findMasterball - recursive predicate that searches for the Masterball
% X,Y - current location
% Val - current value of location
% PathMB - Path traveled so far
% newPath - Path returned
%
%Base Case
findMasterball(_,_,Val,_,PathMB,PathMB) :-
Val == 'mb',
length(PathK,L),
format('~w ~w',['\nPATH TO THE Masterball: ', PathK]),
format('~w ~w',['\nLENGTH OF PATH: ', L]).
%Recursive Case
findMasterball(X,Y,_,Maze,PathMB,newPath) :-
nth1(1,Maze,R), %Get width and height of the maze
length(R,W),
length(Maze,H),
nextMove(X,Y,Xn,Yn,Maze,W,H), %Find the next legal move
curVal(Xn,Yn,Maze,NVal), %Get the value of the next location
\+ memberchk([Xn,Yn],PathMB), %Make sure we have not traveled to this location before
findMewtoo(_,_,Val,_,PathM,PathM) :-
Val == 'mt',
length(PathM,L),
format('~w ~w',['\n\nPATH TO THE SWORD: ', PathM]),
format('~w ~w',['\nLENGTH OF PATH: ', L]).
%Recursive Case
findMewtoo(X,Y,_,Maze,PathM,rPathM) :-
nth1(1,Maze,R), %Get width and height of the maze
length(R,W),
length(Maze,H),
nextMove(X,Y,Xn,Yn,Maze,W,H), %Find the next legal move
curVal(Xn,Yn,Maze,NVal), %Get the value of the next location
\+ memberchk([Xn,Yn],PathM), %Make sure we have not traveled to this location before
findMewtoo(Xn,Yn,NVal,Maze,[[Xn,Yn]|PathM],rPathM). %Recursive call with the next location/value
% findPika - recursive predicate that searches for Pikachoo
% X,Y - current location
% Val - current value of location
% PathPika - Path traveled so far
%
%Base Case
findPika(_,_,Val,_,PikaPath) :-
Val == 'p',
length(PikaPath,L),
format('~w ~w',['\n\nPATH TO THE DUNGEON LORD: ', PikaPath]),
format('~w ~w',['\nLENGTH OF PATH: ', L]).
%Recursive Case
findPika(X,Y,_,Maze,PikaPath) :-
nth1(1,Maze,R), %Get width and height of the maze
length(R,W),
length(Maze,H),
nextMove(X,Y,Xn,Yn,Maze,W,H), %Find the next legal move. Doors are walkable.
curVal(Xn,Yn,Maze,NVal), %Get the value of the next location
\+ memberchk([Xn,Yn],PikaPath), %Make sure we have not traveled to this location before
% X0, Y0 - Current Location
% X, Y - Variables - Next move will be bound to these variables
% Maze
% W, H - Width and height of the maze
nextMove(X0,Y0,X,Y,Maze,W,H) :-
adj(X0,Y0,X,Y),
inBounds(X,Y,W,H).
% Up
adj(X0,Y0,X0,Y) :-
Y is Y0+1.
% Down
adj(X0,Y0,X0,Y) :-
Y is Y0-1.
% Right
adj(X0,Y0,X,Y0) :-
X is X0+1.
% Left
adj(X0,Y0,X,Y0) :-
X is X0-1.
% Is X,Y within the bounds of the maze
inBounds(X,Y,W,H) :-
X >= 1,
Y >= 1,
X =< W,
Y =< H.
% Open space.
roomOpen(X,Y,Maze) :-
nth1(Y,Maze,R),
nth1(X,R,'o').
% This is an egg, pick it up
roomOpen(X,Y,Maze) :-
nth1(Y,Maze,R),
nth1(X,R,'e').
% Here's pikachoo
roomOpen(X,Y,Maze) :-
nth1(Y,Maze,R),
nth1(X,R,'p').
% Is the masterball there? Pick it up & go catch mewtoo!
roomOpen(X,Y,Maze) :-
nth1(Y,Maze,R),
nth1(X,R,'mb').
% Is the mewtoo there? Catch it if you have the masterball!!
roomOpen(X,Y,Maze) :-
nth1(Y,Maze,R),
nth1(X,R,'mt').
%Binds the value of the location of X,Y to Val
curVal(X,Y,Maze,Val) :-
nth1(Y,Maze,R),
nth1(X,R,Val).
Now, my code "complies" fine when I load it into SWI, but as soon as I call mazepath with the test above something strange is happening. As I trace through it, it is looking at adjacent squares to see if we can walk to one. It starts at (1,1) so (1,0) and (0,1) should fail when trying to walk there. Well they do, but when my program looks at (0,1), inBounds fails, then the entire program returns false instead of continuing and finding a path. I cannot understand why it is only looking at the spaces around (1,1) and not moving to an open one and looking for the masterball again. Any ideas?
Upvotes: 2
Views: 262
Reputation: 3543
There are compilation problems with your code:
findMasterball/6
: you have a comma after the last clause \+ memberchk([Xn,Yn],PathMB)
instead of a period.findPika/5
: you have a comma after the last clause \+ memberchk([Xn,Yn],PikaPath)
instead of a period.There are also semantical problems with your code:
In findMewtoo/6
, the last argument is rPathM
in the head and the recursive call: this is an atom, not a variable, which is almost certainly not what you want. Change the r
to a R
.
The same problem exists in findMasterball/6
, with the argument newPath
in the head.
After fixing all this, you will still notice that SWI-Prolog tells you this:
Warning: c:/test.pl:1:
Singleton variables: [Score]
Warning: c:/test.pl:29:
Singleton variables: [NewPath,NVal]
Warning: c:/test.pl:67:
Singleton variables: [NVal]
Warning: c:/test.pl:80:
Singleton variables: [Maze]
which means that those variables at those lines (corresponding to a rule head) are only used once in the entire rule, which almost certainly means that it is a mistake: since Prolog is about relations between variables, it almost always makes no sense that a variable would appear only once. It either means that we don't care about the value of that variable (in that case anonymize it with _
), or that your program is wrong because some variables are not used properly.
Upvotes: 4