%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                              BOMB IN THE TOILET                            %
% Fluents:                                                                   %
%      1. in(X) is true if packge(X) contains the bomb                       %
%      2. armed is true if one package contains bomb                         %
%      3. clogged is true if the toilet is clogged                           %
% Actions:                                                                   %
%      1. dunk(X) makes the bomb defused if package X has the bomb           %
%            Otherwise, it makes the toilet clogged. This action is          %
%            executable	when the toilet is not clogged.     		     %
%      2. detect_metal(X) determines whether package(X) has the bomb or not  %
% Initial State:                                                             %
%      One of package contains the bomb. The domain cannot represent this    %
%          fact. Rather, it's supposed that we have no information about     %		 	         
%          which package(s) that has bomb                                    %
%      Armed is true                                                         %
%      The toilet is clogged                                                 %
% Goal:                                                                      %
%      Not armed                                                             %
%      Not clogged                                                           %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% packages
package(1).
package(2).
package(3).
package(4).
package(5).

% actions
action(dunk(X)):- package(X).
action(detect_metal(X)) :- package(X).

% fluents
fluent(in(X)):- package(X).
fluent(armed).
fluent(clogged).

noninertial(armed).

% effects
causes(dunk(X), neg(in(X)), [in(X)]) :- package(X).
causes(dunk(X), clogged, [neg(in(X))]) :- package(X).


determines(detect_metal(X), in(X)) :- package(X).
determines(detect_metal(X), neg(in(X))) :- package(X).

% preconditions
executable(dunk(X), [neg(clogged)]):- package(X).
executable(detect_metal(X), []) :- package(X).

% initially: one of packages has bomb
initially(armed).
initially(neg(clogged)).

% static laws
caused([in(X)], armed) :- package(X).
caused([neg(in(1)), neg(in(2)), neg(in(3)), neg(in(4)), neg(in(5))], neg(armed)).

caused(L, F):- 
       member(F, [in(1), in(2), in(3), in(4), in(5)]),
       select(F, [in(1), in(2), in(3), in(4), in(5)],
              Q),
       neq_I(Q, L).

neq_I([],[armed]).

neq_I([H|L],[neg(H)|L1]):- neq_I(L,L1).

caused([in(I)], neg(in(J))):- package(I), package(J), neq(I, J).


% goal
sgoal(neg(armed)).
sgoal(neg(clogged)).

