/*
   shotSTAR v2.0 for AmigaDOS, by Aaron Holmes.
   This program is available in three forms for three operating systems;
   Macintosh, MS-DOS, and, with this latest release: AmigaDOS. This simple
   demo uses the trigonometric ratios sine and cosine to create dazzling
   string-art-like images. No two are exactly alike! (FPU RECOMMENDED!)
*/

#include <intuition/intuition.h>
#include <math.h>

#define _X 320
#define _Y 200
#define MaxR _X
#define MaxT 6.283185307   /* slightly exaggerated */
#define MaxI 32768

void SetUP(void);
void TakeDOWN(void);

struct TextAttr TopazFont = { "topaz.font", 8, FS_NORMAL, FPB_ROMFONT };

/* in COLOR!!! */
UWORD OurPalette[4] = { 0x0000, 0x000F, 0x0F00, 0x0000 };

UWORD chip BlankPointer[] =
{
   0x0000, 0x0000,   /* no screen burn-in */
   0x0000, 0x0000,
   0x0000, 0x0000
};

struct NewScreen OSDef =
{
   0, 0, 640, 400, 2,   /* left top wide high deep */
   0, 0,                /* detail 'n' block pens */
   HIRES | LACE,        /* flags (res junk) */
   CUSTOMSCREEN | SCREENBEHIND | SCREENQUIET,   /* type */
   &TopazFont,          /* font (let's be creative) */
   "shotSTAR v2.0",     /* title... ok, so it's invisible */
   NULL,                /* gadgets */
   NULL                 /* custom bitmap */
};

struct NewWindow OWDef =
{
   0, 0, 640, 400,   /* left top wide high */
   0, 0,             /* detail 'n' block pens */
   MOUSEBUTTONS,     /* IDCMP flags */
   SMART_REFRESH | GIMMEZEROZERO | BORDERLESS |
   RMBTRAP | ACTIVATE,   /* misc. flags */
   NULL,             /* gadgets */
   NULL,             /* checkmark */
   NULL,             /* title */
   NULL,             /* screen */
   NULL,             /* superbitmap */
   0, 0, 0, 0,       /* no resizing this bugger */
   CUSTOMSCREEN      /* on a what? */
};

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Screen *OurScreen;
struct Window *OurWindow;

/******************** the MAIN function ********************/

main()
{
   struct IntuiMessage *OurMessage;
   struct RastPort *RP;
   
   double Theta, Rad2Add;
   
   int i, x[320], y[320], r;
   
   unsigned t;
   
   SetUP();   /* get all SetUP */
   
   RP = OurWindow->RPort;   /* save ourselves some time */
   SetDrMd(RP, JAM1);       /* make sure we're in the right mode */
   
   time(&t);
   srand(t);   /* not THAT pseudo */
     
   FOREVER
   {
      Rad2Add = rand();   /* draw a random number */
      if(!Rad2Add == 0)
         Rad2Add = Rad2Add * MaxT / MaxI;   /* limit it to 6.28 */
      
      Theta = 0;   /* set these to starting values */
      r = 0;
      
      SetAPen(RP, 2);   /* select RED from our palette */
      
      do
      {
         if(OurMessage = (struct IntuiMessage *)
         GetMsg(OurWindow->UserPort))   /* got a message? */
         {
            ReplyMsg(OurMessage);
            TakeDOWN();   /* time to quit */
         }
         
         x[r] = _X + r * cos(Theta);   /* our next move */
         y[r] = _Y + r * sin(Theta);
         
         Theta += Rad2Add;                  /* offset Theta */
         if(Theta >= MaxT) Theta -= MaxT;   /* back 360 */
         
         Move(RP, r * 2, 0);   /* start thermometer line */
         Draw(RP, r * 2, 5);   /* finish it */
         
         r++;   /* expand */
      }
      while(r <= MaxR);
      
      SetRast(RP, 0);              /* clear the screen */
      SetAPen(RP, 1);              /* select BLUE */
      Move(RP, _X, _Y);            /* move to the center */
      for(i = 1; i <= MaxR; i++)   /* loop 320 times */
      {
         Draw(RP, x[i], y[i]);   /* draw all the lines */
      }
   }
}

/******************** the SetUP function ********************/

void SetUP()
{
   /* try opening the libraries and our screen */ 
   IntuitionBase = (struct IntuitionBase *)
   OpenLibrary("intuition.library", 0);
   GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0);
   OurScreen = (struct Screen *)OpenScreen(&OSDef);
   /* I hope it worked */
   if((!IntuitionBase) || (!GfxBase) || (!OurScreen)) TakeDOWN();
   
   OWDef.Screen = OurScreen;   /* the window is ours */
   
   /* and now, our window */
   OurWindow = (struct Window *)OpenWindow(&OWDef);
   /* I hope it worked */
   if(!OurWindow) TakeDOWN();
   
   LoadRGB4(&OurScreen->ViewPort, OurPalette, 4);      /* set palette */
   SetPointer(OurWindow, &BlankPointer, 1, 1, 0, 0);   /* no arrow */
   ScreenToFront(OurScreen);                           /* we're here */
}

/******************** the TakeDOWN function ********************/

void TakeDOWN()
{
   if(OurWindow) CloseWindow(OurWindow);   /* close what we opened */
   if(OurScreen) CloseScreen(OurScreen);
   if(GfxBase) CloseLibrary(GfxBase);
   if(IntuitionBase) CloseLibrary(IntuitionBase);
   
   /* we're outta here... adios AMIGA */
   exit(TRUE);
}
