0

I have the following facts that build ne of the wings of my dungeon.

path(room1,e,room2).
path(room2,w,room1).
path(room2,e,room5).
path(room5,w,room2).
path(room5,e,room6).
path(room6,w,room5).
path(room2,n,room3).
path(room3,s,room2).
path(room3,e,room4).
path(room4,w,room3).
path(room4,s,room5).
path(room5,n,room4).
path(room5,s,room7).
path(room7,n,room5).
path(room7,e,room8) :- at(key, in_hand).
path(room7,e,room8) :- write('The door appears to be locked.'), nl, fail.
path(room8,w,room7).
path(room2,s,room9).
path(room9,n,room2).
path(room9,s,room10).
path(room10,n,room9).
path(room10,w,room11).
path(room11,e,room10).
path(room11,s,room12).
path(room12,n,room11).

now i want to check if i one room is connected to another and then perhaps display one of the possible paths. i tried to do something like this connected(X,Y):-path(X,_,Z),path(Z,_,Y). but it keeps giving me false, what am i doing wrong.

false
  • 10,264
  • 13
  • 101
  • 209
Garmagon117
  • 225
  • 3
  • 13
  • What exactly did you try that "keeps giving you false"? Your predicate `connect` doesn't always return `false`. Querying `connected(room1, Y).` for example yields multiple solutions. – lurker Nov 11 '14 at 11:16
  • tried that but it only gives me 3 results when it is actually connected to 77 other rooms. also if you do connected(room1,room2) it will be false – Garmagon117 Nov 11 '14 at 17:39
  • 1
    You have to think about what *connected* means. Right now, your predicate says that *`X` is connected to `Y` if there is a path from `X` to some other point `Z`, AND a path from `Z` to the point `Y`*. Does that sound like it covers all of the cases of connected? It certainly doesn't handle the case of two neighboring rooms unless they happen to have an intermediate connected room as well. It also enforces only one intermediate connected room. You need to expand your definition to include immediate adjoining rooms, and many connecting rooms, which could be done recursively. – lurker Nov 11 '14 at 17:44

1 Answers1

0

Try something like

connect(Bgn,End,Path) :-    % to find a path between two nodes in the graph
  connected(Bgn,End,[],P) , % - we invoke the helper, seeding the visited list as the empty list
  reverse(P,Path)           % - on success, since the path built has stack semantics, we need to reverse it, unifying it with the result
  .

connected(X,Y,V,[X,Y|V]) :- % can we get directly from X to Y?
  path(X,_,Y)               % - if so, we succeed, marking X and Y as visited
  .                         %
connected(X,Y,V,P) :-       % otherwise...
  path(X,_,T) ,             % - if a path exists from X to another room (T)
  T \= Y ,                  % - such that T is not Y
  \+ member(X,V) ,          % - and we have not yet visited X
  connected(T,Y,[X|V],P)    % - we continue on, marking X as visited.
  .

You'll note the test for having visited the room before. If your graph has cycles, if you don't have some sort of test for having previously visited the node, you'll wind up going around and around in circles...until you get a stack overflow.

Nicholas Carey
  • 71,308
  • 16
  • 93
  • 135