%Row 1
wall([X,1]) :- X =\= 2.
% Row 2
wall([X,2]) :- X = 1; X = 4; X = 6.
% Row 3
wall([X,3]) :- X = 1; X = 2; X = 6.
% Row 4
wall([X,4]) :- X =\= 3,X =\= 5.
% Row 5
wall([X,5]) :- X = 1; X = 4; X = 6.
% Row 6
wall([X,6]) :- X =\= 2.
% Start / end
start([2,1]).
end([2,6]).
% Maze Size
mazeSize([6,6]).
 
% Direction you are facing in the maze
direction(north).
direction(south).
direction(east).
direction(west).

% move from a direction
%north
move([CurrX, CurrY],[CurrX, NextY],Direction) :- north = Direction , NextY is CurrY - 1.
%south
move([CurrX, CurrY],[CurrX, NextY],Direction) :- south = Direction , NextY is CurrY + 1.
%east
move([CurrX,CurrY],[NextX,CurrY],Direction):- east = Direction, NextX is CurrX + 1.
%west
move([CurrX,CurrY],[NextX,CurrY],Direction):- west = Direction, NextX is CurrX - 1.

% turn left 
turnleft(Direction,NewDirection):- Direction = north, NewDirection = west.
turnleft(Direction,NewDirection):- Direction = west, NewDirection = south.
turnleft(Direction,NewDirection):- Direction = south, NewDirection = east.
turnleft(Direction,NewDirection):- Direction = east, NewDirection = north.
% trun right
turnright(Direction,NewDirection):- Direction = north, NewDirection = east.
turnright(Direction,NewDirection):- Direction = west, NewDirection = north.
turnright(Direction,NewDirection):- Direction = south, NewDirection = west.
turnright(Direction,NewDirection):- Direction = east, NewDirection = south.
% get the left pos
getleft([CurrX,CurrY],[NextX,CurrY],Direction):- north = Direction, NextX is CurrX -1.
getleft([CurrX,CurrY],[CurrX,NextY],Direction):- west = Direction, NextY is CurrY + 1. 
getleft([CurrX,CurrY],[NextX,CurrY],Direction):- south = Direction, NextX is CurrX + 1.
getleft([CurrX,CurrY],[CurrX,NextY],Direction):- east = Direction, NextY is CurrY - 1.

flip(Direction,NewDirection):- Direction = south , NewDirection = north.
flip(Direction,NewDirection):- Direction = north , NewDirection = south.

badSpot([X,Y]) :- wall([X,Y]).
badSpot([X,Y]) :- X < 1; Y < 1.
badSpot([X,Y]) :- mazeSize([W, H]), (X > W; Y > H).

solve(CurrentLocation,Path,_):- end(CurrentLocation),Path = [CurrentLocation].
% there is a wall to the left
solve(CurrentLocation,Path,Direction):- getleft(CurrentLocation,Left,Direction),wall(Left),
    move(CurrentLocation,NextLocation,Direction),\+badSpot(NextLocation),
    solve(NextLocation,RestOfPath,Direction),
    Path = [CurrentLocation|RestOfPath].
% run into wall 
% no wall to the left
solve(CurrentLocation,Path,Direction):-getleft(CurrentLocation,Left,Direction),\+wall(Left),
    turnleft(Direction,NewDirection),
    move(CurrentLocation,NewNextLocation,NewDirection),\+badSpot(NewNextLocation),
    solve(NewNextLocation,RestOfPath,NewDirection), Path = [CurrentLocation|RestOfPath].
% wall to the left
solve(CurrentLocation,Path,Direction):-getleft(CurrentLocation,Left,Direction),wall(Left),
    turnright(Direction,NewDirection),
    move(CurrentLocation,NewNextLocation,NewDirection),\+badSpot(NewNextLocation),
    solve(NewNextLocation,RestOfPath,NewDirection), Path = [CurrentLocation|RestOfPath].
% in a corner
solve(CurrentLocation,Path,Direction):-flip(Direction,NewDirection),
    solve(CurrentLocation, RestOfPath,NewDirection), Path =[CurrentLocation|RestOfPath]. 




% Convenience rule
solve(Path) :- start(Start), solve(Start,Path,south).


drawCell(Column, Row, _) :- wall([Column, Row]), write("X"), !.
drawCell(Column, Row, _) :- start([Column, Row]), write("S"), !.
drawCell(Column, Row, _) :- end([Column, Row]), write("E"), !.
drawCell(Column, Row, Path) :- member([Column, Row], Path), write("P"), !.
drawCell(_, _, _) :- write("O").

drawRow(Row, Path) :- drawCell(1, Row, Path), tab(1), drawCell(2, Row, Path), tab(1), 
        drawCell(3, Row, Path), tab(1), drawCell(4, Row, Path), tab(1), 
        drawCell(5, Row, Path), tab(1), drawCell(6, Row, Path), nl.
                
draw :- drawRow(1, []), drawRow(2, []), drawRow(3, []), drawRow(4, []), drawRow(5, []), 
        drawRow(6, []).
draw(Path) :- drawRow(1, Path), drawRow(2, Path), drawRow(3, Path), drawRow(4, Path),
        drawRow(5, Path), drawRow(6, Path).