0

I am playing the game Dishonored 2

There is a puzzle in the game, see the picture below (no spoilers).

Riddle

Naturally I wanted to solve this using Prolog. I have looked around and other people have made Prolog programs to solve the riddle, but I would like to know why my solution does not work. In particular, it gives a Warning: Goal (directive) failed, and returns true with no other output.

The code:

% dishonered 2 jindosh riddle

exists(A,(A,_,_,_,_)).
exists(A,(_,A,_,_,_)).
exists(A,(_,_,A,_,_)).
exists(A,(_,_,_,A,_)).
exists(A,(_,_,_,_,A)).

rightOf(A, B, (B,A,_,_,_)).
rightOf(A, B, (_,B,A,_,_)).
rightOf(A, B, (_,_,B,A,_)).
rightOf(A, B, (_,_,_,B,A)).

middlePerson(A,(_,_,A,_,_)).

firstPerson(A, (A,_,_,_,_)).
second(A,(_,A,_,_,_)).
third(A,(_,_,A,_,_)).
fourth(A,(_,_,_,A,_)).
lastPerson(A,(_,_,_,_,A)).

nextTo(A,B,H) :- rightOf(A,B,H).
nextTo(A,B,H) :- rightOf(B,A,H).

:-  exists(person(winslow,green,_,_,_), People),
    firstPerson(person(contee,_,_,_,_), People),
    nextTo(person(contee,_,_,_,_),person(_,white,_,_,_,_), People),
    rightOf(person(_,blue,_,_,_,_),person(_,purple,_,_,_,_), People),
    exists(person(_,purple,absinthe,_,_), People),
    exists(person(_,red,_,dabokva,_), People),
    nextTo(person(_,_,_,_,_,snufftin),person(_,_,_,_,dabokva,_), People),
    exists(person(finch,_,_,_,ring), People),
    exists(person(_,_,_,karnaca,bird), People),
    nextTo(person(_,_,_,_,diamond),person(_,_,_,dunwall,_), People),
    nextTo(person(_,_,_,dunwall,_),person(_,_,wine,_,_), People),
    exists(person(marcolla,_,whiskey,_,_), People),
    exists(person(_,_,rum,fraeport,_), People),
    middlePerson(person(_,_,beer,_,_), People),
    exists(person(natsiou,_,_,baleton,_), People),
    exists(person(_,_,_,_,warmedal), People),
    firstPerson(person(Aperson,Acolour,Adrink,Aloc,Aheir), People),
    second(person(Bperson,Bcolour,Bdrink,Bloc,Bheir), People),
    third(person(Cperson,Ccolour,Cdrink,Cloc,Cheir), People),
    fourth(person(Dperson,Dcolour,Ddrink,Dloc,Dheir), People),
    lastPerson(person(Eperson,Ecolour,Edrink,Eloc,Eheir), People),
    format('The first person is the ~w person~n', (Aperson,Acolour,Adrink,Aloc,Aheir)),
    format('The second person is the ~w person~n', (Bperson,Bcolour,Bdrink,Bloc,Bheir)),
    format('The third person is the ~w person~n', (Cperson,Ccolour,Cdrink,Cloc,Cheir)),
    format('The fourth person is the ~w person~n', (Dperson,Dcolour,Ddrink,Dloc,Dheir)),
    format('The last person is the ~w person~n', (Eperson,Ecolour,Edrink,Eloc,Eheir)).

The command and output:

?- [dishonored].
Warning: c:/users/<USERNAME>/documents/prolog/dishonored.pl:25:
Warning:    Goal (directive) failed: user:(exists(person(winslow,green,_7036,_7058,_7080),_7102),firstPerson(person(contee,_7198,_7220,_7242,_7264),_7102),nextTo(person(contee,_7392,_7414,_7436,_7458),person(_7480,white,_7502,_7524,_7546,_7568),_7102),rightOf(person(_7702,blue,_7724,_7746,_7768,_7790),person(_7812,purple,_7834,_7856,_7878,_7900),_7102),exists(person(_7992,purple,absinthe,_8014,_8036),_7102),exists(person(_8128,red,_8150,dabokva,_8172),_7102),nextTo(person(_8306,_8328,_8350,_8372,_8394,snufftin),person(_8416,_8438,_8460,_8482,dabokva,_8504),_7102),exists(person(finch,_8596,_8618,_8640,ring),_7102),exists(person(_8732,_8754,_8776,karnaca,bird),_7102),nextTo(person(_8898,_8920,_8942,_8964,diamond),person(_8986,_9008,_9030,dunwall,_9052),_7102),nextTo(person(_9174,_9196,_9218,dunwall,_9240),person(_9262,_9284,wine,_9306,_9328),_7102),exists(person(marcolla,_9420,whiskey,_9442,_9464),_7102),exists(person(_9556,_9578,rum,fraeport,_9600),_7102),middlePerson(person(_9698,_9720,beer,_9742,_9764),_7102),exists(person(natsiou,_9856,_9878,baleton,_9900),_7102),exists(person(_9998,_10020,_10042,_10064,warmedal),_7102),firstPerson(person(_10168,_10190,_10212,_10234,_10256),_7102),second(person(_10360,_10382,_10404,_10426,_10448),_7102),third(person(_10552,_10574,_10596,_10618,_10640),_7102),fourth(person(_10744,_10766,_10788,_10810,_10832),_7102),lastPerson(person(_10936,_10958,_10980,_11002,_11024),_7102),format('The first person is the ~w person~n',(_10168,_10190,_10212,_10234,_10256)),format('The second person is the ~w person~n',(_10360,_10382,_10404,_10426,_10448)),format('The third person is the ~w person~n',(_10552,_10574,_10596,_10618,_10640)),format('The fourth person is the ~w person~n',(_10744,_10766,_10788,_10810,_10832)),format('The last person is the ~w person~n',(_10936,_10958,_10980,_11002,_11024)))
**true.**

I am running SWIPL.

My format for the 5-tuple is (name, colour, drink, location, heirloom).

I have looked for what Goal (directive) failed means, finding this, but my error does not occur during importing the file. There is also another SO post but the solution does not apply to me.

I have seen SO user false give answers to some zebra-puzzle related SO questions, but I do not understand them.

I asked ChatGPT, but it spouted nonsense. (It did fix a few typos though!)

I have solved a zebra puzzle using Prolog before, using very similar structure, so am particularly confused as to why this doesn't work. If it as simple as I mistranslated the rules I will be sad.

false
  • 10,264
  • 13
  • 101
  • 209
CricGuru
  • 5
  • 1

2 Answers2

2

You can localize the error without understanding your program. Your problem is that (in a pure monotonic program such as yours when removing the formats) a query fails unexpectedly. If we can remove one goal of your failing query and the resulting query still fails, then (at least) one problem must be in the remaining query. In this manner we generalize the program and narrow down the wall of text to something more readable. In your case a maximal generalization is:

:- op(950, fy, *).

*_G_0.

query :-
   * exists(person(winslow,green,_,_,_), People),
   * firstPerson(person(contee,_,_,_,_), People),
   * nextTo(person(contee,_,_,_,_),person(_,white,_,_,_,_), People),
   rightOf(person(_,blue,_,_,_,_),person(_,purple,_,_,_,_), People),
   * exists(person(_,purple,absinthe,_,_), People),
   * exists(person(_,red,_,dabokva,_), People),
   * nextTo(person(_,_,_,_,_,snufftin),person(_,_,_,_,dabokva,_), People),
   * exists(person(finch,_,_,_,ring), People),
   * exists(person(_,_,_,karnaca,bird), People),
   * nextTo(person(_,_,_,_,diamond),person(_,_,_,dunwall,_), People),
   * nextTo(person(_,_,_,dunwall,_),person(_,_,wine,_,_), People),
   * exists(person(marcolla,_,whiskey,_,_), People),
   * exists(person(_,_,rum,fraeport,_), People),
   * middlePerson(person(_,_,beer,_,_), People),
   * exists(person(natsiou,_,_,baleton,_), People),
   * exists(person(_,_,_,_,warmedal), People),
   * firstPerson(person(Aperson,Acolour,Adrink,Aloc,Aheir), People),
   second(person(Bperson,Bcolour,Bdrink,Bloc,Bheir), People),
   * third(person(Cperson,Ccolour,Cdrink,Cloc,Cheir), People),
   fourth(person(Dperson,Dcolour,Ddrink,Dloc,Dheir), People),
   * lastPerson(person(Eperson,Ecolour,Edrink,Eloc,Eheir), People).

Now this still looks a bit intimidating, so by removing the generalized goals we get:

query2 :-
   rightOf(person(_,_/*blue*/,_,_,_,_),person(_,_/*purple*/,_,_,_,_), People),
   second(person(Bperson,Bcolour,Bdrink,Bloc,Bheir), People),
   fourth(person(Dperson,Dcolour,Ddrink,Dloc,Dheir), People).

Because this fragment already fails, there must be some error in it. Note that also blue and purple have been generalized away. So no concrete names are responsible for this failure.

This was just one such generalization. There are more. But it seems to be enough to understand the problem.

false
  • 10,264
  • 13
  • 101
  • 209
0

First problem: 6 elements rather than 5, in:

nextTo(person(_,_,_,_,_,snufftin),person(_,_,_,_,dabokva,_), People),

Also 6 in:

nextTo(person(contee,_,_,_,_),person(_,white,_,_,_,_), People)

Also 6 in:

rightOf(person(_,blue,_,_,_,_),person(_,purple,_,_,_,_), People),

Fixing those 3 issues, it produces 1 solution.

brebs
  • 3,462
  • 2
  • 3
  • 12