/*
 *  Copyright (c) 1995 Andreas Schmitz
 *  All rights reserved.
 *
 *  This is a blanker-module for Garshne-Blanker 3.6
 */

#include <exec/memory.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <float.h>
#include <stdlib.h>

#include "/includes.h"

#define MASS   0
#define MUSER  2
#define LENGTH 4
#define LUSER  6
#define COLMODE   8
#define SCRMODE 10

Triplet *ColorTable = 0L;

#include "Pendulum_rev.h"
STATIC const UBYTE VersTag[] = VERSTAG;

VOID Defaults( PrefObject *Prefs )
{
	Prefs[MASS].po_Level = 50;
   Prefs[MUSER].po_Active = 1;
	Prefs[LENGTH].po_Level = 50;
   Prefs[LUSER].po_Active = 1;
   Prefs[COLMODE].po_Active = 0;
	Prefs[SCRMODE].po_Depth = 4;
}


LONG Pendel( struct Screen *Scr, SHORT Wid, SHORT Hei, PrefObject *Prefs)
{
	struct RastPort *RP = &( Scr->RastPort );

   int   x1,y1,x2,y2,midx,midy,
         colmodus,totlong,colors;

   int zeit,count=0;

   double phi1,omega1,beschl1,
          phi2,omega2,beschl2,
          dphi,sindp,cosdp,det,Bee,iXs,Yps,
          dt,Energie,
          m2,l1,l2,
          gxl1,l1xl1,l1xl2,m2xl2,m2xgxl2,m2xl1xl2,m2xl2xl2,
          faktor,g=9.81;

   srand((unsigned)clock());

   colmodus=Prefs[COLMODE].po_Active;

   midx=Wid/2;
   midy=Hei/2;
   totlong=midy-2;
   if (midx<midy) totlong=midx-2;

   if (Prefs[MUSER].po_Active==0) {
      m2=0.01+rand()*0.98/RAND_MAX;
   }
   else {
      m2=1.0-0.01*Prefs[MASS].po_Level;
   }
   if (Prefs[LUSER].po_Active==0) {
      l1=0.01+rand()*0.98/RAND_MAX;
   }
   else {
   	l1=0.01*Prefs[LENGTH].po_Level;
   }
   l2=1.0-l1;
   gxl1=g*l1;
   l1xl1=l1*l1;
   l1xl2=l1-l1xl1;
   m2xl2=m2*l2;
   m2xgxl2=m2xl2*g;
   m2xl1xl2=m2*l1xl2;
   m2xl2xl2=m2xl2*l2;

   dt=0.001;
   if (colmodus==0) dt=0.01;

   phi1=rand()*M_PI/RAND_MAX;
   omega1=3.0-rand()*6.0/RAND_MAX;
   phi2=rand()*M_PI/RAND_MAX;
   omega2=3.0-rand()*6.0/RAND_MAX;

   Energie=0.5*(l1xl1*omega1*omega1+m2xl2xl2*omega2*omega2)+m2xl1xl2*omega1*omega2*cos(phi1-phi2)-gxl1*cos(phi1)-m2xgxl2*cos(phi2);
	
	SetRast( RP, 0 );
	ScreenToFront( Scr );
	
   colors = (1L << RP->BitMap->Depth)-1;

   zeit=clock();         

	while (1) {

      x1=midx+totlong*(l1*sin(phi1));
      y1=midy+totlong*(l1*cos(phi1));
      x2=midx+totlong*(l1*sin(phi1)+l2*sin(phi2));
      y2=midy+totlong*(l1*cos(phi1)+l2*cos(phi2));

      Move(RP,midx,midy);
      if (colmodus==2) {
         SetAPen(RP,1+count%colors);
         Draw(RP,x1,y1);
         SetAPen(RP,1+(colors/2+count%colors)%colors);
      }
      else {
         SetAPen(RP,1);
         Draw(RP,x1,y1);
         SetAPen(RP,2);
      }
      Draw(RP,x2,y2);

      dphi=phi1-phi2;
      sindp=sin(dphi);
      cosdp=cos(dphi);
      det=m2*cosdp*cosdp-1.0;
      Bee=cosdp/(l1xl2*det);
      iXs=-gxl1*sin(phi1)-m2xl1xl2*omega2*omega2*sindp;
      Yps=-m2xgxl2*sin(phi2)+m2xl1xl2*omega1*omega1*sindp;

      beschl1=Bee*Yps-iXs/(l1xl1*det);
      beschl2=Bee*iXs-Yps/(m2xl2xl2*det);
      omega1=omega1+beschl1*dt;
      omega2=omega2+beschl2*dt;
      phi1=phi1+omega1*dt;
      phi2=phi2+omega2*dt;

      if (fabs(phi1)>1000000.0) phi1=0.0;
      if (fabs(phi2)>1000000.0) phi2=0.0;

      /*
      Energie-Korrektur
      */
      faktor=sqrt((Energie+gxl1*cos(phi1)+m2xgxl2*cos(phi2))/(0.5*(l1xl1*omega1*omega1+m2xl2xl2*omega2*omega2)+m2xl1xl2*omega1*omega2*cos(phi1-phi2)));
      omega1=omega1*faktor;
      omega2=omega2*faktor;

      count++;
   	if (count%20==0) {
         if (ContinueBlanking()!=OK) return(UNBLANK);
   		ScreenToFront( Scr );
         if (colmodus!=0) {
            if (clock()>zeit+120*CLK_TCK) return(OK);
         }
	   }
	
      if (colmodus==0) {
         Move(RP,midx,midy);
         SetAPen(RP,0);
         WaitTOF();
         Draw(RP,x1,y1);
         Draw(RP,x2,y2);
      }
	}

	return 0;
}

LONG Blank( PrefObject *Prefs )
{
	struct Screen *Scr;
	struct Window *Wnd;
	LONG RetVal;
   char depth;
	
   depth=2;
   if (Prefs[COLMODE].po_Active == 2) {
      depth=Prefs[SCRMODE].po_Depth;
      if (depth==1) depth=2;
   }

	if( Scr = OpenScreenTags( NULL, SA_Depth, depth,
							 SA_Quiet, TRUE, SA_DisplayID, Prefs[SCRMODE].po_ModeID,
							 SA_Behind, TRUE, SA_Overscan, OSCAN_STANDARD,
							 TAG_DONE ))
	{
		SetRGB4(&( Scr->ViewPort ), 0, 0, 0, 0 );
		ColorTable = RainbowPalette( Scr, 0L, 1L, 0L );
      if (Prefs[COLMODE].po_Active != 2) {
   		SetRGB4(&( Scr->ViewPort ), 1, 15, 15, 15 );
	   	SetRGB4(&( Scr->ViewPort ), 2, 15, 0, 0 );
      }
		Wnd = BlankMousePointer( Scr );
		
		do
			RetVal = Pendel( Scr, Scr->Width, Scr->Height, Prefs);
		while( RetVal == OK );
		
		UnblankMousePointer( Wnd );
		RainbowPalette( 0L, ColorTable, 1L, 0L );
		CloseScreen( Scr );
	}
	else
		RetVal = FAILED;
	
	return RetVal;
}
