/* IceFrac.c - Diffusion Limited Aggregation simulator */
/* Version 2.2 */
/* (c) 1989 by Lars R. Clausen */
/* PaletteReq (c) 1989 by Jonathan Potter */
#include <exec/types.h>
#include <graphics/gfxbase.h>
#include <graphics/view.h>
#include <intuition/intuition.h>
#include <libraries/iff.h>
#include <stdio.h>
#include <hardware/blit.h>
#include <hardware/dmabits.h>
#include <math.h>
#include <PaletteReq.h>

/*#define USEBLIT*/

void *OpenLibrary();
struct Window *OpenWindow();
struct Screen *OpenScreen();
struct IntuiMessage *GetMsg();

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *IFFBase = NULL;
struct Window *w;
struct Screen *s;

long code=1,ColCount=250,ColJump=250,Planes=5;
int *BZero = (0xdff002L);
char ifffile[] = "FracPic001";
unsigned char MoveBits=224;
unsigned char TestBits=224;
int Die=1,XSize=320,YSize=255,A1MinX=2,A1MinY=252,A1MaxX=317,A1MaxY=252;
int EnterOnEdge=1,A2MinX=-1,A2MinY=127,A2MaxX=160,A2MaxY=127,MaxIt=100,Margin=2;

char UndoBuff[4],XSBuff[4]="320",YSBuff[4]="255",A1XMinBuff[4]="2",
A1YMinBuff[4]="252",A1XMaxBuff[4]="317",A1YMaxBuff[4]="252",A2XMinBuff[4]="-1",
A2YMinBuff[4]="127",A2XMaxBuff[4]="160",A2YMaxBuff[4]="127",MIBuff[4]="100",
MargBuff[4]="2",ColBuff[4]="250";
char HiRes=0,Lace=0,Pal=1,A2Off=1;
struct Gadget BigGad = { NULL,0,0,320,255,GADGHNONE,RELVERIFY|FOLLOWMOUSE|
	GADGIMMEDIATE,BOOLGADGET,NULL,NULL,NULL,NULL,NULL,0,NULL};

struct NewScreen ns = {0,0,320,256,5,1,2,NULL,CUSTOMSCREEN,NULL,NULL,NULL,NULL};

struct NewWindow nw = {
	0,1,320,255,-1,-1,GADGETUP|MOUSEMOVE|VANILLAKEY|GADGETDOWN,NOCAREREFRESH|ACTIVATE|BORDERLESS,
	&BigGad,NULL,NULL, NULL,NULL,0,0,0,0,CUSTOMSCREEN};

short ColorMap[32] = {     /* format 0x0RGB */
 /*  0-7  */  0x0000,0x0FFF,0x0DDF,0x0CCF,0x0AAF,0x099F,0x077F,0x066F ,
 /*  8-15 */  0x044F,0x046D,0x047B,0x0489,0x0496,0x04B4,0x04D2,0x04F0 ,
 /* 16-23 */  0x06F0,0x08F0,0x0BF0,0x0DF0,0x0FF0,0x0FD0,0x0FB0,0x0F90 ,
 /* 24-31 */  0x0F70,0x0F50,0x0F00,0x0F55,0x0F77,0x0F99,0x0FBB,0x0FDD };

SHORT GadPairs[6][10]={{-1,-1,49,-1,49,9,-1,9,-1,-1},{-2,-2,33,-2,33,9,-2,9,-2,-2},
{0,0,4,0,4,4,0,4,0,0},{-1,-1,25,-1,25,9,-1,9,-1,-1},{-1,-1,34,-1,34,9,-1,9,-1,-1},
{-1,-1,149,-1,149,9,-1,9,-1,-1}};
struct Border Gad6Bord={0,0,3,0,JAM2,5,(SHORT *)GadPairs[0],NULL};
struct Border Gad4Bord={0,0,3,0,JAM2,5,(SHORT *)GadPairs[1],NULL};
struct Border Gad4Bordb={0,0,3,0,JAM2,5,(SHORT *)GadPairs[4],NULL};
struct Border MiniBord={0,0,3,0,JAM2,5,(SHORT *)GadPairs[2],NULL};
struct Border Gad3Bord={0,0,3,0,JAM2,5,(SHORT *)GadPairs[3],NULL};
struct Border Gad13Bord={0,0,3,0,JAM2,5,(SHORT *)GadPairs[5],NULL};
struct IntuiText GadText[8]=
{{1,0,JAM1,1,1,NULL,(UBYTE *)"Regrow",NULL},
 {1,0,JAM1,5,1,NULL,(UBYTE *)"Go On",NULL},
 {1,0,JAM1,1,1,NULL,(UBYTE *)"Cancel",NULL},
 {11,0,JAM1,1,1,NULL,(UBYTE *)"Die",NULL},
 {11,0,JAM1,1,1,NULL,(UBYTE *)"Edge",NULL},
 {1,0,JAM1,1,1,NULL,(UBYTE *)"Make",NULL},
 {1,0,JAM1,1,1,NULL,(UBYTE *)"Make",NULL},
 {1,0,JAM1,1,1,NULL,(UBYTE *)"   Change Colors",NULL}};
struct StringInfo StrInfo[13]=
{{(UBYTE *)&XSBuff[0],(UBYTE *)&UndoBuff[0],0,4,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL},
 {(UBYTE *)&YSBuff[0],(UBYTE *)&UndoBuff[0],0,4,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL},
 {(UBYTE *)&A1XMinBuff[0],(UBYTE *)&UndoBuff[0],0,4,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL},
 {(UBYTE *)&A1YMinBuff[0],(UBYTE *)&UndoBuff[0],0,4,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL},
 {(UBYTE *)&A1XMaxBuff[0],(UBYTE *)&UndoBuff[0],0,4,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL},
 {(UBYTE *)&A1YMaxBuff[0],(UBYTE *)&UndoBuff[0],0,4,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL},
 {(UBYTE *)&A2XMinBuff[0],(UBYTE *)&UndoBuff[0],0,4,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL},
 {(UBYTE *)&A2YMinBuff[0],(UBYTE *)&UndoBuff[0],0,4,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL},
 {(UBYTE *)&A2XMaxBuff[0],(UBYTE *)&UndoBuff[0],0,4,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL},
 {(UBYTE *)&A2YMaxBuff[0],(UBYTE *)&UndoBuff[0],0,4,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL},
 {(UBYTE *)&MIBuff[0],(UBYTE *)&UndoBuff[0],0,4,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL},
 {(UBYTE *)&MargBuff[0],(UBYTE *)&UndoBuff[0],0,4,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL},
 {(UBYTE *)&ColBuff[0],(UBYTE *)&UndoBuff[0],0,4,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}};
struct Gadget DMReqGadget[37] =
{{NULL,5,152,49,9,GADGHCOMP,RELVERIFY|GADGIMMEDIATE|ENDGADGET|TOGGLESELECT,
BOOLGADGET,(APTR)&Gad6Bord,NULL,&GadText[0],0,0,0,0},
{&DMReqGadget[0],105,152,49,9,GADGHCOMP,RELVERIFY|GADGIMMEDIATE|ENDGADGET|TOGGLESELECT
,BOOLGADGET,(APTR)&Gad6Bord,NULL,&GadText[2],0,0,1,0},
{&DMReqGadget[1],68,21,25,9,GADGHCOMP|SELECTED,RELVERIFY|GADGIMMEDIATE|TOGGLESELECT
,BOOLGADGET,(APTR)&Gad3Bord,NULL,&GadText[3],0,0,2,0},
{&DMReqGadget[2],50,2,5,5,GADGHCOMP,RELVERIFY|GADGIMMEDIATE|
TOGGLESELECT,BOOLGADGET,(APTR)&MiniBord,NULL,NULL,0,0,3,0},
{&DMReqGadget[3],55,2,5,5,GADGHCOMP,RELVERIFY|GADGIMMEDIATE|
TOGGLESELECT,BOOLGADGET,(APTR)&MiniBord,NULL,NULL,0,0,4,0},
{&DMReqGadget[4],60,2,5,5,GADGHCOMP,RELVERIFY|GADGIMMEDIATE|
TOGGLESELECT,BOOLGADGET,(APTR)&MiniBord,NULL,NULL,0,0,5,0},
{&DMReqGadget[5],50,7,5,5,GADGHCOMP,RELVERIFY|GADGIMMEDIATE|
TOGGLESELECT,BOOLGADGET,(APTR)&MiniBord,NULL,NULL,0,0,6,0},
{&DMReqGadget[6],60,7,5,5,GADGHCOMP,RELVERIFY|GADGIMMEDIATE|
TOGGLESELECT,BOOLGADGET,(APTR)&MiniBord,NULL,NULL,0,0,7,0},
{&DMReqGadget[7],50,12,5,5,GADGHCOMP|SELECTED,RELVERIFY|GADGIMMEDIATE|
TOGGLESELECT,BOOLGADGET,(APTR)&MiniBord,NULL,NULL,0,0,8,0},
{&DMReqGadget[8],55,12,5,5,GADGHCOMP|SELECTED,RELVERIFY|GADGIMMEDIATE|
TOGGLESELECT,BOOLGADGET,(APTR)&MiniBord,NULL,NULL,0,0,9,0},
{&DMReqGadget[9],60,12,5,5,GADGHCOMP|SELECTED,RELVERIFY|GADGIMMEDIATE|
TOGGLESELECT,BOOLGADGET,(APTR)&MiniBord,NULL,NULL,0,0,10,0},
{&DMReqGadget[10],115,2,5,5,GADGHCOMP,RELVERIFY|GADGIMMEDIATE|
TOGGLESELECT,BOOLGADGET,(APTR)&MiniBord,NULL,NULL,0,0,11,0},
{&DMReqGadget[11],120,2,5,5,GADGHCOMP,RELVERIFY|GADGIMMEDIATE|
TOGGLESELECT,BOOLGADGET,(APTR)&MiniBord,NULL,NULL,0,0,12,0},
{&DMReqGadget[12],125,2,5,5,GADGHCOMP,RELVERIFY|GADGIMMEDIATE|
TOGGLESELECT,BOOLGADGET,(APTR)&MiniBord,NULL,NULL,0,0,13,0},
{&DMReqGadget[13],115,7,5,5,GADGHCOMP,RELVERIFY|GADGIMMEDIATE|
TOGGLESELECT,BOOLGADGET,(APTR)&MiniBord,NULL,NULL,0,0,14,0},
{&DMReqGadget[14],125,7,5,5,GADGHCOMP,RELVERIFY|GADGIMMEDIATE|
TOGGLESELECT,BOOLGADGET,(APTR)&MiniBord,NULL,NULL,0,0,15,0},
{&DMReqGadget[15],115,12,5,5,GADGHCOMP|SELECTED,RELVERIFY|GADGIMMEDIATE|
TOGGLESELECT,BOOLGADGET,(APTR)&MiniBord,NULL,NULL,0,0,16,0},
{&DMReqGadget[16],120,12,5,5,GADGHCOMP|SELECTED,RELVERIFY|GADGIMMEDIATE|
TOGGLESELECT,BOOLGADGET,(APTR)&MiniBord,NULL,NULL,0,0,17,0},
{&DMReqGadget[17],125,12,5,5,GADGHCOMP|SELECTED,RELVERIFY|GADGIMMEDIATE|
TOGGLESELECT,BOOLGADGET,(APTR)&MiniBord,NULL,NULL,0,0,18,0},
{&DMReqGadget[18],45,43,32,10,GADGHCOMP,GADGIMMEDIATE,STRGADGET,(APTR)&Gad4Bord,
0,0,0,(APTR)&StrInfo[0],19,0},
{&DMReqGadget[19],121,43,32,10,GADGHCOMP,GADGIMMEDIATE,STRGADGET,(APTR)&Gad4Bord,
0,0,0,(APTR)&StrInfo[1],20,0},
{&DMReqGadget[20],7,76,32,10,GADGHCOMP,GADGIMMEDIATE,STRGADGET,(APTR)&Gad4Bord,
0,0,0,(APTR)&StrInfo[2],21,0},
{&DMReqGadget[21],45,76,32,10,GADGHCOMP,GADGIMMEDIATE,STRGADGET,(APTR)&Gad4Bord,
0,0,0,(APTR)&StrInfo[3],22,0},
{&DMReqGadget[22],83,76,32,10,GADGHCOMP,GADGIMMEDIATE,STRGADGET,(APTR)&Gad4Bord,
0,0,0,(APTR)&StrInfo[4],23,0},
{&DMReqGadget[23],121,76,32,10,GADGHCOMP,GADGIMMEDIATE,STRGADGET,(APTR)&Gad4Bord,
0,0,0,(APTR)&StrInfo[5],24,0},
{&DMReqGadget[24],7,98,32,10,GADGHCOMP,GADGIMMEDIATE,STRGADGET,(APTR)&Gad4Bord,
0,0,0,(APTR)&StrInfo[6],25,0},
{&DMReqGadget[25],45,98,32,10,GADGHCOMP,GADGIMMEDIATE,STRGADGET,(APTR)&Gad4Bord,
0,0,0,(APTR)&StrInfo[7],26,0},
{&DMReqGadget[26],83,98,32,10,GADGHCOMP,GADGIMMEDIATE,STRGADGET,(APTR)&Gad4Bord,
0,0,0,(APTR)&StrInfo[8],27,0},
{&DMReqGadget[27],121,98,32,10,GADGHCOMP,GADGIMMEDIATE,STRGADGET,(APTR)&Gad4Bord,
0,0,0,(APTR)&StrInfo[9],28,0},
{&DMReqGadget[28],83,109,32,10,GADGHCOMP,GADGIMMEDIATE,STRGADGET,(APTR)&Gad4Bord,
0,0,0,(APTR)&StrInfo[10],29,0},
{&DMReqGadget[29],83,120,32,10,GADGHCOMP,GADGIMMEDIATE,STRGADGET,(APTR)&Gad4Bord,
0,0,0,(APTR)&StrInfo[11],30,0},
{&DMReqGadget[30],82,130,34,9,GADGHCOMP|SELECTED,RELVERIFY|GADGIMMEDIATE|
TOGGLESELECT,BOOLGADGET,(APTR)&Gad4Bordb,NULL,&GadText[4],0,0,31,0},
{&DMReqGadget[31],55,152,49,9,GADGHCOMP,RELVERIFY|GADGIMMEDIATE|ENDGADGET|TOGGLESELECT
,BOOLGADGET,(APTR)&Gad6Bord,NULL,&GadText[1],0,0,32,0},
{&DMReqGadget[32],120,65,34,9,GADGHCOMP,RELVERIFY|GADGIMMEDIATE|ENDGADGET
,BOOLGADGET,(APTR)&Gad4Bordb,NULL,&GadText[5],0,0,33,0},
{&DMReqGadget[33],120,87,34,9,GADGHCOMP,RELVERIFY|GADGIMMEDIATE|ENDGADGET
,BOOLGADGET,(APTR)&Gad4Bordb,NULL,&GadText[6],0,0,34,0},
{&DMReqGadget[34],121,54,32,10,GADGHCOMP,GADGIMMEDIATE,STRGADGET,(APTR)&Gad4Bord,
0,0,0,(APTR)&StrInfo[12],35,0},
{&DMReqGadget[35],5,140,149,9,GADGHCOMP,RELVERIFY|GADGIMMEDIATE,BOOLGADGET,(APTR)&Gad13Bord,
0,&GadText[7],0,NULL,36,0},
};

struct Requester DMReq;
SHORT ReqBorderPairs[10]={0,0,158,0,158,165,0,165,0,0};
struct Border DMReqBorder={0,0,1,0,JAM2,5,(SHORT *)&ReqBorderPairs[0],NULL};
struct IntuiText DMReqText[12]=
{{1,0,JAM1,4,3,NULL,(UBYTE *)"Move:",NULL},
 {1,0,JAM1,70,3,NULL,(UBYTE *)"Test:",&DMReqText[0]},
 {1,0,JAM1,4,21,NULL,(UBYTE *)"Border:",&DMReqText[1]},
 {1,0,JAM1,4,32,NULL,(UBYTE *)"Size:",&DMReqText[2]},
 {1,0,JAM1,4,43,NULL,(UBYTE *)"X:",&DMReqText[3]},
 {1,0,JAM1,84,43,NULL,(UBYTE *)"Y:",&DMReqText[4]},
 {1,0,JAM1,4,65,NULL,(UBYTE *)"StartArea 1:",&DMReqText[5]},
 {1,0,JAM1,4,87,NULL,(UBYTE *)"StartArea 2:",&DMReqText[6]},
 {1,0,JAM1,4,109,NULL,(UBYTE *)"MaxIt:",&DMReqText[7]},
 {1,0,JAM1,4,120,NULL,(UBYTE *)"Margin:",&DMReqText[8]},
 {1,0,JAM1,4,131,NULL,(UBYTE *)"Enter on:",&DMReqText[9]},
 {1,0,JAM1,4,54,NULL,(UBYTE *)"Color change:",&DMReqText[10]}};

MySetDMRequester()
{
	InitRequester(&DMReq);
	DMReq.LeftEdge = 50;
	DMReq.TopEdge = 30;
	DMReq.Width = 159;
	DMReq.Height = 166;
	DMReq.RelLeft = -80;
	DMReq.RelTop = -77;
	DMReq.ReqGadget = &DMReqGadget[36];
	DMReq.ReqText = &DMReqText[11];
	DMReq.BackFill = 0;
	DMReq.ReqBorder = &DMReqBorder;
	DMReq.Flags |= POINTREL;
	SetDMRequest(w,&DMReq);
}

DrawBox(rp,startx,starty,endx,endy)
struct RastPort *rp;
long startx,starty,endx,endy;
{
	if ((startx!=endx)&&(starty!=endy))
	{
		Move(rp,startx,starty);
		Draw(rp,endx,starty);
		Draw(rp,endx,endy);
		Draw(rp,startx,endy);
		Draw(rp,startx,starty+1);
	}
}

GetSquare(fromx,fromy,nr)
long fromx,fromy;
int nr;
{
	struct IntuiMessage *msg;
	long initx,inity,endx,endy,currx,curry,partx,party,t;
	int invx=0,invy=0,i;
	struct RastPort *rp;

	initx=fromx;inity=fromy;
	rp=w->RPort;
	endx=initx;endy=inity;
	WaitPort(w->UserPort);
	msg=(struct IntuiMessage *)GetMsg(w->UserPort);
	SetDrMd(rp,COMPLEMENT);
	for (;msg->Class==MOUSEMOVE;)
	{
		currx=msg->MouseX; curry=msg->MouseY; ReplyMsg(msg);
		if ((invx==1)&&(currx>=initx)&&(currx<endx)) initx=currx;
		if ((invy==1)&&(curry>=inity)&&(curry<endy)) inity=curry;
		if ((invx==1)&&(currx>=initx)&&(currx>=endx)) { invx=0; initx=endx;endx=currx;}
		if ((invy==1)&&(curry>=inity)&&(curry>=endy)) { invy=0; inity=endy;endy=curry;}
		if ((currx>=initx)&&(invx==0)) endx=currx;
		if ((curry>=inity)&&(invy==0)) endy=curry;
		if ((currx<initx)&&(invx==0)) { invx=1; endx=initx; initx=currx;}
		if ((curry<inity)&&(invy==0)) { invy=1; endy=inity; inity=curry;}
		if (currx<initx) initx=currx;
		if (curry<inity) inity=curry;
		DrawBox(rp,initx,inity,endx,endy);
		WaitPort(w->UserPort);
		msg=(struct IntuiMessage *)GetMsg(w->UserPort);
		DrawBox(rp,initx,inity,endx,endy);
	}
	if (nr==1)
	{
		sprintf(&A1XMinBuff[0],"%ld",initx);
		sprintf(&A1XMaxBuff[0],"%ld",endx);
		sprintf(&A1YMinBuff[0],"%ld",inity);
		sprintf(&A1YMaxBuff[0],"%ld",endy);
	}
	else
	{
		sprintf(&A2XMinBuff[0],"%ld",initx);
		sprintf(&A2XMaxBuff[0],"%ld",endx);
		sprintf(&A2YMinBuff[0],"%ld",inity);
		sprintf(&A2YMaxBuff[0],"%ld",endy);
	}
	SetDrMd(w->RPort,JAM1);
}

int ChangePara()
{
	struct IntuiMessage *msg;
	struct Gadget *hit;
	int i=2,j=0,tmp;
	
	for (;w->Flags&INREQUEST;WaitPort(w->UserPort))
	{
		msg=GetMsg(w->UserPort);
		if (msg->Class==GADGETDOWN)
		{
			hit = (struct Gadget *)msg->IAddress;
			if ((hit->GadgetID > 32)&&(hit->GadgetID<35))
			{
				do {} while (ClearDMRequest(w)==FALSE);
				do
				{
					ReplyMsg(msg);
					WaitPort(w->UserPort);
					msg=GetMsg(w->UserPort);
				}
				while (msg->Class!=GADGETDOWN);
				GetSquare((long)msg->MouseX,(long)msg->MouseY,hit->GadgetID-32);
				hit->Flags&=!SELECTED;
				SetDMRequest(w,&DMReq);
				Request(&DMReq,w);
			}
			if (hit->GadgetID == 36) palette_request(w,10L,10L,"Change Colors",NULL,Planes);
			ReplyMsg(msg);
		}
	}
	if (!(DMReqGadget[1].Flags&0x0080))
	{
		if (DMReqGadget[32].Flags&0x0080) {j=2;DMReqGadget[32].Flags&=0xFF7F;}
		else {j=1; DMReqGadget[0].Flags&=0xFF7F;}
		if (DMReqGadget[2].Flags&SELECTED) Die=1; else Die=0;
		if (DMReqGadget[3].Flags&SELECTED) MoveBits|=0x01; else MoveBits&=0xFE;
		if (DMReqGadget[4].Flags&SELECTED) MoveBits|=0x02; else MoveBits&=0xFD;
		if (DMReqGadget[5].Flags&SELECTED) MoveBits|=0x04; else MoveBits&=0xFB;
		if (DMReqGadget[6].Flags&SELECTED) MoveBits|=0x08; else MoveBits&=0xF7;
		if (DMReqGadget[7].Flags&SELECTED) MoveBits|=0x10; else MoveBits&=0xEF;
		if (DMReqGadget[8].Flags&SELECTED) MoveBits|=0x20; else MoveBits&=0xDF;
		if (DMReqGadget[9].Flags&SELECTED) MoveBits|=0x40; else MoveBits&=0xBF;
		if (DMReqGadget[10].Flags&SELECTED) MoveBits|=0x80; else MoveBits&=0x7F;
		if (DMReqGadget[11].Flags&SELECTED) TestBits|=0x01; else TestBits&=0xFE;
		if (DMReqGadget[12].Flags&SELECTED) TestBits|=0x02; else TestBits&=0xFD;
		if (DMReqGadget[13].Flags&SELECTED) TestBits|=0x04; else TestBits&=0xFB;
		if (DMReqGadget[14].Flags&SELECTED) TestBits|=0x08; else TestBits&=0xF7;
		if (DMReqGadget[15].Flags&SELECTED) TestBits|=0x10; else TestBits&=0xEF;
		if (DMReqGadget[16].Flags&SELECTED) TestBits|=0x20; else TestBits&=0xDF;
		if (DMReqGadget[17].Flags&SELECTED) TestBits|=0x40; else TestBits&=0xBF;
		if (DMReqGadget[18].Flags&SELECTED) TestBits|=0x80; else TestBits&=0x7F;
		if (j==1) XSize=atoi(&XSBuff[0]);
		if (j==1) { YSize=atoi(&YSBuff[0]); ChangeSize(); ColCount=0;}
		A1MinX=atoi(&A1XMinBuff[0]);
		A1MinY=atoi(&A1YMinBuff[0]);
		A1MaxX=atoi(&A1XMaxBuff[0]);
		A1MaxY=atoi(&A1YMaxBuff[0]);
		A2MinX=atoi(&A2XMinBuff[0]);
		A2MinY=atoi(&A2YMinBuff[0]);
		A2MaxX=atoi(&A2XMaxBuff[0]);
		A2MaxY=atoi(&A2YMaxBuff[0]);
		MaxIt=atoi(&MIBuff[0]);
		Margin=atoi(&MargBuff[0]);
		ColJump=atoi(&ColBuff[0]);
		if (ColJump<1) ColJump=-1;
		if (DMReqGadget[31].Flags&SELECTED) EnterOnEdge=1; else EnterOnEdge=0;
		if (A1MinX<2) A1MinX=2;
		if (A1MinY<2) A1MinY=2;
		if ((A2MinX<2)&&(A2MinX!=-1)) A2MinX=2;
		if (A2MinY<2) A2MinY=2;
		if (A1MaxX>XSize-3) A1MaxX=XSize-3;
		if (A1MaxY>YSize-3) A1MaxY=YSize-3;
		if (A2MaxX>XSize-3) A2MaxX=XSize-3;
		if (A2MaxY>YSize-3) A2MaxY=YSize-3;
		if (A1MinX>XSize-3) A1MinX=XSize-3;
		if (A1MinY>YSize-3) A1MinY=YSize-3;
		if (A2MinX>XSize-3) A2MinX=XSize-3;
		if (A2MinY>YSize-3) A2MinY=YSize-3;
		if (MaxIt<2) MaxIt=2;
		if (Margin>MaxIt) Margin=MaxIt;
		if (Margin<2) Margin=2;
		code++;
		/*printf("Current Blit Code is : %d\n",code);*/
	}
	else
	{
		DMReqGadget[1].Flags&=!SELECTED;
		for (msg=GetMsg(w->UserPort);msg!=NULL;ReplyMsg(msg),
				msg=GetMsg(w->UserPort));
		if (Die==1) DMReqGadget[2].Flags|=SELECTED; else DMReqGadget[2].Flags&=!SELECTED;
		if (MoveBits&1) DMReqGadget[3].Flags|=SELECTED; else DMReqGadget[3].Flags&=!SELECTED;
		if (MoveBits&2) DMReqGadget[4].Flags|=SELECTED; else DMReqGadget[4].Flags&=!SELECTED;
		if (MoveBits&4) DMReqGadget[5].Flags|=SELECTED; else DMReqGadget[5].Flags&=!SELECTED;
		if (MoveBits&8) DMReqGadget[6].Flags|=SELECTED; else DMReqGadget[6].Flags&=!SELECTED;
		if (MoveBits&16) DMReqGadget[7].Flags|=SELECTED; else DMReqGadget[7].Flags&=!SELECTED;
		if (MoveBits&32) DMReqGadget[8].Flags|=SELECTED; else DMReqGadget[8].Flags&=!SELECTED;
		if (MoveBits&64) DMReqGadget[9].Flags|=SELECTED; else DMReqGadget[9].Flags&=!SELECTED;
		if (MoveBits&128) DMReqGadget[10].Flags|=SELECTED; else DMReqGadget[10].Flags&=!SELECTED;
		if (TestBits&1) DMReqGadget[11].Flags|=SELECTED; else DMReqGadget[11].Flags&=!SELECTED;
		if (TestBits&2) DMReqGadget[12].Flags|=SELECTED; else DMReqGadget[12].Flags&=!SELECTED;
		if (TestBits&4) DMReqGadget[13].Flags|=SELECTED; else DMReqGadget[13].Flags&=!SELECTED;
		if (TestBits&8) DMReqGadget[14].Flags|=SELECTED; else DMReqGadget[14].Flags&=!SELECTED;
		if (TestBits&16) DMReqGadget[15].Flags|=SELECTED; else DMReqGadget[15].Flags&=!SELECTED;
		if (TestBits&32) DMReqGadget[16].Flags|=SELECTED; else DMReqGadget[16].Flags&=!SELECTED;
		if (TestBits&64) DMReqGadget[17].Flags|=SELECTED; else DMReqGadget[17].Flags&=!SELECTED;
		if (TestBits&128) DMReqGadget[18].Flags|=SELECTED; else DMReqGadget[18].Flags&=!SELECTED;
		if (EnterOnEdge==1) DMReqGadget[31].Flags|=SELECTED; else DMReqGadget[31].Flags&=!SELECTED;
		j=0;
	}
	sprintf(&A1XMinBuff[0],"%d",A1MinX);
	sprintf(&A2XMinBuff[0],"%d",A2MinX);
	sprintf(&A1YMinBuff[0],"%d",A1MinY);
	sprintf(&A2YMinBuff[0],"%d",A2MinY);
	sprintf(&A1XMaxBuff[0],"%d",A1MaxX);
	sprintf(&A2XMaxBuff[0],"%d",A2MaxX);
	sprintf(&A1YMaxBuff[0],"%d",A1MaxY);
	sprintf(&A2YMaxBuff[0],"%d",A2MaxY);
	sprintf(&MIBuff[0],"%d",MaxIt);
	sprintf(&MargBuff[0],"%d",Margin);
	sprintf(&XSBuff[0],"%d",XSize);
	sprintf(&YSBuff[0],"%d",YSize);
	sprintf(&ColBuff[0],"%ld",ColJump);
	return(j);
}

ChangeSize()
{
	if (XSize<10) XSize=10;
	if (YSize<10) YSize=10;
	if (XSize>640) XSize=640;
	if ((Pal)&&(YSize>511)) YSize=511;
	if ((!Pal)&&(YSize>399)) YSize=399;
	if ((XSize<321)&&(HiRes==1))
	{
		for (;!ClearDMRequest(w););
		if (w) CloseWindow(w);
		if (s) CloseScreen(s);
		ns.ViewModes&=(!HIRES);
		ns.Width=320;
		if (!(s=(struct Screen *)OpenScreen(&ns)))
			abort(104);
		LoadRGB4(&s->ViewPort,&ColorMap[0],(long)1<<Planes);
		nw.Screen=s;
		nw.Width=320;
		BigGad.Width=nw.Width;
		if (!(w = (struct Window *) OpenWindow(&nw))) 
			abort(105);
		MySetDMRequester();
		HiRes=0;
	}
	if ((XSize>320)&&(XSize<641)&&(HiRes==0))
	{
		for (;!ClearDMRequest(w););
		if (w) CloseWindow(w);
		if (s) CloseScreen(s);
		ns.ViewModes|=HIRES;
		ns.Width=640;
		if (Planes==5) ns.Depth=4;
		if (!(s=(struct Screen *)OpenScreen(&ns)))
			abort(104);
		LoadRGB4(&s->ViewPort,&ColorMap[0],(long)1<<Planes);
		nw.Screen=s;
		nw.Width=640;
		BigGad.Width=nw.Width;
		if (!(w = (struct Window *) OpenWindow(&nw))) 
			abort(105);
		MySetDMRequester();
		HiRes=1;
	}
	if (Pal)
	{
		if ((YSize<256)&&(Lace==1))
		{
			for (;!ClearDMRequest(w););
			if (w) CloseWindow(w);
			if (s) CloseScreen(s);
			ns.ViewModes&=(!LACE);
			ns.Height=256;
			if (!(s=(struct Screen *)OpenScreen(&ns)))
				abort(104);
			LoadRGB4(&s->ViewPort,&ColorMap[0],(long)1<<Planes);
			nw.Screen=s;
			nw.Height=255;
			BigGad.Height=nw.Height;
			if (!(w = (struct Window *) OpenWindow(&nw))) 
				abort(105);
			MySetDMRequester();
			Lace=0;
		}
		if ((YSize>255)&&(Lace==0))
		{
			for (;!ClearDMRequest(w););
			if (w) CloseWindow(w);
			if (s) CloseScreen(s);
			ns.ViewModes|=LACE;
			ns.Height=512;
			if (!(s=(struct Screen *)OpenScreen(&ns)))
				abort(104);
			LoadRGB4(&s->ViewPort,&ColorMap[0],(long)1<<Planes);
			nw.Screen=s;
			nw.Height=511;
			BigGad.Height=nw.Height;
			if (!(w = (struct Window *) OpenWindow(&nw))) 
				abort(105);
			MySetDMRequester();
			Lace=1;
		}
	}
	else
	{
		if ((YSize<200)&&(Lace==1))
		{
			for (;!ClearDMRequest(w););
			if (w) CloseWindow(w);
			if (s) CloseScreen(s);
			ns.ViewModes&=(!LACE);
			ns.Height=200;
			if (!(s=(struct Screen *)OpenScreen(&ns)))
				abort(104);
			LoadRGB4(&s->ViewPort,&ColorMap[0],(long)1<<Planes);
			nw.Screen=s;
			nw.Height=199;
			BigGad.Height=nw.Height;
			if (!(w = (struct Window *) OpenWindow(&nw))) 
				abort(105);
			MySetDMRequester();
			Lace=0;
		}
		if ((YSize>199)&&(Lace==0))
		{
			for (;!ClearDMRequest(w););
			if (w) CloseWindow(w);
			if (s) CloseScreen(s);
			ns.ViewModes&=LACE;
			ns.Height=400;
			if (!(s=(struct Screen *)OpenScreen(&ns)))
				abort(104);
			LoadRGB4(&s->ViewPort,&ColorMap[0],(long)1<<Planes);
			nw.Screen=s;
			nw.Height=399;
			BigGad.Height=nw.Height;
			if (!(w = (struct Window *) OpenWindow(&nw))) 
				abort(105);
			MySetDMRequester();
			Lace=1;
		}
	}
}

OpenAll()
{
	if (!(GfxBase = (struct GfxBase *) OpenLibrary("graphics.library",0L)))
		abort(101);
	if (GfxBase->NormalDisplayRows==200) Pal=0;

	if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 0L)))
		abort(102);

	if(!(IFFBase = OpenLibrary(IFFNAME,IFFVERSION)))
		abort(103);
	ns.Depth=Planes;
	if (!Pal)
		ns.Height=200;
	if (!(s=(struct Screen *)OpenScreen(&ns)))
		abort(104);
	
	LoadRGB4(&s->ViewPort,&ColorMap[0],(long)1<<Planes);
	nw.Screen=s;
	if (!Pal)
	{
		nw.Height=BigGad.Height=YSize=199;
		A1MaxY=A1MinY=197;
		strcpy(A1YMinBuff,"197");
		strcpy(A1YMaxBuff,"197");
		strcpy(YSBuff,"199");
	}
	if (!(w = (struct Window *) OpenWindow(&nw))) 
		abort(105);
	MySetDMRequester();
}

abort(exitcode)
{
	for (;!ClearDMRequest(w););
	if (w) CloseWindow(w);
	if (s) CloseScreen(s);
	if (IFFBase) CloseLibrary(IFFBase);
	if (GfxBase) CloseLibrary(GfxBase);
		OpenWorkBench();
	if (IntuitionBase) CloseLibrary(IntuitionBase);
	exit(exitcode);
}

DisplayUsage()
{
	puts("[33mIceFrac[31m - A Diffusion Limited Aggregation simulator.");
	puts("[1mUsage[0m: IceFrac [-P#planes]");
	puts("1989 By Lars R. Clausen");
	puts("Critics, comments & contributions are welcome.");
	exit(0);
}
main(argc,argv)
int argc;
char *argv[];
{
	struct IntuiMessage *msg;
	register int t,maxx,minx,maxy,miny;
	long sec,mic,i,j=2;
	int iffcount=0,alldone=0;
	register long x,y,dir;

	if (argc==2)
	{
		if (toupper(argv[1][1])=='P') Planes=atoi(&argv[1][2]);
		else DisplayUsage();
	}
	ColCount=ColJump;
	OpenAll();
	CurrentTime(&sec,&mic);
	sec=mic; mic>>8; mic+=sec;
	srand((int)mic);
	if (!A2Off)
	{
		if (A1MinX>A2MinX) minx=A2MinX-Margin;
		else minx=A1MinX-Margin;
		if (A1MaxX>A2MaxX) maxx=A1MaxX+Margin;
		else maxx=A2MaxX+Margin;
		if (A1MinY>A2MinY) miny=A2MinY-Margin;
		else miny=A1MinY-Margin;
		if (A1MaxY>A2MaxY) maxy=A1MaxY+Margin;
		else maxy=A2MaxY+Margin;
	}
	else
	{
		minx=A1MinX-Margin;
		maxx=A1MaxX+Margin;
		miny=A1MinY-Margin;
		maxy=A1MaxY+Margin;
	}
	if (minx<1) minx=1;
	if (maxx>XSize-2) maxx=XSize-2;
	if (miny<1) miny=1;
	if (maxy>YSize-2) maxy=YSize-2;
	SetAPen(w->RPort,1L);
	RectFill(w->RPort,(long)A1MinX,(long)A1MinY,(long)A1MaxX,(long)A1MaxY);
	if (!A2Off)RectFill(w->RPort,(long)A2MinX,(long)A2MinY,(long)A2MaxX,(long)A2MaxY);
	for (;;)
	{
		i=0;
		do
		{
			x=rand()%(maxx-minx)+minx;
			y=rand()%(maxy-miny)+miny;
			if (EnterOnEdge==1)
			{
				if (rand()%(maxx-minx+maxy-miny)<maxy-miny)
					if (rand()%2==1) x=minx;
					else x=maxx;
				else
					if (rand()%2==1) y=miny;
					else y=maxy;
			}
			alldone=0;
			if (i++>=100)
			{
				alldone=1;
				for (x=minx,y=miny;(x<=maxx)&&(alldone==1);x++)
					if (ReadPixel(w->RPort,x,(long)miny)==0) alldone=0;
				x--;
				if (alldone==1)
				{
					for (x=minx,y=miny;(y<=maxy)&&(alldone==1);y++)
						if (ReadPixel(w->RPort,(long)minx,y)==0) alldone=0;
					y--;
				}
				if (alldone==1)
				{
					for (x=maxx,y=miny;(y<=maxy)&&(alldone==1);y++)
						if (ReadPixel(w->RPort,(long)maxx,y)==0) alldone=0;
					y--;
				}
				if (alldone==1)
				{
					for (x=minx,y=maxy;(x<=maxx)&&(alldone==1);x++)
						if (ReadPixel(w->RPort,x,(long)maxy)==0) alldone=0;
					x--;
				}
				printf("Alldone=%d, x=%ld,y=%ld\n",alldone,x,y);
			}
		}
		while (((x<1)||(x>XSize-2)||(y<1)||(y>YSize-2)||(ReadPixel(w->RPort,x,y)!=0))&&(alldone==0));
		for (t=0;t<MaxIt;t++)
		{
#ifdef USEBLIT
/* Doesn't work yet */
			printf("Blitting at %ld,%ld - code = %ld\n",x-1,y-1,code);
			BltBitMapRastPort(&s->BitMap,x-1,y-1,&w->RPort,x-1,y,3L,3L,code);
			printf("Done\n");
			if (!(*BZero&(1<<13))) t=MaxIt+10;
#else
			if ((TestBits&0x01)&&(ReadPixel(w->RPort,x-1,y-1))) t=MaxIt+10;
			if ((TestBits&0x02)&&(ReadPixel(w->RPort,x,y-1))) t=MaxIt+10;
			if ((TestBits&0x04)&&(ReadPixel(w->RPort,x+1,y-1))) t=MaxIt+10;
			if ((TestBits&0x08)&&(ReadPixel(w->RPort,x-1,y))) t=MaxIt+10;
			if ((TestBits&0x10)&&(ReadPixel(w->RPort,x+1,y))) t=MaxIt+10;
			if ((TestBits&0x20)&&(ReadPixel(w->RPort,x-1,y+1))) t=MaxIt+10;
			if ((TestBits&0x40)&&(ReadPixel(w->RPort,x,y+1))) t=MaxIt+10;
			if ((TestBits&0x80)&&(ReadPixel(w->RPort,x+1,y+1))) t=MaxIt+10;
#endif
			if (t==MaxIt+10)
			{
				if (x+Margin>maxx) maxx=x+Margin;
				if (x-Margin<minx) minx=x-Margin;
				if (y+Margin>maxy) maxy=y+Margin;
				if (y-Margin<miny) miny=y-Margin;
				if (maxx>XSize-2) maxx=XSize-2;
				if (maxy>YSize-2) maxy=YSize-2;
				if (miny<1) miny=1;
				if (minx<1) minx=1;
 				if (ColJump>-1) SetAPen(w->RPort,(long)ColCount++/ColJump);
				if (ColCount>ColJump*(1<<Planes)) ColCount=0;
 				if (ColCount/ColJump==0) ColCount+=ColJump;
				WritePixel(w->RPort,x,y);
			}
			else
			{
				dir=rand()%8;
				if ((dir==0)&&(MoveBits&0x08)) x--;
				if ((dir==1)&&(MoveBits&0x10)) x++;
				if ((dir==2)&&(MoveBits&0x02)) y--;
				if ((dir==3)&&(MoveBits&0x40)) y++;
				if ((dir==4)&&(MoveBits&0x20)) { y++; x--; }
				if ((dir==5)&&(MoveBits&0x80)) { y++; x++; }
				if ((dir==6)&&(MoveBits&0x01)) { y--; x--; }
				if ((dir==7)&&(MoveBits&0x04)) { y--; x++; }
				if (Die)
					if ((x<=1)||(y<=1)||(x>=XSize-2)||(y>=YSize-2))
					{
						t=MaxIt;
					}
			}
		}
		if (alldone) WaitPort(w->UserPort);
		alldone=0;
		if (w->Flags&INREQUEST)
			if ((j=ChangePara())!=0)
			{
				if (j==1)
				{
					SetAPen(w->RPort,1L);
					Move(w->RPort,0L,0L);
					ClearScreen(w->RPort);
					if (A2MinX==-1) A2Off=1; else A2Off=0;
					RectFill(w->RPort,(long)A1MinX,(long)A1MinY,(long)A1MaxX,(long)A1MaxY);
					if (!A2Off)
					{
						RectFill(w->RPort,(long)A2MinX,(long)A2MinY,(long)A2MaxX,(long)A2MaxY);
						if (A1MinX>A2MinX) minx=A2MinX-Margin;
						else minx=A1MinX-Margin;
						if (A1MaxX>A2MaxX) maxx=A1MaxX+Margin;
						else maxx=A2MaxX+Margin;
						if (A1MinY>A2MinY) miny=A2MinY-Margin;
						else miny=A1MinY-Margin;
						if (A1MaxY>A2MaxY) maxy=A1MaxY+Margin;
						else maxy=A2MaxY+Margin;
					}
					else
					{
						minx=A1MinX-Margin;
						maxx=A1MaxX+Margin;
						miny=A1MinY-Margin;
						maxy=A1MaxY+Margin;
					}
					if (minx<1) minx=1;
					if (maxx>XSize-2) maxx=XSize-2;
					if (miny<1) miny=1;
					if (maxy>YSize-2) maxy=YSize-2;
					}
				}
		if (msg=GetMsg(w->UserPort))/* User messages */
		{
			if (msg->Class==VANILLAKEY)
			{
				if (msg->Code==27) abort(0);
				if (msg->Code==32)
				{
					if (!SaveBitMap(ifffile,&s->BitMap,0L,1L))
						puts("Error in saving picture");
					ifffile[10]++;
					if (ifffile[10]==58)
					{
						ifffile[9]++;
						ifffile[10]=48;
						if (ifffile[9]==58)
						{
							ifffile[9]=48;
							ifffile[8]++;
						}
					}
				}
				ReplyMsg(msg);
			}
		}
	}
	abort(0);
}
