User Conscious
User Conscious

Reputation: 105

Prolog traverse list for adjacent positions

I'm programming a pacman AI (yes it's homework), however I'm fairly new and I want to find all the adjacent positions (up, down, left and right) to pacman's current position. Now I have a list of all positions that are free in the level but I want to remove all those that aren't adjacent to the current position. Here's my adjacent rules:

adjacent((X,Y), (Xx,Yy)) :-
    X+1=Xx,
    Y=Yy.
adjacent((X,Y), (Xx,Yy)) :-
    X-1=Xx,
    Y=Yy.
adjacent((X,Y), (Xx,Yy)) :-
    X=Xx,
    Y+1=Yy. 
adjacent((X,Y), (Xx,Yy)) :-
    X=Xx
    Y-1=Yy.

Now I want to use a list of positions (Xx,Yy) and only use the positions that fulfill one of the adjacent rules. So I have to traverse the list, use adjacent (Prolog will check all 4 rules, correct?) and if true, add them to a new list.

So something like this

    find_adjacent((X,Y),[(Xx,Yy)|T], Z] :-
        adjacent((X,Y),(Xx,Yy) -> add_to_new_list((Xx,Yy),Z);

Is this the correct way of thinking in Prolog? Could someone point me in the right direction?

Thanks.

Upvotes: 3

Views: 841

Answers (1)

false
false

Reputation: 10102

If you are using Prolog without constraints, you will have to normalize/evaluate the expression first. That is:

adjacent((X,Y), (Xx,Yy)) :-
   Xx is X+1,
   Yy = Y.
...

Even simpler and faster would be

adjacent((X,Y), (X, Yy)) :-
   ( Yy is Y+1 ; Yy is Y-1 ).
adjacent((X,Y), (Xx, Y)) :-
   ( Xx is X+1 ; Xx is X-1).

And if the second argument is always ground (no variables):

adjacent((X,Y), (Xx, Yy)) :-
   abs(X-XX)+abs(Y-Yy) =:= 1.

You might consider using library(clpfd) which would permit you to state all four rules just as compactly as above version, but still would permit variables everywhere.

adjacent((X,Y), (Xx, Yy)) :-
   abs(X-Xx)+abs(Y-Yy) #= 1.

However, as a beginner, there are better examples getting acquainted with library(clpfd).

Upvotes: 4

Related Questions