/* Turmites.c */
/* Scientific American September 1989 */
/* Lloyd Linstrom */
#include "exec/types.h"
#include "intuition/intuition.h"
#include "exec/memory.h"
#include "graphics/gfxmacros.h"

#define XMAX 300			/* Number of pixels x direction */
#define YMAX 185			/* Number of pixels y direction */

struct Window *w,*OpenWindow();		/* pointer to a window */
struct RastPort *rp;			/* pointer to a RastPort */
struct Screen *s,*OpenScreen();		/* pointer to a screen */
struct ViewPort *vp,*ViewPortAddress();	/* pointer to a ViewPort */
struct IntuiMessage *msg, *GetMsg();	/* pointer to Intuition Message */
struct Library *IntuitionBase, *GfxBase, *OpenLibrary();
long ReadPixel();
void CloseScreen(), CloseWindow(), CloseLibrary();
void SetAPen(), WritePixel(), ReplyMsg(); 
void SetWindowTitles();

short deltastate[ ] = {1, 4, 2, 7, 3, 13, 4, 7, 8, 9, 3, 12,
			6, 11, 5, 13};	/* change in state indexed by color */
short dmove[ ] = {1, 1, 2, 0, 1, -1, 1, -1, 0, 1, 2, 1, 1, -1, -1, 1};
long dx[ ] = { 0,  1, -1,  0};		/* Conversion from dir to x,y */
long dy[ ] = { -1, 0,  0,  1};
struct turmiteinfo 
{
	short num;			/* Termite number */
	short state;			/* State code for turmite */
	short dir;			/* Direction code for turmite */
	long x;				/* x coordinate for turmite */
	long y;				/* y coordinate for turmite */
};
struct turmiteinfo turmites[200];		/* NTURMITES turmites */

UBYTE titlestr[40];			/* Window Title */

struct TextAttr TextFont = { (UBYTE *)"topaz.font", 8, 0, 0 };

struct NewScreen turmScreen = {
	0L, 0L,
	320L, 200L,
	4L,			/* Four bit planes */
	0L, 1L,
	0L,
	CUSTOMSCREEN,
	&TextFont,
	(UBYTE *)"Tur-mite Screen",
	NULL
};


struct NewWindow turmWindow = {
	0L, 0L,
	320L, 200L,
	0L, 
	1L,
	CLOSEWINDOW,
	WINDOWCLOSE | WINDOWDEPTH | WINDOWSIZING
	 | WINDOWDRAG | ACTIVATE | GIMMEZEROZERO,
	NULL, NULL,
	(UBYTE *) "Tur-mites",
	NULL,
	NULL, 
	50L, 
	30L, 
	320L, 
	200L,
	CUSTOMSCREEN
};


int HandleEvent(code)		/* Handle messages from Intuition */
long code;			/* provided by main */
{
	switch (code)
	{
	case CLOSEWINDOW:
		return(0);
		break;
	default:
		return(1);
		break;
	}
}

int init()			/* Open Libraries, Screen, & Window  */
{
	long i;
	
	IntuitionBase = NULL;
	s = NULL;
	w = NULL;

	GfxBase = OpenLibrary("graphics.library", 0L);
	if(GfxBase == NULL) return(0);

	IntuitionBase = OpenLibrary("intuition.library", 0L);
	if(IntuitionBase == NULL) return(0);

	s = OpenScreen(&turmScreen);
	if(s == NULL) return(0);

	turmWindow.Screen = s;		/* Tie window to screen */
	w = OpenWindow(&turmWindow);
	if (w == NULL) return(0);

	vp = ViewPortAddress(w);	/* ViewPort address of Window  */
	rp = w->RPort;

	return(1);		/* Successful initialization */
}


void endit()			/* Close Window, Screen, &  Librarys  */
{
	if(w) CloseWindow(w);
	if(s) CloseScreen(s);
	if(GfxBase) CloseLibrary(GfxBase);
	if(IntuitionBase) CloseLibrary(IntuitionBase);
	exit(0);
}

void moveturmite(tm)
struct turmiteinfo *tm;
{
	register long x, y;
	long newcolor;
	short delta, color;
	
	x = tm->x;
	y = tm->y;
	color = ReadPixel(rp, x, y);

	newcolor = (color + tm->state + tm->num) % 16;	/* Set new color */
	SetAPen(rp, newcolor);
	WritePixel(rp, x, y);

	/* Set new x and y */
	delta = dmove[(color - tm->state) & 0xf];
	tm->dir = (tm->dir + delta) & 3;

	x += dx[tm->dir];
	if(x < 0) x += XMAX;
	if(x >= XMAX) x -= XMAX;
	tm->x = x;

	y += dy[tm->dir];
	if(y < 0) y += YMAX;
	if(y >= YMAX) y -= YMAX;
	tm->y = y;

	/* Set new state */
	tm->state = (tm->state + deltastate[color]) % 16;
}


main(argc, argv)
int argc;
char *argv[];
{
	
	int idcmpcode;
	short i, nturmites;

	if(argc > 1)
	{
		nturmites = atoi(argv[1]);

	}
	else 
	{
		printf("Tur-mite Program\n\n");
		printf("Scientific American  September 1989\n");
		printf("Enter number turmites [1-200]: ");
		scanf("%d", &nturmites);
	}	
	if(nturmites < 1) nturmites = 1;
	if(nturmites > 200) nturmites = 200;	

	if(init() == 0) endit();	/* Initialize everything */
	srand(time(NULL));		/* Set PRN generator */
	for(i=0; i<nturmites; i++)	/* Initialize turmites */
	{
		turmites[i].num = i;
		turmites[i].x = (long) rand() % XMAX;
		turmites[i].y = (long) rand() % YMAX;
		turmites[i].state = rand() % 16;
		turmites[i].dir = rand() % 4;
	}
	sprintf(&titlestr[0], "%3d Tur-mites", nturmites); /* Set title */
	SetWindowTitles(w, titlestr, -1L);

	idcmpcode = 1;			/* end flag */

	while(idcmpcode >0)
	{
		for(i=0; i<nturmites; i++)	/* Move turmites */
		{
			moveturmite(&turmites[i]);
		}
		
		while((msg = GetMsg(w->UserPort))!=NULL)
		{
			idcmpcode = idcmpcode * HandleEvent(msg->Class);
			ReplyMsg(msg);
		}

	}
	endit();
}
