/*   bug 
 
bacteria life simulation

*/


/*include.pre contains the following precompiled includes :
	#include <functions.h>
	#include <stdio.h>
	#include <math.h>
	#include <exec/types.h>
	#include <graphics/gfxbase.h>
	#include <graphics/sprite.h>
	#include <graphics/gels.h>
	#include <intuition/intuition.h>
*/
#include <graphics/gfxmacros.h>

/* not yet needed for this pgm 
#include <hardware/custom.h>
#include <fcntl.h>
#include <libraries/dos.h>
#include <devices/audio.h>
#include <exec/memory.h>
*/

#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
#define ABS(a) ((a<0)?(-(a)):(a))

extern void *GetMsg();
struct Screen *scr;
struct Window *win, *pwin, *rwin, *gwin;
struct RastPort *rp, *prp, *rrp, *grp;
struct ViewPort *vp;
struct GfxBase *GfxBase;
struct IntuitionBase *IntuitionBase;
struct IntuiMessage *msg;
struct NewScreen sspecs = { 0,0,320,200, 3, 0, 1, NULL ,CUSTOMSCREEN, NULL, NULL, NULL, NULL };

UBYTE GadgetSIBuff11[20] = { "ffffffrfffffflffff?" };
struct StringInfo GadgetSInfo11 = {
	GadgetSIBuff11,	NULL, 0, 20, 10, 0,0,0,0,0,0,0,NULL };
struct Gadget gadget11 = {
	NULL,150,22,160,8,	NULL,GADGIMMEDIATE+STRINGRIGHT,STRGADGET,NULL,
	NULL,NULL,NULL,(APTR)&GadgetSInfo11,NULL,NULL };

UBYTE GadgetSIBuff10[20] = { "ffffffrffffffrfffff" };
struct StringInfo GadgetSInfo10 = {
	GadgetSIBuff10,	NULL, 0, 20, 10, 0,0,0,0,0,0,0,NULL };
struct Gadget gadget10 = {
	&gadget11,150,34,160,8,	NULL,GADGIMMEDIATE+STRINGRIGHT,STRGADGET,NULL,
	NULL,NULL,NULL,(APTR)&GadgetSInfo10,NULL,NULL };

/* 9 is not currently in use */
UBYTE GadgetSIBuff9[16] = { "0" };
struct StringInfo GadgetSInfo9 = {
	GadgetSIBuff9,	NULL, 0, 15, 10, 0,0,0,0,0,0,0,NULL };
struct Gadget gadget9 = {
	NULL,214,116,60,8,	NULL,GADGIMMEDIATE+STRINGRIGHT+LONGINT,STRGADGET,NULL,
	NULL,NULL,NULL,(APTR)&GadgetSInfo9,NULL,NULL };

UBYTE GadgetSIBuff8[16] = { "100" };
struct StringInfo GadgetSInfo8 = {
	GadgetSIBuff8,	NULL, 0, 15, 10, 0,0,0,0,0,0,100,NULL };
struct Gadget gadget8 = {
	NULL,214,104,60,8,	NULL,GADGIMMEDIATE+STRINGRIGHT+LONGINT,STRGADGET,NULL,
	NULL,NULL,NULL,(APTR)&GadgetSInfo8,NULL,NULL };

UBYTE GadgetSIBuff7[16] = { "10" };
struct StringInfo GadgetSInfo7 = {
	GadgetSIBuff7,	NULL, 0, 15, 10, 0,0,0,0,0,0,10,NULL };
struct Gadget gadget7 = {
	&gadget8,214,92,60,8,	NULL,GADGIMMEDIATE+STRINGRIGHT+LONGINT,STRGADGET,NULL,
	NULL,NULL,NULL,(APTR)&GadgetSInfo7,NULL,NULL };

UBYTE GadgetSIBuff6[16] = { "1200" };
struct StringInfo GadgetSInfo6 = {
	GadgetSIBuff6,	NULL, 0, 15, 10, 0,0,0,0,0,0,1200,NULL };
struct Gadget gadget6 = {
	&gadget7,214,80,60,8,	NULL,GADGIMMEDIATE+STRINGRIGHT+LONGINT,STRGADGET,NULL,
	NULL,NULL,NULL,(APTR)&GadgetSInfo6,NULL,NULL };

UBYTE GadgetSIBuff5[16] = { "2000" };
struct StringInfo GadgetSInfo5 = {
	GadgetSIBuff5,	NULL, 0, 15, 10, 0,0,0,0,0,0,2000,NULL };
struct Gadget gadget5 = {
	&gadget6,214,68,60,8,	NULL,GADGIMMEDIATE+STRINGRIGHT+LONGINT,STRGADGET,NULL,
	NULL,NULL,NULL,(APTR)&GadgetSInfo5,NULL,NULL };

UBYTE GadgetSIBuff4[16] = { "5" };
struct StringInfo GadgetSInfo4 = {
	GadgetSIBuff4,	NULL, 0, 15, 10, 0,0,0,0,0,0,5,NULL };
struct Gadget gadget4 = {
	&gadget5,214,56,60,8,	NULL,GADGIMMEDIATE+STRINGRIGHT+LONGINT,STRGADGET,NULL,
	NULL,NULL,NULL,(APTR)&GadgetSInfo4,NULL,NULL };

UBYTE GadgetSIBuff3[16] = { "99" };
struct StringInfo GadgetSInfo3 = {
	GadgetSIBuff3,	NULL, 0, 15, 10, 0,0,0,0,0,0,99,NULL };
struct Gadget gadget3 = {
	&gadget4,214,44,60,8,	NULL,GADGIMMEDIATE+STRINGRIGHT+LONGINT,STRGADGET,NULL,
	NULL,NULL,NULL,(APTR)&GadgetSInfo3,NULL,NULL };

UBYTE GadgetSIBuff2[16] = { "50" };
struct StringInfo GadgetSInfo2 = {
	GadgetSIBuff2,	NULL, 0, 15, 10, 0,0,0,0,0,0,50,NULL };
struct Gadget gadget2 = {
	&gadget3,214,32,60,8,	NULL,GADGIMMEDIATE+STRINGRIGHT+LONGINT,STRGADGET,NULL,
	NULL,NULL,NULL,(APTR)&GadgetSInfo2,NULL,NULL };

UBYTE GadgetSIBuff1[16] = { "300" };
struct StringInfo GadgetSInfo1 = {
	GadgetSIBuff1,	NULL, 0, 15, 10, 0,0,0,0,0,0,300,NULL };
struct Gadget gadget1 = {
	&gadget2,214,20,60,8,	NULL,GADGIMMEDIATE+STRINGRIGHT+LONGINT,STRGADGET,NULL,
	NULL,NULL,NULL,(APTR)&GadgetSInfo1,NULL,NULL };

struct NewWindow wspecs = { 0,0,320,200,0,1,
				MOUSEBUTTONS | VANILLAKEY | MENUPICK,
				SMART_REFRESH | ACTIVATE,
				NULL, NULL, (UBYTE *)"BUG WINDOW",
				NULL, NULL, 0,0,0,0,CUSTOMSCREEN };
struct NewWindow pwspecs = { 0,0,320,200,0,1,
				CLOSEWINDOW,
				SIMPLE_REFRESH | ACTIVATE | WINDOWCLOSE,
				&gadget1, NULL, (UBYTE *)"PARAMETER WINDOW",
				NULL, NULL, 0,0,0,0,CUSTOMSCREEN };
struct NewWindow gwspecs = { 0,0,320,200,0,1,
				CLOSEWINDOW,
				SIMPLE_REFRESH | ACTIVATE | WINDOWCLOSE,
				&gadget10, NULL, (UBYTE *)"GENE WINDOW",
				NULL, NULL, 0,0,0,0,CUSTOMSCREEN };
struct NewWindow rwspecs = { 0,0,320,200,0,1,
				CLOSEWINDOW,
				SIMPLE_REFRESH | ACTIVATE | WINDOWCLOSE,
				NULL, NULL, (UBYTE *)"REPORT WINDOW",
				NULL, NULL, 0,0,0,0,CUSTOMSCREEN };

struct IntuiText M0text[7] = {
	{0, 0, JAM1, 10, 2, NULL,(UBYTE *)"GENES",   NULL},
	{0, 0, JAM1, 10, 2, NULL,(UBYTE *)"PARAMS",  NULL},
	{0, 0, JAM1, 10, 2, NULL,(UBYTE *)"GO",    	NULL},
	{0, 0, JAM1, 10, 2, NULL,(UBYTE *)"CONTINUE",NULL},
	{0, 0, JAM1, 10, 2, NULL,(UBYTE *)"REPORT",  NULL},
	{0, 0, JAM1, 10, 2, NULL,(UBYTE *)"TRAILS",  NULL},
	{0, 0, JAM1, 10, 2, NULL,(UBYTE *)"QUIT",    NULL}
};
struct MenuItem Menu0[7] = {
     {&Menu0[1], 0,  0, 76, 12, ITEMTEXT |
		 ITEMENABLED | HIGHCOMP, 0, &M0text[0],NULL,0,NULL, 0 },
     {&Menu0[2], 0, 12, 76, 12, ITEMTEXT |
		 ITEMENABLED | HIGHCOMP, 0, &M0text[1],NULL,0,NULL, 0 },
	{&Menu0[3], 0, 24, 76, 12, ITEMTEXT |
		 ITEMENABLED | HIGHCOMP, 0, &M0text[2],NULL,0,NULL, 0 },
	{&Menu0[4], 0, 36, 76, 12, ITEMTEXT |
		 ITEMENABLED | HIGHCOMP, 0, &M0text[3],NULL,0,NULL, 0 },
	{&Menu0[5], 0, 48, 76, 12, ITEMTEXT |
		 ITEMENABLED | HIGHCOMP, 0, &M0text[4],NULL,0,NULL, 0 },
	{&Menu0[6], 0, 60, 76, 12, ITEMTEXT |
		 ITEMENABLED | HIGHCOMP | CHECKIT, 0, &M0text[5],NULL,0,NULL, 0 },	
	{NULL,      0, 72, 76, 12, ITEMTEXT |
		 ITEMENABLED | HIGHCOMP, 0, &M0text[6],NULL,0,NULL, 0 },	
};
struct Menu proj_menu = { NULL,  1, 0, 77, 10, 
			MENUENABLED, "PROJECT",          &Menu0[0]  };

#define MAXBUGS 1200
#define MAXAGE  250
#define BEGIN	 0
#define CONTIN  1
 
struct abug {
	int    x,y;		/* screen coordinates */
	int    color;		/* color */
	int    type;		/* 0, 1 */
	short  dir;		/* direction of movement */
	short  nrg;		/* food supply */
	short  idx;		/* current index in movement pattern */
	short  age; 	     /* age */
} bug[MAXBUGS];

char *mov[2];  /* movement patterns */
int len[2];

int foodval = 1, births[2], starved[2], oldage[2], maxage=MAXAGE;
int initnrg = 200, foodrate = 4,	initfood = 1000, cycles = 2000;
int startbugs = 50, alive[2] = {50,50}, lastbug = 50;
int divnrg = 200, eaten[2] = 0, flags = 0;
int udrawpen = 5;	/* for eraseing or leaving a trail */
int trails = FALSE;

/**************************************************************************/
main(argc,argv)
int argc;
char *argv[];
{
	long class;
	short code;

	init();
	if( argc > 1) foodval = atoi(argv[1]);

	while(1) {
		while( (msg = GetMsg( win->UserPort)) != NULL) ReplyMsg(msg);
		WaitPort(win->UserPort);
		msg = (struct IntuiMessage *)GetMsg( win->UserPort );
		class = msg->Class;
		code = msg->Code;
		ReplyMsg(msg);
		switch( class ) {
			case CLOSEWINDOW : 	quit();
			case VANILLAKEY  :	switch( code ) {
								case 'g' :
								case 'G' : go(BEGIN);	break;
								case 'c' : 
								case 'C' : go(CONTIN); break;
								case 'q' :
								case 'Q' : quit();
						    	}
						    	break;
			case MENUPICK    :	switch( MENUNUM(code) ) {
								case 0 : switch( ITEMNUM(code) ) {
											case 0 : setgenes();
												    break;
											case 1 : setparms();
												    break;
											case 2 : go(BEGIN);
												    break;
											case 3 : go(CONTIN);
												    break;
											case 4 : report();
												    break;
											case 5 : if( trails == TRUE){
														Menu0[5].Flags &= ~CHECKED;
														trails = FALSE;
												    }	
												    else {
														Menu0[5].Flags |= CHECKED;
														trails = TRUE;
												    }
												    break;
						 					case 6 : quit();
									    }
									    break;
								case 1 : break;

							}
		}
	}
}

init()
{
	int seed;
	char *OpenLibrary();
	static USHORT colormap[20] = {
		0x0000,0x0ddf,0x0ff0,0x0f0f,	/* 0,1 menus and gadgets 2,3 bugs */
		0x0234,0x0922,0x0000,0x0ff0,  /* 4 food 5 trails  6,7 menus & gad  */

		0x0f55,0x055f,0x05f5,0x0030,  /* unused in 3 plane screen   */
		0x00ff,0x00f0,0x0000,0x0ff0,	/* */

		0x0000,0x0f00,0x0666,0x0700   /* pointer colors */
	};

	GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",1);
	IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",1);

	scr = OpenScreen( &sspecs );	wspecs.Screen = scr;
	win = OpenWindow( &wspecs );	rp  = win->RPort;

	vp  = (struct ViewPort *)ViewPortAddress(win);
	LoadRGB4(vp, &colormap, 20);
	SetMenuStrip(win, &proj_menu);
	srand( (seed = VBeamPos()) );
}

quit()
{
	if( win ) CloseWindow(win);
	if( scr ) CloseScreen(scr);
	if( GfxBase ) CloseLibrary( GfxBase );
	if( IntuitionBase) CloseLibrary( IntuitionBase );
	exit(0);
}

/* directions nsew = 0123 */

go(mode)
int mode;
{
	long class;
	short code;
	int col,tx, ty, i, winner, loser;
	char c, buf[20];
	static int cy = 0;
	register int b;

	ClearMenuStrip(win);
	if(trails) udrawpen = 5;
	else udrawpen = 0;

	if( mode == BEGIN ) {
		lastbug = 2*startbugs;	/* lastbug is last used structure index */
		alive[0] = startbugs;
		alive[1] = startbugs;
		births[0] = starved[0] = oldage[0] = eaten[0] = 0;
		births[1] = starved[1] = oldage[1] = eaten[1] = 0;
		initbugs();
		cy = 0;
	}
	SetAPen(rp,0);	SetBPen(rp,1);	Move(rp,200,7);	Text(rp,"CYCLES:   ",7);     
	for( ; cy<cycles; cy++) {
		if(cy%10==0) {
			sprintf(buf,"%ld  ",cy);	SetAPen(rp,0);
			Move(rp,264,7);	Text(rp,buf,strlen(buf));
		}
		if( (msg = (struct IntuiMessage *)GetMsg( win->UserPort)) != NULL){
			class = msg->Class;
			code = msg->Code;
			ReplyMsg(msg);
			break;
		}
		if( (alive[0]+alive[1]) <= 0 ) break;
		newfood();
		for(b=0; b<lastbug; b++ ) {
			if( bug[b].nrg == -86 ) continue; /* he is dead */
			--bug[b].nrg;	++bug[b].age;
			if( bug[b].nrg <= 0 || bug[b].age > maxage) {
				rip(b);	continue;
			}
			if( bug[b].nrg > divnrg ) mitosis(b);
			switch( (c=*(mov[bug[b].type]+ bug[b].idx)) ) {
				case 'l' : bug[b].dir = (--bug[b].dir & 3); break;
				case 'r' : bug[b].dir = (++bug[b].dir & 3); break;
				case '?' : bug[b].dir = rand() & 3; break;
				case 'f' : switch( bug[b].dir ) {		/* test location */
							case 0 :	tx = bug[b].x;	ty = bug[b].y-1;
									col = ReadPixel(rp,tx,ty);
									break;
							case 1 :	tx = bug[b].x+1; ty = bug[b].y;
									col = ReadPixel(rp,tx,ty);
									break;
							case 2 :	tx = bug[b].x;	ty = bug[b].y+1;
									col = ReadPixel(rp,tx,ty);
									break;
							case 3 :	tx = bug[b].x-1; ty = bug[b].y;
									col = ReadPixel(rp,tx,ty);
									break;
 						 }
						 switch(col) {
						 	case 4 :  /* eat food */
									SetAPen(rp,0);
									WritePixel(rp,tx,ty);
									bug[b].nrg += foodval;
									break;
						 	case 2 :
							case 3:  /* if alien - fight */
									if( col != bug[b].color) {
										for(i=0;i<lastbug;++i) { /* find opponent */
											if(bug[i].x==tx && bug[i].y==ty) {
												winner = (bug[i].nrg>bug[b].nrg)?i:b;
												loser = (winner==i)?b:i;
												continue;
											}
										}
										SetAPen(rp,0);
										WritePixel(rp,bug[b].x,bug[b].y);
										bug[winner].x = tx;
										bug[winner].y = ty;
										bug[loser].nrg = -86;
										bug[winner].nrg += bug[loser].nrg;
										SetAPen(rp,bug[winner].color);
										WritePixel(rp,tx,ty);
										--alive[bug[loser].type];
										++eaten[bug[loser].type];
									}
									else {	/*same species  */
						 				bug[b].dir = rand()%4; /*turn random */
						 			}
									break;
							case 1 :  /* hit a wall */
									bug[b].dir = rand()%4; /*turn random */
									break;
							case 0 :
						 	default:  /* not occupied, move */
								     SetAPen(rp,udrawpen);
 						     		WritePixel(rp,bug[b].x,bug[b].y);
									bug[b].x = tx;
									bug[b].y = ty;
									SetAPen(rp,bug[b].color);
									WritePixel(rp,bug[b].x,bug[b].y);
									break;
						}
			}	
			if( ++bug[b].idx > len[bug[b].type]) bug[b].idx = 0;
		}
		WaitTOF();
	}
	SetMenuStrip(win, &proj_menu);
}

initbugs()
{
	int i, j, col, typ;
	char *buf;

	mov[0] = GadgetSIBuff10;
	mov[1] = GadgetSIBuff11;
	len[0] = strlen(GadgetSIBuff10);
	len[1] = strlen(GadgetSIBuff11);

	col = 2;	typ = 0;
	for(j=0; j<2; j++) {
		for( i=j*startbugs; i<startbugs+(j*startbugs); ++i) {
			bug[i].x = rand()%316+2;
			bug[i].y = rand()%188+10;
			bug[i].dir = rand()%4;
			bug[i].nrg = initnrg;
			bug[i].idx = rand()%len[typ];
			bug[i].age = rand()%maxage;
			bug[i].type = typ;
			bug[i].color = col;
		}
		col = 3; typ = 1;
	}
 
	SetAPen(rp,0);
	RectFill(rp,2,10,318,198);
	SetAPen(rp,4); 		/* set out food */
	for( i=0; i<initfood; ++i) WritePixel(rp,rand()%316+2,rand()%188+10);
}	

newfood()
{
	int i, x, y, c;

	for(i=0; i<foodrate; ++i) {
		do {
			x = rand()%316 + 2;
			y = rand()%188 + 10;
			c = ReadPixel(rp,x,y);
		} while( c != 0 );   		/* while not color 0 */
		SetAPen(rp,4);
		WritePixel(rp,x,y);
	}
}

report()
{
	int i, avg[2], cnt[2], sum[2];
	char buf[81];

	rwspecs.Screen = scr;
	rwin = OpenWindow(&rwspecs);
	rrp = rwin->RPort;

	cnt[0]=sum[0]=0;
	cnt[1]=sum[1]=0;
	for(i=0; i<lastbug; i++) {
		if( bug[i].nrg > 0 ) {
			++cnt[bug[i].type];
			sum[bug[i].type] += bug[i].nrg;
		}
	}

	avg[0] = (cnt[0]>0) ? sum[0]/cnt[0] : 0;
	avg[1] = (cnt[1]>0) ? sum[1]/cnt[1] : 0;

	SetAPen(rrp,2);
	sprintf(buf,"Initial number                 %4ld",startbugs);
     Move(rrp,10,20);	Text(rrp,buf,strlen(buf));
	sprintf(buf,"Births                         %4ld",births[0]);
     Move(rrp,10,30);	Text(rrp,buf,strlen(buf));
	sprintf(buf,"                 Total         %4ld",births[0]+startbugs);
     Move(rrp,10,40);	Text(rrp,buf,strlen(buf));

	sprintf(buf,"Starved                        %4ld",starved[0]);
     Move(rrp,10,60);	Text(rrp,buf,strlen(buf));
	sprintf(buf,"Died of old age                %4ld",oldage[0]);
    	Move(rrp,10,70);	Text(rrp,buf,strlen(buf));
	sprintf(buf,"Eaten                          %4ld",eaten[0]);
    	Move(rrp,10,80);	Text(rrp,buf,strlen(buf));
	sprintf(buf,"                 Total         %4ld",starved[0] + oldage[0] + eaten[0]);
     Move(rrp,10,90);	Text(rrp,buf,strlen(buf));

	sprintf(buf,"Currently alive                %4ld",alive[0]);
     Move(rrp,10,110);	Text(rrp,buf,strlen(buf));
	sprintf(buf,"Avgerage energy                %4ld",avg[0]);
     Move(rrp,10,120);	Text(rrp,buf,strlen(buf));


	SetAPen(rrp,3);
	sprintf(buf,"%4ld",startbugs);
     Move(rrp,208,20);	Text(rrp,buf,strlen(buf));
	sprintf(buf,"%4ld",births[1]);
     Move(rrp,208,30);	Text(rrp,buf,strlen(buf));
	sprintf(buf,"%4ld",births[1]+startbugs);
     Move(rrp,208,40);	Text(rrp,buf,strlen(buf));

	sprintf(buf,"%4ld",starved[1]);
     Move(rrp,208,60);	Text(rrp,buf,strlen(buf));
	sprintf(buf,"%4ld",oldage[1]);
    	Move(rrp,208,70);	Text(rrp,buf,strlen(buf));
	sprintf(buf,"%4ld",eaten[1]);
    	Move(rrp,208,80);	Text(rrp,buf,strlen(buf));
	sprintf(buf,"%4ld",starved[1] + oldage[1] + eaten[1]);
     Move(rrp,208,90);	Text(rrp,buf,strlen(buf));

	sprintf(buf,"%4ld",alive[1]);
     Move(rrp,208,110);	Text(rrp,buf,strlen(buf));
	sprintf(buf,"%4ld",avg[1]);
     Move(rrp,208,120);	Text(rrp,buf,strlen(buf));


	WaitPort(rwin->UserPort);
	msg = (struct IntuiMessage *)GetMsg(rwin->UserPort );
	ReplyMsg(msg);
	CloseWindow(rwin);
}

mitosis(n)
int n;
{
	int c, x, y, xo, yo, new, i, j;

	if( (alive[0]+alive[1]) >= MAXBUGS-1) return();	/* return if allocated space used */
	for(yo=-1; yo<2; ++yo) {           /* find a spot to have baby */
		for(xo=-1; xo<2; ++xo) {
			c = ReadPixel(rp, bug[n].x+xo, bug[n].y+yo);
			if( c == 0 ) {
				x = bug[n].x + xo;
				y = bug[n].y + yo;
				goto divide;		/* found it */
			}
		}
	}
	return();	/* no space was found */

  divide:
	/* look for empty structure left by a dead bug */
	for(i=0, new = -1; i<lastbug; ++i) {
		if( bug[i].nrg == -86 ){
			 new = i;		break;
		}
	}
	++alive[bug[n].type];
	if( new == -1 ) {		/* if no empty spots make a new one */
		new = ++lastbug-1;
	}
	bug[new].x = x;		
	bug[new].y = y;
	bug[new].dir = rand()%4;
	bug[new].nrg = bug[n].nrg/2;
	bug[new].idx = rand()%len[bug[n].type];		
	bug[new].age = 0; 		
	bug[n].nrg /= 2;
	bug[new].type = bug[n].type;
	bug[new].color = bug[n].color;
	++births[bug[n].type];
}

setparms()
{
	int i, j;
	long class;
	short code;
	char buf[16];
	static char title[8][24] = {
		{  "Age at death (10-1000)"	},
		{  "Food value (0-1000)"      },
		{  "Initial energy(10-1000)"  },
		{  "Food rate (0-100)"		},
		{  "Cycles (0-100000)"		},
		{  "Initial food (0-10000)"   },
		{  "Initial # bugs(1-500)"   },
		{  "Mitosis nrg(10-10000)"    },
	};

	pwspecs.Screen = scr;
	pwin = OpenWindow( &pwspecs );	prp  = pwin->RPort;

	/* gadget borders */
	for(i=0; i<8; ++i) {
		j = 12*i;
		SetAPen(prp,3); 	RectFill(prp,210,18+j,270,29+j);
		SetAPen(prp,0); 	RectFill(prp,212,19+j,268,28+j);
		SetAPen(prp,1);
		Move(prp,20,26+j);	Text(prp,title[i],strlen(title[i]));
	}

	RefreshGadgets(&gadget1,pwin,NULL);

	while( (msg = GetMsg( pwin->UserPort)) != NULL) ReplyMsg(msg);
	WaitPort(pwin->UserPort);
	msg = (struct IntuiMessage *)GetMsg( pwin->UserPort );
	class = msg->Class;
	code = msg->Code;
	ReplyMsg(msg);
	maxage    = GadgetSInfo1.LongInt;
	foodval   = GadgetSInfo2.LongInt;
	initnrg   = GadgetSInfo3.LongInt;
     foodrate  = GadgetSInfo4.LongInt;
	cycles    = GadgetSInfo5.LongInt;
	initfood  = GadgetSInfo6.LongInt;
	startbugs = GadgetSInfo7.LongInt;
	divnrg    = GadgetSInfo8.LongInt;

	if( maxage < 10) GadgetSInfo1.LongInt = maxage = 10;
	if( maxage > 1000) GadgetSInfo1.LongInt = maxage = 1000; 
	if( foodval < 0 ) GadgetSInfo2.LongInt = foodval = 0;
	if( foodval > 1000) GadgetSInfo2.LongInt = foodval = 1000; 
	if( initnrg < 10 ) GadgetSInfo3.LongInt = initnrg = 10;
	if( initnrg > 1000 ) GadgetSInfo3.LongInt = initnrg = 1000;
	if( foodrate < 0 ) GadgetSInfo4.LongInt = foodrate = 0;
	if( foodrate > 100 ) GadgetSInfo4.LongInt = foodrate = 100;
	if( cycles > 100000 ) GadgetSInfo5.LongInt = cycles = 100000;
	if( cycles < 1 ) cycles = 2000000000; 
	if( initfood < 0 ) GadgetSInfo6.LongInt = initfood = 0;
	if( initfood > 10000 ) GadgetSInfo6.LongInt = initfood = 10000;
	if( startbugs < 1 ) GadgetSInfo7.LongInt = startbugs = 1;
	if( startbugs > 500 ) GadgetSInfo7.LongInt = startbugs = 500;
	if( divnrg < 10 ) GadgetSInfo8.LongInt = divnrg = 10;	
	if( divnrg > 10000 ) GadgetSInfo8.LongInt = divnrg = 10000;	

	sprintf(buf,"%ld",maxage);
	strcpy(GadgetSIBuff1,buf);
	sprintf(buf,"%ld",foodval);
	strcpy(GadgetSIBuff2,buf);
	sprintf(buf,"%ld",initnrg);
	strcpy(GadgetSIBuff3,buf);
	sprintf(buf,"%ld",foodrate);
	strcpy(GadgetSIBuff4,buf);
	sprintf(buf,"%ld",initfood);
	strcpy(GadgetSIBuff6,buf);
	sprintf(buf,"%ld",startbugs);
	strcpy(GadgetSIBuff7,buf);
	sprintf(buf,"%ld",divnrg);
	strcpy(GadgetSIBuff8,buf);

	CloseWindow(pwin);
}

rip(b)
int b;
{
	if( bug[b].age > maxage ) ++oldage[bug[b].type];
	else ++starved[bug[b].type];
	--alive[bug[b].type];

	SetAPen(rp,4);					/* change it to food */
	WritePixel(rp,bug[b].x,bug[b].y);
	bug[b].nrg = -86; 				/* signifying he dead */
	WaitTOF();
}


setgenes()
{
	int i, j;
	long class;
	short code;
	static char title[2][19] = {
		{  "Type 1"	},
		{  "Type 2"     }
	};

	gwspecs.Screen = scr;
	gwin = OpenWindow( &gwspecs );	grp  = gwin->RPort;

	/* gadget borders */
	for(i=0; i<2; ++i) {
		j = 12*i;
		SetAPen(grp,3); 	RectFill(grp,106,20+j,317,31+j);
		SetAPen(grp,0); 	RectFill(grp,108,21+j,315,30+j);
		SetAPen(grp,3-i);
		Move(grp,30,28+j);	Text(grp,title[i],strlen(title[i]));
	}
	RefreshGadgets(&gadget10,gwin,NULL);

	while( (msg = GetMsg( gwin->UserPort)) != NULL) ReplyMsg(msg);
	WaitPort(gwin->UserPort);
	msg = (struct IntuiMessage *)GetMsg( gwin->UserPort );
	class = msg->Class;
	code = msg->Code;
	ReplyMsg(msg);
	CloseWindow(gwin);
}



