/* LoveMice (Mice in Love) 
   by Guido Wegener of CLUSTER
   This program is freeware, please read LoveMice.doc for copy-conditions.
*/  
#include "math.h"
#include "libraries/dosextens.h"
#include "functions.h"
#include "exec/types.h"
#include "intuition/intuition.h"
#include "graphics/rastport.h"
#include "graphics/gfxbase.h"

#define PI 3.14159
#define XADD 100  /* Some constants for transforming */
#define YADD 100  /* float coordinates (-100 -» 100) */
#define XF 3      /* into normal coordinates         */
#define YF 2
#define ANZ 15    /* max number of mice */
float q[ANZ][2],p[ANZ][2]; /* positions of mice (actual and last) */
int n[ANZ];     /* start positions on circle */
int farbs[ANZ]; /* color registers for each mouse */
float teil;     /* part of distance walked in one step */
 
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase; 
struct Screen *MyScreen;
struct DOSBase *DOSBase;

struct FileHandle *fh;  

struct NewScreen MyNewScreen={0,0,640,500,4,
                              15,14,
                              HIRES|LACE,
                              CUSTOMSCREEN,
                              NULL,
                              (UBYTE *)"Mice in Love by Guido Wegener of CLUSTER",
                              NULL,NULL};
long int col[]={ 0,0,0,     /* color definitions */
             15,15,15,
             15,0,0,
             0,15,0,
             0,0,15,
             15,0,15,
             15,15,0,
             0,15,15,
             
             4,0,15,
             8,4,15,
             12,8,15,
             6,15,15,
             15,6,15,
             10,8,11,
             8,8,12,
             15,15,15
 };
struct RastPort *rp;
int anz; /* real number of mice */
struct Window *MyWindow;
#define FILEN 38 /* display position of filename */
#define FILEL 30 /* length of filename */
struct NewWindow win=
 {
  0,10,640,480,
  15,13,
  CLOSEWINDOW,
  WINDOWCLOSE | SMART_REFRESH | BACKDROP | BORDERLESS | ACTIVATE,
  NULL,
  NULL,
  (UBYTE *)"<=- klick here to exit   PATTERNNAME:                               ",
  NULL,
  NULL,
  50,50,-1,-1,
  CUSTOMSCREEN
 };

info() /* is displayed when called without arguments */
 {
  puts("Mice in Love by Guido Wegener of CLUSTER");
  puts("finished on 1.Feb.1990");
  puts("You should have called this programm with an argument !");
  puts("Example : lovemice mice/fighter");
  puts("            (show pattern generated by the file fighter)");
  puts("You really should read LoveMice.Doc !!!");
 }
 
main(argc,argv)
int argc;
char *argv[];
 {
  long int i,t;
  void *mess;   /* message port */
  int closed=0; /* close gadget hit ? */
  
  if(argc!=2) /* arguments */
   {
    info();
    exit(0);
   }
   
  /* open, check and exit (in a stupid way, but first version only 
     opened three things, but as time goes by ... */
  IntuitionBase=(struct IntuitionBase *) OpenLibrary("intuition.library",33L);
  if(!IntuitionBase) {puts("Can't open Intuition.library !");exit(20);}

  GfxBase=(struct GfxBase *) OpenLibrary("graphics.library",33L);
  if(!IntuitionBase) {puts("Can't open Graphics.library !");CloseLibrary(IntuitionBase);exit(20);}
	
  DOSBase=(struct DOSBase *)OpenLibrary("dos.library",33L);
  if(!DOSBase){puts("Can't open Dos.library !");CloseLibrary(GfxBase);CloseLibrary(IntuitionBase);exit(20);}

  MyScreen=OpenScreen(&MyNewScreen);
  if(!MyScreen){puts("Can't open screen !");CloseLibrary(DOSBase);CloseLibrary(GfxBase);CloseLibrary(IntuitionBase);exit(20);}

  win.Screen=MyScreen;  /* link to screen */
  for(i=0;i<FILEL;i++)win.Title[i+FILEN]=argv[1][i]; /* copy filename to title */
  MyWindow=(struct Window *)OpenWindow(&win);
  if(!MyWindow){puts("Can't open Window !");CloseScreen(MyScreen);CloseLibrary(DOSBase);CloseLibrary(GfxBase);CloseLibrary(IntuitionBase);exit(20);}
  
  rp=(MyWindow->RPort);
  init(argv[1]);    /* get and set all parameters set in the pattern file */
  for(i=0;i<16;i++) /* use colors */
   {  
    SetRGB4(&(MyScreen->ViewPort),i,col[i*3],col[i*3+1],col[i*3+2]);
   }

  starts(); /* compute real start positions and colors */   
  while(!closed)
   {
    mess=GetMsg(MyWindow->UserPort);
    if(mess)
     {
      closed=1;
      ReplyMsg(mess);
     } 
    views();  /* draw lines */
    move();   /* move mice  */
   }
   
  /* close all */
  CloseWindow(MyWindow);
  CloseScreen(MyScreen);  	
	
  CloseLibrary(DOSBase);
  CloseLibrary(GfxBase);
	CloseLibrary(IntuitionBase);
 }

init(filen)
char *filen;
 {
  int j,i,x,t;
  
  fh=Open(filen,MODE_OLDFILE);
  if(fh==0)  /* trouble ?  let's go ! */
   {
    CloseWindow(MyWindow);
    CloseScreen(MyScreen);
    CloseLibrary(DOSBase);
    CloseLibrary(GfxBase);
    CloseLibrary(IntuitionBase);
    puts("Can't find pattern data-file !");
    exit(20);
   }
  teil=1/(float)readnum(); /* get'n'compute part of distance */
  anz=readnum();  /* nmumber of mice */
  for(i=0;i<anz;i++)       /* get start positions */
    n[i]=readnum();
  for(i=3;i<(anz+1)*3;i++) /* ... and colors */
   {
    col[i]=readnum();  
   }
  Close(fh);
 }
  
readnum()  /* get next number */
 {
  int i=0;
  char buff[80];
  
  do       /* don't use anything but numbers */
   {
    Read(fh,&buff[0],1L);
    i++;
   }
  while((buff[0]<'0' || buff[0]>'9') && i<80);  
  i=1;
  do       /* read numbers */
   {
    Read(fh,&buff[i],1L);
    i++;
   }
  while(i<80 && buff[i-1]>='0' && buff[i-1]<='9');  
  return atoi(buff);
 }

starts()
 {
  int i;
  
  for(i=0;i<anz;i++)
   {
    p[i][0]=sin(n[i]*2*PI/anz+PI/anz)*100;  /* <---  that was one          */
    p[i][1]=-cos(n[i]*2*PI/anz+PI/anz)*100; /*   |   of the BIG problems   */
    farbs[i]=n[i]+1;                        /* <-/   (= 1.5 days trying    */
   }
 }
  
views()
 {
  int mouse;
  
  for(mouse=0;mouse<anz;mouse++)
   {                                     /*        |    */
    SetAPen(rp,(long int)farbs[mouse]);  /* this ( V ) is not the best way of doing it, but as time goes by and proggies grow ...*/
    Move(rp,(long int)(10+(p[mouse][0]+XADD)*XF),(long int)(50+(p[mouse][1]+YADD)*YF));
    Draw(rp,(long int)(10+(p[(mouse+1)%anz][0]+XADD)*XF),(long int)(50+(p[(mouse+1)%anz][1]+YADD)*YF));
   }
 }
 
move()
 {
  int m,mg;
  
  for(m=0;m<anz;m++)   /* compute next positions */
   {
    mg=(m+1)%anz;
    q[m][0]=p[m][0]+teil*(p[mg][0]-p[m][0]);
    q[m][1]=p[m][1]+teil*(p[mg][1]-p[m][1]);
   }
  for(m=0;m<anz;m++)   /* use the new positions */
   {
    p[m][0]=q[m][0];
    p[m][1]=q[m][1];
   }
 }

