:- ['5_flux'].
:- ['5_wumpus_simulator'].

init(Z0) :- Z0 = [has(arrow),wumpus(WX,WY),alive|Z],
	    [WX,WY] :: [1..5],
            not_holds(wumpus(1,1),Z0),
            not_holds_all(wumpus(_,_),Z),
            not_holds(pit(1,1),Z),
            not_holds_all(pit(_,0),Z),
            not_holds_all(pit(_,6),Z),
            not_holds_all(pit(0,_),Z),
            not_holds_all(pit(6,_),Z),
            not_holds_all(at(_,_),Z),
            not_holds_all(facing(_),Z),
            duplicate_free(Z0).

main :- init(Z0), execute(enter, Z0, Z1),
        Cpts = [[1,2]], Btr = [], Visited = [(1,1)],
        main_loop(Cpts, Btr, Visited, Z1).

/*------- implementation area -------------------*/

main_loop([Dirs|Cpts], Btr, Vis, Z0) :-
   write('Cpts:'), writeln([Dirs|Cpts]),
   write('Btr:'), writeln(Btr),
   write('Vis:'), writeln(Vis),
   writeln("------------------"),
   false. /*implement*/


try_wumpus_hunt(X,Y,Z1,Z2) :-  false. /*implement*/

explore(X,Y,D,Vis,Z1,Z2) :- false. /*implement*/

turn_to(D,Z1,Z2) :- false. /*implement*/

backtrack(_,[],_, _).
backtrack(Cpts,[Dir|Btr],Vis,Z) :- false. /*implement*/

/*------- end of implementation area ------------*/



%%%%%%%% auxiliary %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

 adjacent(X,Y,D,X1,Y1) :-
   [X,Y,X1,Y1]::1..5, D::1..4,
       (D#=1) #/\ (X1#=X)   #/\ (Y1#=Y+1) % north
   #\/ (D#=3) #/\ (X1#=X)   #/\ (Y1#=Y-1) % south
   #\/ (D#=2) #/\ (X1#=X+1) #/\ (Y1#=Y)   % east
   #\/ (D#=4) #/\ (X1#=X-1) #/\ (Y1#=Y).  % west

 in_direction(X,Y,D,X1,Y1) :-
   [X,Y,X1,Y1]::1..5, D::1..4,
       (D#=1) #/\ (X1#=X) #/\ (Y1#>Y)  % north
   #\/ (D#=3) #/\ (X1#=X) #/\ (Y1#<Y)  % south
   #\/ (D#=2) #/\ (X1#>X) #/\ (Y1#=Y)  % east
   #\/ (D#=4) #/\ (X1#<X) #/\ (Y1#=Y). % west

%%%%%%%% state update %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

 state_update(Z1,enter,Z2,[B,S,G]) :-
   update(Z1,[at(1,1),facing(1)],[],Z2),
   breeze_perception(1,1,B,Z2),
   stench_perception(1,1,S,Z2),
   glitter_perception(1,1,G,Z2).

 state_update(Z1,exit,Z2,[]) :-
   holds(facing(D),Z1),
   update(Z1,[],[at(1,1),facing(D)],Z2).

 state_update(Z1,turn,Z2,[]) :-
   holds(facing(D),Z1),
   (D#<4 #/\ D1#=D+1) #\/ (D#=4 #/\ D1#=1),
   update(Z1,[facing(D1)],[facing(D)],Z2).

 state_update(Z1,grab,Z2,[]) :-
   holds(at(X,Y),Z1),
   update(Z1,[has(gold)],[gold(X,Y)],Z2).

 state_update(Z1,shoot,Z2,[S]) :-
   ( S=true, update(Z1,[],[has(arrow),alive],Z2)
     ; S=false, update(Z1,[],[has(arrow)],Z2) ).

 state_update(Z1,go,Z2,[B,S,G]) :-
   holds(at(X,Y),Z1), holds(facing(D),Z1),
   adjacent(X,Y,D,X1,Y1),
   update(Z1,[at(X1,Y1)],[at(X,Y)],Z2),
   breeze_perception(X1,Y1,B,Z2),
   stench_perception(X1,Y1,S,Z2),
   glitter_perception(X1,Y1,G,Z2).

%%%%%%%% percepts %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

 stench_perception(X,Y,Percept,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) ).

 breeze_perception(X,Y,Percept,Z) :-
   XE#=X+1, XW#=X-1, YN#=Y+1, YS#=Y-1,
   ( Percept=false, not_holds(pit(XE,Y),Z),
                    not_holds(pit(XW,Y),Z),
                    not_holds(pit(X,YN),Z),
                    not_holds(pit(X,YS),Z) ;
     Percept=true,
       or_holds([pit(XE,Y),pit(X,YN),
           pit(XW,Y),pit(X,YS)],Z) ).

 glitter_perception(X,Y,Percept,Z) :-
   Percept=false, not_holds(gold(X,Y),Z) ;
   Percept=true,  holds(gold(X,Y),Z).
