%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%									% 
% Multimedia Authoring II 2006		%
%									%
% Marco Bouterse - 1142828			%
%									%
% Final Project - "Checkpoint City" %
%									%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%





% Controller object
%
% Sets up the different opjects


:-object ccity : [bcilib].



% URL of the VRML world
var url = './city/prototypes/city.wrl'.

main :-
	
	% Enable debug output
	text_area(Browser),
	set_output(Browser),

	% Load the world
	loadURL(url),
	format('The  game will start in 5 seconds,~n'),
    sleep(5000),
	format('The game has started.~n'),


	% Start Traffic 
	_Traffic1 := new(traffic(car1, position(41, 0.55, 6.5))),
	sleep(100),

	_Traffic2 := new(traffic(car2, position(129, 0.55, 163.5))),
	sleep(100),

	_Traffic3 := new(traffic(car3, position(86.5, 0.55, 89))),
	sleep(100),

	_Traffic4 := new(traffic(car4, position(3.5, 0.55, 41))),
	sleep(100),

	_Traffic5 := new(traffic(car5, position(41, 0.55, 86.5))),
	sleep(100),

	% Start checkpoints
	_Checkpoint := new(checkpoint),

	% Start player control
 	_Car := new(player_car).


:-end_object ccity.





% Player object
%
% Controls the player's car

:-object player_car : [bcilib].

var distanceBetweenCrossings = 40.

player_car :-
	format('Car thread active.~n'),
	setSFBool(ts1,enabled,true),
	update.


% Car control loop
update :- 

	repeat,
		
		getRotation(carTransform,0,1,0,R),	
		getPosition(carTransform,X,_Y,Z),

		keep_car_from_drifting(X,Z),	

		X1 is (X mod distanceBetweenCrossings),
		Z1 is (Z mod distanceBetweenCrossings),

		CX is ((X//distanceBetweenCrossings) + 1),
		CZ is ((Z//distanceBetweenCrossings) + 1),	
	
		decide_action(R,X1,Z1,CX,CZ,Action),

		nonvar(Action),	
		do_action(R,Action),
	
		delay(50),

	fail,
	!.

keep_car_from_drifting(X,_) :- X < 0, do_action(0.0,reset_car), !.
keep_car_from_drifting(X,_) :- X > 170, do_action(0.0,reset_car), !.
keep_car_from_drifting(_,Z) :- Z < 0, do_action(0.0,reset_car), !.
keep_car_from_drifting(_,Z) :- Z > 170, do_action(0.0,reset_car), !.
keep_car_from_drifting(_,_) :- !.


%decide_action(CarAngle,Xpos,Zpos,CrossingX,CrossingZ,Action)
%
% Finds the action to execute based on current location and player input

% ERROR CONTROL - If car drifts off track, reset it.
decide_action(_,_,_,CX,_,reset_car) :- CX < 1, !.
decide_action(_,_,_,CX,_,reset_car) :- CX > 5, !.
decide_action(_,_,_,_,CZ,reset_car) :- CZ < 1, !.
decide_action(_,_,_,_,CZ,reset_car) :- CZ > 5, !.

% If car is not on a crossing, just go straight
decide_action(_,X,_,_,_,keep_going) :- X > 7, !.
decide_action(_,X,_,_,_,keep_going) :- X < 3, !.
decide_action(_,_,Z,_,_,keep_going) :- Z > 7, !.
decide_action(_,_,Z,_,_,keep_going) :- Z < 3, !.

% If car on a crossing and right key is pressed, turn to right (if possible)
decide_action( 0.0 ,_,_,CX,CZ,turn_right) :-  
	getSFInt32(carControl,rightDown,1), 
	CZ1 is CZ + 1, 
	connected([CX,CZ],[CX,CZ1]), 
	!.

decide_action( 1.57,_,_,CX,CZ,turn_right) :-  
	getSFInt32(carControl,rightDown,1), 
	CX1 is CX + 1, 
	connected([CX,CZ],[CX1,CZ]), 
	!.

decide_action( 3.14,_,_,CX,CZ,turn_right) :-  
	getSFInt32(carControl,rightDown,1), 
	CZ1 is CZ - 1, 
	connected([CX,CZ],[CX,CZ1]), 
	!.

decide_action(-1.57,_,_,CX,CZ,turn_right) :-  
	getSFInt32(carControl,rightDown,1), 
	CX1 is CX - 1, 
	connected([CX,CZ],[CX1,CZ]), 
	!.

% If car is on a crossing and left key is pressed, turn to left (if possible)
decide_action( 0.0 ,_,_,CX,CZ,turn_left) :-  
	getSFInt32(carControl,leftDown,1), 
	CZ1 is CZ - 1, 
	connected([CX,CZ],[CX,CZ1]), 
	!.

decide_action( 1.57,_,_,CX,CZ,turn_left) :-  
	getSFInt32(carControl,leftDown,1), 
	CX1 is CX - 1, 
	connected([CX,CZ],[CX1,CZ]), 
	!.

decide_action( 3.14,_,_,CX,CZ,turn_left) :-  
	getSFInt32(carControl,leftDown,1), 
	CZ1 is CZ + 1, 
	connected([CX,CZ],[CX,CZ1]), 
	!.

decide_action(-1.57,_,_,CX,CZ,turn_left) :-  
	getSFInt32(carControl,leftDown,1), 
	CX1 is CX + 1, 
	connected([CX,CZ],[CX1,CZ]), 
	!.

% If there is no input, let car go forward on the crossing if possible
decide_action( 0.0 ,_,_,CX,CZ,keep_going) :- 
	CX1 is CX + 1, 
	connected([CX,CZ],[CX1,CZ]), 
	!.

decide_action( 1.57,_,_,CX,CZ,keep_going) :- 
	CZ1 is CZ - 1, 
	connected([CX,CZ],[CX,CZ1]), 
	!.

decide_action( 3.14,_,_,CX,CZ,keep_going) :- 
	CX1 is CX - 1, 
	connected([CX,CZ],[CX1,CZ]), 
	!.

decide_action(-1.57,_,_,CX,CZ,keep_going) :- 
	CZ1 is CZ + 1, 
	connected([CX,CZ],[CX,CZ1]), 
	!.

% If there is no input and forward is not possible, go right
decide_action( 0.0 ,_,_,CX,CZ,turn_right) :- 
	CZ1 is CZ + 1, 
	connected([CX,CZ],[CX,CZ1]), 
	!.

decide_action( 1.57,_,_,CX,CZ,turn_right) :- 
	CX1 is CX + 1, 
	connected([CX,CZ],[CX1,CZ]), 
	!.

decide_action( 3.14,_,_,CX,CZ,turn_right) :- 
	CZ1 is CZ - 1, 
	connected([CX,CZ],[CX,CZ1]), 
	!.

decide_action(-1.57,_,_,CX,CZ,turn_right) :- 
	CX1 is CX - 1, 
	connected([CX,CZ],[CX1,CZ]), 
	!.

% If there is no input and forward & right are not possible, go left
decide_action( 0.0 ,_,_,CX,CZ,turn_left) :- 
	CZ1 is CZ - 1, 
	connected([CX,CZ],[CX,CZ1]), 
	!.

decide_action( 1.57,_,_,CX,CZ,turn_left) :- 
	CX1 is CX - 1, 
	connected([CX,CZ],[CX1,CZ]), 
	!.

decide_action( 3.14,_,_,CX,CZ,turn_left) :- 
	CZ1 is CZ + 1, 
	connected([CX,CZ],[CX,CZ1]), 
	!.

decide_action(-1.57,_,_,CX,CZ,turn_left) :- 
	CX1 is CX + 1, 
	connected([CX,CZ],[CX1,CZ]), 
	!.

% If nothing succeeds, return no_action
decide_action(_,_,_,_,_,no_action) :- !.



%do_action(CarRotation,Action)
%
% Executes the given action

% Reset car to original position
do_action(_,reset_car) :- setPosition(carTransform,10,0.55,6.5), setRotation(carTransform,0,1,0,0.0), !.

% Just let the car keep going forward (handled in vrml)
do_action(_,keep_going) :- !.

% Make the car turn to the right
do_action(-1.57,turn_right) :-
	setRotation(carTransform,0,1,0,3.14),
	delay(1000), 
	!.

do_action(R,turn_right) :-
	R1 is R - 1.57,
	setRotation(carTransform,0,1,0,R1), 
	delay(1000), 
	!.

% Make the car turn to the left
do_action(3.14,turn_left) :-
	setRotation(carTransform,0,1,0,-1.57), 
	delay(1000), 
	!.

do_action(R,turn_left) :- 
	R1 is R + 1.57, 
	setRotation(carTransform,0,1,0,R1), 
	delay(1000), 
	!.

% Not a recognised action
do_action(_,_) :- format('ERROR'), !.


%connected(CrossingA,CrossingB)
%
% Two crossings are connected if there exists a road from A to B or from B to A

connected([X1,Z1],[X2,Z2]) :- road([X1,Z1],[X2,Z2]) ; road([X2,Z2],[X1,Z1]).


%road([X1,Z1],[X2,Z2]
%
% Represents road that connects [X1,Z1] with [X2,Z2]
% The roadmap looks like this:

%
% 	1	2	3	4	5
% 1 * - * - * - * - *
%   |   |   |   |   |
% 2 * - * - * - *   *
%   |   |   |   |   |
% 3 * - * - * - *   *
%   |   |   |   |   |
% 4 *   * - * - * - *
%   |       |   |   |
% 5 * - * - * - * - *
%


road([1,1],[2,1]).
road([1,1],[1,2]).
road([2,1],[3,1]).
road([2,1],[2,2]).
road([3,1],[4,1]).
road([3,1],[3,2]).
road([4,1],[5,1]).
road([4,1],[4,2]).
road([5,1],[5,2]).
road([1,2],[2,2]).
road([1,2],[1,3]).
road([2,2],[3,2]).
road([2,2],[2,3]).
road([3,2],[4,2]).
road([3,2],[3,3]).
road([4,2],[4,3]).
road([5,2],[5,3]).
road([1,3],[2,3]).
road([1,3],[1,4]).
road([2,3],[3,3]).
road([2,3],[2,4]).
road([3,3],[4,3]).
road([3,3],[3,4]).
road([4,3],[4,4]).
road([5,3],[5,4]).
road([1,4],[1,5]).
road([2,4],[3,4]).
road([3,4],[4,4]).
road([3,4],[3,5]).
road([4,4],[5,4]).
road([4,4],[4,5]).
road([5,4],[5,5]).
road([1,5],[2,5]).
road([2,5],[3,5]).
road([3,5],[4,5]).
road([4,5],[5,5]).


:-end_object player_car.




% Checkpoint object
%
% Handles checkpoints and timer


:-object checkpoint : [bcilib].

var nrOfCheckPoints = 20.
var collisionRadius = 3.

checkpoint :-
	
	format('Checkpoint thread active.~n'),
	setSFBool(ts2,enabled,true),
	game_loop(nrOfCheckPoints).


%game_loop(CheckpointID)
%
% Main control loop for checkpoint thread

game_loop(0) :- 

	format('YOU WIN!!'), 
	setSFBool(ts2,enabled,false).

game_loop(CP) :- 

	checkpoint(CP, X, Y, Z, T),
	setPosition(checkPt,X,Y,Z),
 
	getSFInt32(countScript,clock,C), 
	C1 is C + T, 
	setSFInt32(countScript,clock,C1),

	setSFBool(cpSound,loop,true),
	sleep(800),
	setSFBool(cpSound,loop,false),  

	check_collision(X,Z,10),

	CP1 is CP - 1,
	game_loop(CP1).

game_loop(_):- format('ERROR!'), !.


%check_collision(CarX,CarZ,DistanceToCar)
%
% Keeps looping until the distance between the car and checkpoint is small enough

check_collision(_,_,D) :- 
	D < collisionRadius,
	setPosition(checkPt,0,-100,0), 
	!.

check_collision(X,Z,_) :- 
	getPosition(carTransform, Xcar, _, Zcar), 
	distance(Xcar,Zcar,X,Z,D1), 
	delay(50), 
	check_collision(X,Z,D1), 
	!.

%distance(X1,Z1,X2,Z2,Distance)
%
% Calculates the distance between two points in 2d plane

distance(X1,Z1,X2,Z2,D) :- 

	Xdiff is X2 - X1, 
	Zdiff is Z2 - Z1, 
	D is (sqrt((Xdiff*Xdiff)+(Zdiff*Zdiff))),
	!.



%checkpoint(id, X, Y, Z, timelimit)
%
% Database of checkpoint locations + time to reach them

checkpoint( 1, 125, 1.5,  65, 10).
checkpoint( 2, 165, 1.5, 125, 10).
checkpoint( 3,  20, 1.5,  45, 10).
checkpoint( 4,  85, 1.5, 145, 10).
checkpoint( 5,  85, 1.5,  65, 10). 
checkpoint( 6,  25, 1.5,   5, 10). 
checkpoint( 7, 125, 1.5,  25, 10). 
checkpoint( 8, 105, 1.5, 125, 20).
checkpoint( 9,   5, 1.5, 125, 20). 
checkpoint(10, 165, 1.5,  95, 20). 
checkpoint(11,  25, 1.5,  85, 20).
checkpoint(12,  85, 1.5,   5, 20).
checkpoint(13, 125, 1.5, 105, 20).
checkpoint(14,   5, 1.5,  65, 20).
checkpoint(15,  60, 1.5, 165, 30). 
checkpoint(16, 165, 1.5, 165, 30). 
checkpoint(17,  65, 1.5,  45, 30). 
checkpoint(18, 165, 1.5,  25, 30).
checkpoint(19,  45, 1.5, 125, 30). 
checkpoint(20,  85, 1.5,  85, 25). 


:-end_object checkpoint.





% Traffic Object
%
% Controls an autonomous car, travelling through the city


:-object traffic : [bcilib].


traffic(Car,position(X,Y,Z)) :-

	format('Traffic thread active [~w].~n',[Car]),
	setPosition(Car,X,Y,Z),

	CX is (X//40) + 1,
	CZ is (Z//40) + 1,

	traffic_loop(Car,CX,CZ).


%traffic_loop(ObjectID,CrossingX,CrossingZ)
%
% Main traffic loop, directing the cars from current location to destination

traffic_loop(Car,CX,CZ) :-

		random(RD1),
		random(RD2),

		CX1 is truncate(RD1*5)+1,
		CZ1 is truncate(RD2*5)+1,

		route([CX,CZ],[CX1,CZ1], Path), !,

		drive_to_destination(Path, Car), !,

		sleep(5000),

		traffic_loop(Car,CX1,CZ1).


%drive_to_destination(Route,Object)
%
% moves object to destination using a calculated route

drive_to_destination([_C1|[]],_) :- !.	% Destination reached if there is only 1 element left

drive_to_destination([C1,C2|Path2],Car) :- 

	getRotation(Car,0,1,0,CarRotation), 
	decide_action(CarRotation,C1,C2,Action),
	nonvar(Action),

	getPosition(Car,X,Y,Z),
	do_action(Car,CarRotation,position(X,Y,Z),Action),

	Path3 = [C2|Path2],
	drive_to_destination(Path3,Car).

drive_to_destination(_,_) :- format('ERROR~n'), !.


%decide_action(CarRotation,CurrentCrossing,DestinationCrossing,Action)
%
% Decides which action must be taken to reach the destination crossing

decide_action(0.0, [CX1,CZ], [CX2,CZ], go_straight) :- CX1 < CX2, !.
decide_action(1.57,[CX,CZ1], [CX,CZ2], go_straight) :- CZ1 > CZ2, !.
decide_action(3.14,[CX1,CZ], [CX2,CZ], go_straight) :- CX1 > CX2, !.
decide_action(4.71,[CX,CZ1], [CX,CZ2], go_straight) :- CZ1 < CZ2, !.

decide_action(0.0, [CX,CZ1], [CX,CZ2], turn_right) :- CZ1 < CZ2, !.
decide_action(1.57,[CX1,CZ], [CX2,CZ], turn_right) :- CX1 < CX2, !.
decide_action(3.14,[CX,CZ1], [CX,CZ2], turn_right) :- CZ1 > CZ2, !.
decide_action(4.71,[CX1,CZ], [CX2,CZ], turn_right) :- CX1 > CX2, !.

decide_action(0.0, [CX,CZ1], [CX,CZ2], turn_left) :- CZ1 > CZ2, !.
decide_action(1.57,[CX1,CZ], [CX2,CZ], turn_left) :- CX1 > CX2, !.
decide_action(3.14,[CX,CZ1], [CX,CZ2], turn_left) :- CZ1 < CZ2, !.
decide_action(4.71,[CX1,CZ], [CX2,CZ], turn_left) :- CX1 < CX2, !.

decide_action(0.0, [CX1,CZ], [CX2,CZ], turn_back) :- CX1 > CX2, !.
decide_action(1.57,[CX,CZ1], [CX,CZ2], turn_back) :- CZ1 < CZ2, !.
decide_action(3.14,[CX1,CZ], [CX2,CZ], turn_back) :- CX1 < CX2, !.
decide_action(4.71,[CX,CZ1], [CX,CZ2], turn_back) :- CZ1 > CZ2, !.

decide_action(_,_,_,no_action) :- !.


%do_action(Object,Orientation,Position,Action)
%
% Moves the object from current crossing to the next one

do_action(Car,0.0 ,position(X,Y,Z),go_straight) :- 
	X1 is X + 40, 
	move_to_position(Car,position(X,Y,Z),position(X1,Y,Z),40), 
	!.

do_action(Car,1.57,position(X,Y,Z),go_straight) :- 
	Z1 is Z - 40, 
	move_to_position(Car,position(X,Y,Z),position(X,Y,Z1),40),
	!.

do_action(Car,3.14,position(X,Y,Z),go_straight) :- 
	X1 is X - 40, 
	move_to_position(Car,position(X,Y,Z),position(X1,Y,Z),40), 
	!.

do_action(Car,4.71,position(X,Y,Z),go_straight) :- 
	Z1 is Z + 40, 
	move_to_position(Car,position(X,Y,Z),position(X,Y,Z1),40), 
	!.


do_action(Car,0.0 ,position(X,Y,Z),turn_right) :- 
	setRotation(Car,0,1,0,-0.785),
	X1 is X + 2.5, Z1 is Z + 2.5, 
	move_to_position(Car,position(X,Y,Z),position(X1,Y,Z1),5), 
	setRotation(Car,0,1,0,4.71),
	Z2 is Z1 + 32, 
	move_to_position(Car,position(X1,Y,Z1),position(X1,Y,Z2),32), !.

do_action(Car,1.57,position(X,Y,Z),turn_right) :-
	setRotation(Car,0,1,0,0.785),
	X1 is X + 2.5, Z1 is Z - 2.5, 
	move_to_position(Car,position(X,Y,Z),position(X1,Y,Z1),5),
	setRotation(Car,0,1,0,0.0),
	X2 is X1 + 32, 
	move_to_position(Car,position(X1,Y,Z1),position(X2,Y,Z1),32), !.

do_action(Car,3.14,position(X,Y,Z),turn_right) :-
	setRotation(Car,0,1,0,2.355),
	X1 is X - 2.5, Z1 is Z - 2.5, 
	move_to_position(Car,position(X,Y,Z),position(X1,Y,Z1),5),
	setRotation(Car,0,1,0,1.57),
	Z2 is Z1 - 32, 
	move_to_position(Car,position(X1,Y,Z1),position(X1,Y,Z2),32), !.

do_action(Car,4.71,position(X,Y,Z),turn_right) :-
	setRotation(Car,0,1,0,3.925),
	X1 is X - 2.5, Z1 is Z + 2.5, 
	move_to_position(Car,position(X,Y,Z),position(X1,Y,Z1),5),
	setRotation(Car,0,1,0,3.14),
	X2 is X1 - 32, 
	move_to_position(Car,position(X1,Y,Z1),position(X2,Y,Z1),32), !.


do_action(Car,0.0 ,position(X,Y,Z),turn_left) :- 
	setRotation(Car,0,1,0,0.785),
	X1 is X + 5.5, Z1 is Z - 5.5, move_to_position(Car,position(X,Y,Z),position(X1,Y,Z1),10),
	setRotation(Car,0,1,0,1.57),
	Z2 is Z1 - 32, 
	move_to_position(Car,position(X1,Y,Z1),position(X1,Y,Z2),32), !.

do_action(Car,1.57,position(X,Y,Z),turn_left) :-
	setRotation(Car,0,1,0,2.355),
	X1 is X - 5.5, Z1 is Z - 5.5, move_to_position(Car,position(X,Y,Z),position(X1,Y,Z1),10),
	setRotation(Car,0,1,0,3.14),
	X2 is X1 - 32, 
	move_to_position(Car,position(X1,Y,Z1),position(X2,Y,Z1),32), !.

do_action(Car,3.14,position(X,Y,Z),turn_left) :-
	setRotation(Car,0,1,0,3.925),
	X1 is X - 5.5, Z1 is Z + 5.5, move_to_position(Car,position(X,Y,Z),position(X1,Y,Z1),10), 
	setRotation(Car,0,1,0,4.71),
	Z2 is Z1 + 32, 
	move_to_position(Car,position(X1,Y,Z1),position(X1,Y,Z2),32), !.

do_action(Car,4.71,position(X,Y,Z),turn_left) :-
	setRotation(Car,0,1,0,-0.785),
	X1 is X + 5.5, Z1 is Z + 5.5, move_to_position(Car,position(X,Y,Z),position(X1,Y,Z1),10), 
	setRotation(Car,0,1,0,0.0),
	X2 is X1 + 32, 
	move_to_position(Car,position(X1,Y,Z1),position(X2,Y,Z1),32), !.


do_action(Car,0.0 ,position(X,Y,Z),turn_back) :- 
	setRotation(Car,0,1,0,1.57),
	Z1 is Z - 3, move_to_position(Car,position(X,Y,Z),position(X,Y,Z1),3), 
	setRotation(Car,0,1,0,3.14),
	X1 is X - 32, 
	move_to_position(Car,position(X,Y,Z1),position(X1,Y,Z1),32), !.

do_action(Car,1.57,position(X,Y,Z),turn_back) :- 
	setRotation(Car,0,1,0,3.14),
	X1 is X - 3, move_to_position(Car,position(X,Y,Z),position(X1,Y,Z),3), 
	setRotation(Car,0,1,0,4.71),
	Z1 is Z + 32, 
	move_to_position(Car,position(X1,Y,Z),position(X1,Y,Z1),32), !.

do_action(Car,3.14,position(X,Y,Z),turn_back) :- 
	setRotation(Car,0,1,0,4.71),
	Z1 is Z + 3, move_to_position(Car,position(X,Y,Z),position(X,Y,Z1),3), 
	setRotation(Car,0,1,0,0.0),
	X1 is X + 32, 
	move_to_position(Car,position(X,Y,Z1),position(X1,Y,Z1),32), !.

do_action(Car,4.71,position(X,Y,Z),turn_back) :- 
	setRotation(Car,0,1,0,0.0),
	X1 is X + 3, move_to_position(Car,position(X,Y,Z),position(X1,Y,Z),3), 
	setRotation(Car,0,1,0,1.57),
	Z1 is Z - 32, 
	move_to_position(Car,position(X1,Y,Z),position(X1,Y,Z1),32), !.


do_action(_,_,_,_) :- format('Unrecognised Action~n'), !.



%move_to_position(Object,CurrentPosition,DestinationPosition,InterpolationFactor)
%
% Interpolates an object's position between two points

move_to_position(Object,_,position(X,Y,Z),0):- 
	setPosition(Object,X,Y,Z).  

move_to_position(Object, position(X1,Y1,Z1), position(X2,Y2,Z2),C):-

	C1 is C-1,

	Xdif is X2 - X1,
	Zdif is Z2 - Z1,

	X is X1 + Xdif/C,
	Z is Z1 + Zdif/C,	 

	setPosition(Object,X,Y1,Z),
    sleep(50),

	move_to_position(Object,position(X,Y1,Z), position(X2,Y2,Z2),C1).


%route(CrossingA,CrossingB,RouteFromAtoB)
%
% Calculates route from A to B

route(A, B, Path) :- route_hlp(A, B, Path, [A]).


route_hlp(A, B, Path,_) :- 
	connected(A,B), 
	Path = [A,B].

route_hlp(A, B, Path, Between) :- 	
	connected(A,C), 
	\+ member(C, Between), 
	Between2 = [C|Between],
	route_hlp(C, B, Path2, Between2),
	Path = [A| Path2].




%connected(CrossingA,CrossingB)
%
% Two crossings are connected if there exists a road from A to B or from B to A

connected([X1,Z1],[X2,Z2]) :- road([X1,Z1],[X2,Z2]) ; road([X2,Z2],[X1,Z1]).


%road([X1,Z1],[X2,Z2]
%
% Represents connected roads

road([1,1],[2,1]).
road([1,1],[1,2]).
road([2,1],[3,1]).
road([2,1],[2,2]).
road([3,1],[4,1]).
road([3,1],[3,2]).
road([4,1],[5,1]).
road([4,1],[4,2]).
road([5,1],[5,2]).
road([1,2],[2,2]).
road([1,2],[1,3]).
road([2,2],[3,2]).
road([2,2],[2,3]).
road([3,2],[4,2]).
road([3,2],[3,3]).
road([4,2],[4,3]).
road([5,2],[5,3]).
road([1,3],[2,3]).
road([1,3],[1,4]).
road([2,3],[3,3]).
road([2,3],[2,4]).
road([3,3],[4,3]).
road([3,3],[3,4]).
road([4,3],[4,4]).
road([5,3],[5,4]).
road([1,4],[1,5]).
road([2,4],[3,4]).
road([3,4],[4,4]).
road([3,4],[3,5]).
road([4,4],[5,4]).
road([4,4],[4,5]).
road([5,4],[5,5]).
road([1,5],[2,5]).
road([2,5],[3,5]).
road([3,5],[4,5]).
road([4,5],[5,5]).

:-end_object traffic.





