/* predict. 
Prediction for Roller Coaster Problems
Alan Bundy 7.4.81 */


/*MOTION ON A PATH*/
/*----------------*/

/*MOTION CHECK*/
motion(Part,Path,Start,Side,Per) :-
  inplace(Part,Path,Start,Side,Begin),
  cue(timesys(Per,Begin,End)),
  trace('Checking motion of %t\n\t\t on %t\n\t\t from %t\n\t\t on %t\n\t\t during %t\n',
           [Part,Path,Start,Side,Per],4),
  motion1(Part,Path,Start,Side,Per),
  cue(motion(Part,Path,Start,Side,Per)).


/*GENERAL MOTION ON PATH*/   /*LETS THROUGH TOO MANY POSIBILITIES*/
motion1(Part,Path,Start,Side,Per) :-
  simple_curve(Path), !,
  ncc initial(Per,Begin),
  getstarted(Part,Path,Start,Side,Begin),
  nostopping(Part,Path,Start,Side,Per),
  notakeoff(Part,Path,Start,Side,Per),
  nofalloff(Part,Path,Start,Side,Per).


/*BREAK INTO SUBPATHS*/
motion1(Part,Path,Start,Side,Per) :- !,
  arrangepath(Path,Start,Npathlist),
  makeperiods(Npathlist,Per,Perlist),
  multimotion(Part,Npathlist,Start,Side,Perlist).

/* Path is a simple curve */
simple_curve(Path) :-
	dc concavity(Path,_),
	dc slope(Path,_), !.

/* Put partition of path in order */
arrangepath(Path,Start,Npathlist) :-
  dc partition(Path,Pathlist),
  dc end(Path,Start,End),
  condrev(End,Pathlist,Npathlist).

/* make a new subperiod for each subpath */
makeperiods(Npathlist,Per,Perlist) :-
  maplist(makeone,Npathlist,Perlist),
  dbentry(partition(Per,Perlist)),
  trace('Divide %t into : %l',[Per,Perlist],2).

/*DEAL WITH EACH SUBPATH*/
multimotion(Part,[],Start,Side,[]).

multimotion(Part,[Path|Pathl],Start,Side,[Per|Perl]) :-
  pc motion(Part,Path,Start,Side,Per),
  farend(Path,Start,Finish),
  multimotion(Part,Pathl,Finish,Side,Perl).

/*MAKE ONE PERIOD */
makeone(Path,Per) :- ccreate(period,Per).

/* Gets started on motion */
/*------------------------*/

/* Stationary at start */
getstarted(Part,Path,Start,Side,Begin) :-
  ncc vel(Part,zero,Dir,Begin), !,
  ( horizontal(Path,Start) ->
  dc nudge(Part,Begin) ; top(Path,Start) ).

/*HEADED IN RIGHT DIRECTION*/
getstarted(Part,Path,Start,Side,Begin) :- !,
  along(Path,Start,Start,Dir),
  cc vel(Part,V,Dir,Begin),
  condition(positive(V)).


/* Particle does not run out of steam */
/*-----------------------------------*/

/*DOWNHILL OR HORIZONTAL RUN*/
nostopping(Part,Path,Start,Side,Per) :-
  dc end(Path,Start,End), opposite(End,Oend),
  dc slope(Path,Hend), diff(Oend,Hend), !.

/*MAKES IT TO THE TOP*/
nostopping(Part,Path,Start,Side,Per) :- !,
 ncc farend(Path,Start,Finish),
 along(Path,Start,Finish,Dir),
 cc finvel(Part,V,Dir,Per),
 condition(real(V)).

/* Particle does not take off */
/*-----------------------*/

/* Particle is threaded on */
notakeoff(Part,Path,Start,threaded,Per) :- !.

/*BELOW PATH*/
notakeoff(Part,Path,Start,Side,Per) :-
  below(Path,Start,Side), !.

/*SLOPE DOES NOT DROP AWAY*/
notakeoff(Part,Path,Start,Side,Per) :-
  dc concavity(Path,Conc), diff(Conc,right), !.

/*INSUFFICIENT VEL TO TAKE OFF*/
notakeoff(Part,Path,Start,Side,Per) :-
  dc concavity(Path,right), !,
  cc typical_point(Path,TypPt),
  towards(Path,Part,Start,Side,TypPt,Per,Dir),
  cc reaction(Path,Part,N,Dir,Per),
  condition(non_neg(N)).


/* Particle does not fall off */
/*----------------------------*/

/* It is threaded on */
nofalloff(Part,Path,Start,threaded,Per) :- !.

/*SUPPORTED*/
nofalloff(Part,Path,Start,Side,Per) :-
  above(Path,Start,Side), !.

/*VERTICAL FALL*/
nofalloff(Part,Path,Start,Side,Per) :-
  ncc end(Path,Start,Par),
  dc slope(Path,Par),
  dc concavity(Path,stline),
  ncc incline(Path,270,Start), !.

/*STICKS ON*/
nofalloff(Part,Path,Start,Side,Per) :-
  dc concavity(Path,right), !,
  cc normal(Path,Dir1),
  cc typical_point(Path,TypPt),
  along(Path,Start,TypPt,Dir2),
  cc vel(Part,V,Dir2,Per),
  cc radius(Path,R),
  condition((V^2)*sin(Dir1)>=R*g).

/*FREEFALL*/		%Put in failure cases on other conditions?
nofalloff(Part,Path,Start,Side,Per) :-
  dc concavity(Path,Conc), diff(Conc,right),
  trace('%t falls off %t during %t\n',[Part,Path,Per],1),
  assert(falls_off(Part,Path,Start,Side,Per)),
  !, fail.

/*PARTICLE IS IN PLACE AT START OF PATH*/
inplace(Part,Path1,Finish,Side,End) :-
  dc cued(motion(Part,Path2,Start,Side,Per)),
  farend(Path2,Start,Finish),
  ncc final(Per,End), !.

inplace(Part,Path,Start,Side2,Time) :-	% Side2 is looking from Start
  ncc at(Part,Start,Time), !,
  dc side(Part,Start,Side1,Time),	% Side1 is looking from left end
  dc end(Path,Start,End),
  condval(End,Side1,Side2).



/*YOU GET TO YOUR DESTINATION BY TRAVELING THERE*/
at(Part,Place2,Mom2) :-
  farend(Path,Place2,Place1),
  inplace(Part,Path,Place1,Side,Mom1),
  cue(timesys(Per,Mom1,Mom2)), !,		% duplication
  pc motion(Part,Path,Place1,Side,Per).


