%Solution to problem 1
%Solve maze by following the left wall
%Solution prints by calling "solve"

% 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]).

badSpot([X,Y]) :- wall([X,Y]).
badSpot([X,Y]) :- X < 1; Y < 1.
badSpot([X,Y]) :- mazeSize([W, H]), (X > W; Y > H).

%up
move([CurrX, CurrY], [CurrX, NextY], Direction) :- Direction = up, NextY is CurrY - 1.
%down
move([CurrX, CurrY], [NextX, NextY], Direction) :- Direction = down, NextY is CurrY + 1, NextX = CurrX.
%left
move([CurrX, CurrY], [NextX, NextY], Direction) :- Direction = left, NextY = CurrY, NextX is CurrX - 1.
%right
move([CurrX, CurrY], [NextX, NextY], Direction) :- Direction = right, NextY = CurrY, NextX is CurrX + 1.

%check: Make sure left hand is following wall.
check(List, Result, Location, New) :- List = [Current|_], move(Location, NewLoc, Current), \+badSpot(NewLoc),
	New = NewLoc, Result = Current.
check(List, Result, Location, New) :- List = [Current|Next], move(Location, NewLoc, Current), badSpot(NewLoc),
	check(Next, Result, Location, New).
check(List, Result, Location, New) :- List = [Current], move(Location, NewLoc, Current), \+badSpot(NewLoc),
	New = NewLoc, Result = Current.


%solve: Print a solution to the maze.
solve(CurrentLocation, _, Path) :- end(CurrentLocation), Path = [CurrentLocation].

solve(CurrentLocation, right, Path) :- List = [up, right, down, left],
	check(List, Result, CurrentLocation, New), solve(New, Result, NewPath), Path = [CurrentLocation|NewPath].
	
solve(CurrentLocation, left, Path) :- List = [down, left, up, right],
	check(List, Result, CurrentLocation, New), solve(New, Result, NewPath), Path = [CurrentLocation|NewPath].
	
solve(CurrentLocation, up, Path) :- List = [left, up, right, down],
	check(List, Result, CurrentLocation, New), solve(New, Result, NewPath), Path = [CurrentLocation|NewPath].
	
solve(CurrentLocation, down, Path) :- List = [right, down, left, up],
	check(List, Result, CurrentLocation, New), solve(New, Result, NewPath), Path = [CurrentLocation|NewPath].
	
solve() :- start(Start), start([X,_]), X = 1, solve(Start, right, Path), write(Path).
solve() :- start(Start), start([_,Y]), Y = 1, solve(Start, down, Path), write(Path).
solve() :- start(Start), start([X,_]), mazeSize([SX,_]), X = SX, solve(Start, left, Path), write(Path).
solve() :- start(Start), start([_,Y]), mazeSize([_,SY]), Y = SY, solve(Start, up, Path), write(Path).	


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).