%	Modified version of a simple robot problem solver published
%	in Byte magazine.


put(Object, Place) :-
	inside(Object, Place), !.
put(Object, Place) :-
	pickup(Object),
	moveto(Place),
	drop(Object).

pickup(Object) :-
	liftable(Object),
	inside(Object, Place),
	moveto(Place),
	emptyhand,
	assert(holding(Object)).

emptyhand :-
	holding(Object), !,
	drop(Object).
emptyhand.

drop(Object) :- retract(holding(Object)).

moveto(Place) :- inside(robot, Place), !.
moveto(Place) :-
	inside(robot, Place2), !,
	leave(Place2),
	enter(Place).
moveto(Place) :-
	outside(robot),
	enter(Place).

leave(Place) :-
	entrance(X, Place),
	unlock(X),
	retract(inside(robot, Place)),
	assert(outside(robot)),
	takeout(Place).

unlock(door) :-
	closed(door), !,
	get_key,
	retract(closed(door)).
unlock(X) :- closed(X), retract(closed(X)).
unlock(X).

get_key :- holding(key), !.
get_key :-
	inside(key, Place),
	pickup(key),
	leave(Place).

takeout(Place) :-
	holding(Object), !,
	retract(inside(Object, Place)),
	assert(outside(Object)).
takeout(_).

enter(Place) :-
	entrance(X, Place),
	unlock(X),
	retract(outside(robot)),
	assert(inside(robot, Place)),
	takein(Place).

takein(Place) :-
	holding(Object), !,
	retract(outside(Object)),
	assert(inside(Object, Place)).
takein(_).

inside(human, rocket).
inside(robot, rocket).
inside(fuel, building).
inside(key, cave).
inside(gold, cave).

entrance(airlock, rocket).
entrance(door, building).
entrance(hole, cave).

closed(airlock).
closed(door).

liftable(key).
liftable(fuel).
liftable(gold).

run :-
	print("The robot will move some gold from a cave to a rocket."),
	print("Watch the trace of the program to see what the robot does."),
	trace [pickup,moveto,leave,enter,put,inside,entrance,takein,takeout],
	nl,
	put(gold, rocket).
