/* Mountain.c */
/* Scientific American December 1986 */
#include "exec/types.h"
#include "intuition/intuition.h"
#include "exec/memory.h"
#include "graphics/gfxmacros.h"

#define XMAX 630			/* Number of pixels x direction */
#define YMAX 185			/* Number of pixels y direction */
#define DELTAMAX 128			/* Max change in y */

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();
void CloseScreen(), CloseWindow(), CloseLibrary();
void SetAPen(), ReplyMsg(), Draw(), Move(); 
void WaitPort(), ClearScreen();
void SetWindowTitles(), SetRast();

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

struct lineinfo
{
	UWORD x1;			/* x coordinate of start of line */
	UWORD y1;			/* y coordinate of start of line */
	UWORD x2;			/* x coordinate of end of line */
	UWORD y2;			/* y coordinate of end of line */
};
struct lineinfo line[700];

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

struct NewScreen mntScreen = {
	0L, 0L,
	640L, 200L,
	1L,			/* One bit planes */
	0L, 1L,
	HIRES,
	CUSTOMSCREEN,
	&TextFont,
	(UBYTE *)"Mountain Screen",
	NULL
};


struct NewWindow mntWindow = {
	0L, 0L,
	640L, 200L,
	0L, 
	1L,
	CLOSEWINDOW | INTUITICKS,
	WINDOWCLOSE | WINDOWDEPTH | WINDOWSIZING
	 | WINDOWDRAG | ACTIVATE | GIMMEZEROZERO,
	NULL, NULL,
	(UBYTE *) "Mountain",
	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;
	case INTUITICKS:
		return(1);
		break;
	default:
		return(2);
		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(&mntScreen);
	if(s == NULL) return(0);

	mntWindow.Screen = s;		/* Tie window to screen */
	w = OpenWindow(&mntWindow);
	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);
}

main()
{
	short delmax, numlines, i, t, count, pdelay;
	UWORD newx, newy;
	int mtype;

	if(init() == 0) endit();	/* Open everything */

loop:	line[0].x1 =  0;
	line[0].y1 = YMAX;
	line[0].x2 = XMAX;
	line[0].y2 = YMAX;

	t = 1;
	delmax = DELTAMAX;
	count = 0;

	while(delmax > 0)
	{

		numlines = t;
		for(i=0; i<numlines; i++)
		{
			/* New line ends at end of an old line */
			line[t].x2 = line[i].x2;
			line[t].y2 = line[i].y2;

			newx = (line[i].x1 + line[i].x2)/2;
			newy = (line[i].y1 + line[i].y2)/2 - rand() % delmax;

			/* Old line ends at perturbed former midpoint */
			line[i].x2 = newx;
			line[i].y2 = newy;
			/* New line starts at same point */
			line[t].x1 = newx;
			line[t].y1 = newy;

			/* Draw lines */
			Move(rp, (long)line[i].x1, (long)line[i].y1);
			Draw(rp, (long)line[i].x2, (long)line[i].y2);

			Draw(rp, (long)line[t].x2, (long)line[t].y2);

			t++;		/* Next new line */
			
		}

		sprintf(&titlestr[0], 
			"Mount Mandelbrot   Count:%5d     Max DeltaY:%3d",
			 ++count, delmax); /* Write count */
		SetWindowTitles(w, titlestr, -1L);

		delmax = delmax/2;	/* Max y deviation for next iteration */

		if(delmax == 0)
			pdelay = 25;
		else pdelay = 5;
		/* Delay and check for close window */
		while(pdelay > 0) 
		{
			WaitPort(w->UserPort);	/* Wait for intuition */
			msg = GetMsg(w->UserPort);
			mtype = HandleEvent(msg->Class);
			ReplyMsg(msg);
			switch(mtype)
			{
			case 0:		/* CloseWindow */
				while((msg = GetMsg(w->UserPort))!=NULL)
				{
					ReplyMsg(msg);
				}
				endit();
				break;

			case 1:
				pdelay--;	/* decrement delay */
				break;

			default:
				break;
			}
		}
		SetRast(rp, 0L);	/* Clear Screen */	
	}
	goto loop;
}	
