:- ['4_flux'].
:- lib(fd).
%%%%% parameters %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
xdim(4).
ydim(4).
%%%%% state update axioms %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
state_update(Z1,turn_left,Z2) :-
holds(facing(D),Z1),
(D#>1 #/\ D1#=D-1) #\/ (D#=1 #/\ D1#=4),
update(Z1,[facing(D1)],[facing(D)],Z2).
state_update(Z1,turn_right,Z2) :-
holds(facing(D),Z1),
(D#<4 #/\ D1#=D+1) #\/ (D#=4 #/\ D1#=1),
update(Z1,[facing(D1)],[facing(D)],Z2).
state_update(Z1,go,Z2) :-
holds(at(X,Y),Z1),
holds(facing(D),Z1),
adjacent(X,Y,D,X1,Y1),
update(Z1,[at(X1,Y1)],[at(X,Y)],Z2).
%%%%% percepts %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
sf(sense_stench,Percept,Z) :-
holds(at(X,Y),Z),
XE#=X+1, XW#=X-1, YN#=Y+1, YS#=Y-1,
(Percept=false ->
not_holds(wumpus(XE,Y),Z),
not_holds(wumpus(XW,Y),Z),
not_holds(wumpus(X,YN),Z),
not_holds(wumpus(X,YS),Z)
;
Percept=true ->
or_holds([wumpus(XE,Y),wumpus(X,YN),wumpus(XW,Y),wumpus(X,YS)],Z)
).
%%%%% auxiliary predicates %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
adjacent(X,Y,D,X1,Y1) :-
xdim(XD), ydim(YD),
[X,X1]::[1..XD], [Y,Y1]::[1..YD], D :: [1..4],
X1#>0, Y1#>0,
((D#=1) #/\ (X1#=X) #/\ (Y1#=Y+1) #\/ % north
(D#=2) #/\ (X1#=X+1) #/\ (Y1#=Y) #\/ % east
(D#=3) #/\ (X1#=X) #/\ (Y1#=Y-1) #\/ % south
(D#=4) #/\ (X1#=X-1) #/\ (Y1#=Y) % west
).