
%% Locations: 

:-  dynamic(you_have/1),
    dynamic(location/2),
    dynamic(is_closed/1),
    dynamic(is_open/1).

location(egg,duck_pen).
location(ducks,duck_pen).
location(fox,woods).
location(you,house).

connect(yard,house).
connect(yard,woods).

connect(duck_pen,yard) :- is_open(gate).

is_closed(gate).

%% Moving around: 

goto(X) :- 
    location(you,L), 
    (connect(L,X); connect(X,L)),
    retract(location(you,L)),
    assert(location(you,X)),
    write(' You are in the '), 
    write(X), write('.'), nl.
goto(X) :- write(' You cannot get to the '),
    write(X), write(' from here.'), nl.

%% Picking up the egg: 

pick(egg) :- 
    location(you,duck_pen),
    not(you_have(egg)),
    assert(you_have(egg)),
    write(' You picked the egg '), nl.
pick(_) :- write(' Nothing to pick here. '), nl.

%% Opening the gate: 

open(gate) :- 
    location(you,yard),
    is_closed(gate),
    retract(is_closed(gate)),
    assert(is_open(gate)),
    write(' Opened. '), nl.
open(X) :- write(' You cannot open '), write(X), write('.'), nl.

%% How the other creatures react: 

ducks :- 
    is_open(gate),
    retract(location(ducks,duck_pen)),
    assert(location(ducks,yard)).
ducks.

fox :- 
    location(ducks,yard),
    location(you,house),
    write(' The fox has taken a duck.'), nl.
fox.

%% The main loop: 

go :- done.
go :- 
    write('>> '),
    read(X),
    call(X),
    go.

done :- 
    location(you,house),
    you_have(egg),
    ducks, fox,
    write(' Thanks for getting the egg. '), nl.

/*

  An example of interaction: 

  ?- go.
  >>goto(yard).
   You are in the yard
  >>goto(duck_pen).
   You cannot get there from here 
  >>pick(egg).
   There is nothing to pick 
  >>open(gate).
   Opened. 
  >>goto(duck_pen).
   You are in the duck_pen
  >>pick(egg).
   You picked the egg 
  >>goto(house).
   You cannot get there from here 
  >>goto(yard).
   You are in the yard
  >>goto(house).
   You are in the house
   The fox has taken a duck 
   Thanks for getting the egg.
  true

*/