Question

I try to create a simple program in prolog, but i have a problem:

:- dynamic at/2, i_am_holding/1, i_am_at/1.

/* some lines of code */

i_am_at(room1).

at(revolver, room1).

take(revolver) :- write('You picked up the revolver.'),nl.

take(X):- i_am_at(Place),
      assert(i_am_holding(X)),
      retract(at(X,Place)).

/* some lines of code */

I want the user to pick up the revolver,and then (the revolver)to be retracted from the place where he is in, so he won't be able to pick it up again.

When I run my code, the take(revolver) query runs, but the take(X) does not.

Was it helpful?

Solution

Mark is right on the money. You probably want to replace your whole code with something like this:

:- dynamic at/2, holding/1.

at(player, room1).
at(revolver, room1).

take(X) :-
    at(player, Place),
    at(X, Place),
    !,
    format('You pick up the ~a.~n', [X]),
    retract(at(X,Place)),
    assert(holding(X)).

take(X) :-
    holding(X),
    !,
    format('You''re already holding the ~a!~n', [X]).

There are a lot of interesting ways you could take this further. An operator is_at might make the code more readable:

take(X) :-
  player is_at Place,
  X is_at Place,
  ...

You could also have some nice case-based reasoning for getting the articles and whatnot right:

subject(X, Some_X) :- mass_noun(X), !, atom_concat('some ', X, Some_X).
subject(X, The_X)  :- atom_concat('the ', X, The_X).

mass_noun(water).

then you could integrate these into the output routines:

take(X) :- 
  ...
  subject(X, Subj),
  format('You take ~a.~n', [Subj]),
  ...

You could do some fun stuff with DCGs to generate the output too:

:- use_module(library(dcg/basics)).

success(take(X)) --> "You took ", subject(X).
subject(X) --> "the ", atom(X).

You can make that even more generic with some histrionics like this:

success_term(Command) --> { Command =.. CommandList }, success(CommandList).
success([Command, DirectObject]) --> 
  "You ", past_tense(Command), " ", subject(DirectObject), ".".

subject(Noun) --> "the ", atom(Noun).
past_tense(X) --> { past_tense(X, Y) }, atom(Y).

past_tense(take, took).
past_tense(X, Xed) :- atom_concat(X, 'ed', Xed).

Then run that like so: phrase(success_term(take(revolver)), X), format('~s~n', [X]) and you'll get You took the revolver., which is kind of neat.

These text adventures are a lot of fun to code. I recommend you go through the Amzi Prolog Nani Search tutorial if you haven't yet. There are a lot of great ideas in there!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top