/* Eaters by Guido Wegener of CLUSTER */
#include "math.h"
#include "exec/types.h"
#include "functions.h"
#include "intuition/intuition.h"
#include "graphics/gfxbase.h"
#include "graphics/gfx.h"
#include "stdio.h"
#include "exec/memory.h"
#define ABS(a) ((a<0) ? -a : a)  /* Usefull function, but it didn't work always */
#define LI (long int)   /* The average guru is caused by short variables
                           passed to system functions. */
#define MAXANZ 500

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Screen wbs;    /* workbenchscreen */
struct ViewPort *vpo; /* wbs' ViewPort  */
struct RastPort *rpo; /* and RastPort   */
struct Window *MyWindow=NULL;
struct NewWindow MyNewWindow=
 {
  0,0,
  391,10,
  -1,-1,
  CLOSEWINDOW,
  NOCAREREFRESH+SMART_REFRESH+WINDOWDEPTH+WINDOWCLOSE+WINDOWDRAG,
  NULL,NULL,
  (UBYTE *)"Eaters by G.Wegener of CLUSTER",
  NULL,NULL,
  391,10,
  391,10,
  WBENCHSCREEN
 };
BOOL closed=FALSE;
int x[MAXANZ],y[MAXANZ],u[MAXANZ];  /* Positions of Eaters; what is beneath them */
int w,h;    /* wbs width, height */
int dcoords[8][2]=  /* double list of where to look for white dots */
 {                  /* as pairs of delta-x,y */
  1,0,
  -1,0,
  0,1,
  0,-1,
  1,0,   /* Once again the same list, this copy is needed to get */
  -1,0,  /* a bit random later */
  0,1,
  0,-1
 };
int anz=35;   /* number of eaters */
     
main(argc,argv)
int argc;
char *argv[];
 {
  struct IntuiMessage *message;
  int i; 

  if(argc!=2) info();
  else anz=atoi(argv[1]);
  if(anz<1 || anz>500) anz=35;
  openit();  /* some start values and opens */

  while(!closed) /* while not closed ... */
   {
    message=(struct IntuiMessage *)GetMsg(MyWindow->UserPort);
    if(message) /* if there was a message */
     {
      switch(message->Class)
       {
        case CLOSEWINDOW:closed=TRUE;break;
        default : puts("Unknown message class !"); /* You should never see this */
       }
      ReplyMsg((struct Message *)message);
     }
    for(i=0;i<anz;i++) moveme(i);  /* move the Eaters */
   }
  go(NULL); /* very clean exit (Who needs the 23KB that get lost each call ?) */
 }

info()
 {
  puts("Eaters V1.0 by Guido Wegener of CLUSTER 21.5.1990");
  puts("Usage : run eaters <n>      where <n> is the number of eaters");
  puts(" n must be smaller than 500, but you won't like it anyway");
 }

moveme(n)
int n;
 {
  int i;
  int nx,ny; /* new position of Eater */
  int fc;

  fc=RangeRand(4L);    /* starting point in delta-list */
  if(u[n]==1) u[n]=2;  /* turn white into black */
  if(u[n]==3) u[n]=0;  /*  and orange into blue */
  SetAPen(rpo,LI(u[n]));             /* kill the */
  WritePixel(rpo,LI(x[n]),LI(y[n]));        /* image of the Eater */
  nx=x[n];ny=y[n];  /* set default : no move */
  for(i=0;i<4;i++)  /* search for WHITE */
   {
    nx=x[n]+dcoords[fc+i][0];
    if(nx<0 || nx>=w) continue; /* bound-checking */
    ny=y[n]+dcoords[fc+i][1];
    if(ny<0 || ny>=h) continue;
    if(ReadPixel(rpo,LI(nx),LI(ny))==1) break; /* look at neighbour */
   }
  if(nx==x[n] && ny==y[n]) /* if no WHITE is found ... */
   {
    x[n]+=1-RangeRand(3L); /* ... move randomly */
    y[n]+=1-RangeRand(3L);
   }
  else    /* else go to WHITE */
   {
    x[n]=nx;
    y[n]=ny;
   }
  if(x[n]>=w) x[n]=w-1; /* check if Eater is leaving the screen */
  if(x[n]<0) x[n]=0;
  if(y[n]>=h) y[n]=h-1;
  if(y[n]<0) y[n]=0;
  u[n]=ReadPixel(rpo,LI(x[n]),LI(y[n])); /* what color has the new dot ? */
  SetAPen(rpo,3L);
  WritePixel(rpo,LI(x[n]),LI(y[n]));  /* draw eater */
 }

openit()
 {
  BOOL succ;
  int i;
  
  IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0L);
  if(!IntuitionBase) go("Can't open Intuition !");
  GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0L);
  if(!GfxBase) go("Can't open Graphics !");

  MyWindow=OpenWindow(&MyNewWindow);
  succ=GetScreenData((CPTR)&wbs,(long int)sizeof(struct Screen),WBENCHSCREEN,NULL);  
  if(!succ) go("Can't find WBENCHSCREEN !"); /* ^ search workbenchscreen */
  vpo=&(wbs.ViewPort); /* WBscreen viewport */
  rpo=&(wbs.RastPort);
  w=wbs.Width;
  h=wbs.Height;
  for(i=0;i<anz;i++) /* initialize positions */
   {
    x[i]=RangeRand(LI(w));
    y[i]=RangeRand(LI(h));
   }
 }
 
go(text)    /* to use a function like this one is VERY usefull */
char *text;
 {
  int i;
  
  if(MyWindow)
    for(i=0;i<anz;i++)
     {
      SetAPen(rpo,LI(u[i]));
      WritePixel(rpo,LI(x[i]),LI(y[i]));
     }
  if(text) puts(text); /* tell about errror */
  
  if(MyWindow) CloseWindow(MyWindow);
  if(GfxBase) CloseLibrary(GfxBase);
  if(IntuitionBase) CloseLibrary(IntuitionBase);
  exit(0);
 }

/* :-) Always looking for fun (-:
   . .       CLUSTER          · ·               
    ª          °ª°             ª   
*/

