	/********************************************************
	*							*
	*			Bounce 				*
	*			======				*
	*							*
	* Authors: Steve Hansel and Tom Hansel			*
	*							*
	* This program creates little dots that bounce around	*
	* and multiply.  These dots (balls) react to collisions *
	* in the following manner:				*
	*							*
	* 1) If a ball hits a wall of color 2, it bounces off 	*
	*    in an elastic collision.				*
	*							*
	* 2) If a ball hits a wall of color 1 or another ball	*
	*    it bounces off with a random speed and direction.	*
	*							*
	* 3) If a ball hits a red pixel, it divides.		*
	*							*
	* This program will run until someone hits the close	*
	* gadget.						*
	*							*
	********************************************************/

#include "exec/types.h"
#include "exec/tasks.h"
#include "exec/libraries.h"
#include "exec/devices.h"
#include "devices/keymap.h"
#include "graphics/copper.h"
#include "graphics/display.h"
#include "graphics/gfxbase.h"
#include "graphics/text.h"
#include "graphics/view.h"
#include "graphics/gels.h"
#include "graphics/regions.h"
#include "hardware/blit.h"
#include "intuition/intuition.h"
#include "intuition/intuitionbase.h"

struct Ball
{  short x,y,vx,vy;
   struct Ball *next;
};

struct GfxBase *GfxBase;   /* Export library base pointers */
struct IntuitionBase *IntuitionBase;
struct IntuiMessage *message;
struct Screen *screen;

struct Window *window;
struct RastPort *rport;

struct NewWindow nwindow =
{  0,10,639,175,
   1,2,CLOSEWINDOW, SMART_REFRESH | WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE,
   NULL,NULL,(char *)"Bounce By SJH & TJH",
   NULL,NULL,
   20,20,650,100,WBENCHSCREEN
};

struct Ball firstball = {120,120,2,3,NULL},*curball,*tempball;

main ()
{
short x,y;
char flag = TRUE;
short random ();

   if ((IntuitionBase = (struct  IntuitionBase *)OpenLibrary("intuition.library",0))==0)
   {  printf("Problems opening intuition\n");
      exit ();
   }

   if ((GfxBase = (struct  GfxBase *) OpenLibrary("graphics.library",0))==0)
   {  printf ("Problems opening graphics library\n");
      CloseLibrary (IntuitionBase);
      exit ();
   }

   window = (struct Window *)OpenWindow(&nwindow);
   if (window == 0)
   {  printf ("Window Failed\n");
      CloseScreen (screen);
      CloseLibrary (GfxBase);
      CloseLibrary (IntuitionBase);
      exit ();
   };

   rport = window -> RPort;

   SetAPen (rport,3L);
   Move (rport,320L,75L);
   Draw (rport,320L,115L);


   SetAPen (rport,2L);
   Move (rport,60L,160L);
   Draw (rport,60L,30L);
   Draw (rport,350L,30L);

   for (x=80;x<300;x+=10)
   { Move (rport,(long)x,150L);
     Draw (rport,(long)x,120L);
   }

   SetAPen (rport,1L);
   for (x=400;x<500;x+=5)
      for (y=40;y<100;y+=7)
         WritePixel (rport,(long)x,(long)y);

   Move (rport,40L,170L);
   Draw (rport,250L,170L);

   while (flag)
   {  curball = &firstball;
      while (curball != NULL)
      {  SetAPen (rport,0L);
         WritePixel (rport,(long)(curball -> x >> 2), (long)(curball -> y >> 2));

         x = curball -> x + curball -> vx;
         y = curball -> y + curball -> vy;

         switch (ReadPixel (rport,(long)(x >> 2), (long)(y >> 2)))
         {  case 3:
            NewBall (curball);
            break;

            case 1:
            do
            {  curball -> vx = random () - 4;
               curball -> vy = random () - 4;
            }
            while (!(curball -> vx && curball -> vy));
            break;
         }
         if (ReadPixel (rport,(long)(x >> 2),(long)(curball -> y >> 2)))
         {  curball -> vx = - curball -> vx;
            x = curball -> x;
         }

         if (ReadPixel (rport,(long)(curball -> x >> 2),(long)(y >> 2)))
         {  curball -> vy = - curball -> vy;
            y = curball -> y;
         }

         if (ReadPixel (rport,(long)(x >> 2),(long)(y >> 2)))
         {  curball -> vy = - curball -> vy;
            curball -> vx = - curball -> vx;
            x = curball -> x;
            y = curball -> y;
         }

         SetAPen (rport,1L);
         WritePixel (rport,(long)(x >> 2),(long)(y >> 2));

         curball -> x = x;
         curball -> y = y;
         curball = curball -> next;
      }

      if (message = (struct IntuiMessage *) GetMsg (window -> UserPort))
      {  flag = (message -> Class != CLOSEWINDOW);
         ReplyMsg (message);
      }
   }

   curball = firstball.next;
   while (curball != NULL)
   {  tempball = curball -> next;
      FreeMem (curball,(long)sizeof (struct Ball));
      curball = tempball;
   }

   CloseWindow (window);
   CloseLibrary (GfxBase);
   CloseLibrary (IntuitionBase);
}

NewBall (splitball)

struct Ball *splitball;
{
struct Ball *newball;
short i,j,random();
static short count = 1;

   if (newball = (struct Ball *) AllocMem ((long)sizeof (struct Ball),0L))
   {  newball -> next = firstball.next;
      firstball.next = newball;

      i = -2; j = -2;

      while (ReadPixel (rport,(long)(i + (splitball -> x >> 2)),
         (long)(j + (splitball -> y >> 2))))
      {  ++i;
         if (i > 1)
         {  i = -2;
            ++j;
         }
      }
      newball -> x = i * 4 + splitball -> x;
      newball -> y = j * 4 + splitball -> y;

      do
      {  newball -> vx = random () - 4;
         newball -> vy = random () - 4;
      }
      while (!(newball -> vx && newball -> vy));
   }
}

short random ()
{
   static short number = 143;
   number =   (((number & 1) ^ (number >> 1 & 1)) ^ ((number >> 3 & 1) ^ (number >> 12 & 1))) << 14 | (number >> 1);
   return (short) (number & 7);
}




