/********************************* Chaos.c *********************************/
/* :ts=8 - for z editor */
/* Inspired by Public Broadcast System's broadcast of NOVA episode "Chaos".*/
/* Encouragement form Gene E. Toye who wrote C128 version in basic 1st.    */
/* Original Window & Screen definitions by PowerWindows 2.0 and modified.  */

/* This source code and executable are hereby placed in the public domain  */
/* with all the implications thereof, etc., etc. legal gobbledeegook.      */

#include <stdio.h>
#include <graphics/gfxbase.h>
#include <intuition/intuitionbase.h>

struct LPoint {
    long	 X,
		 Y;
    };

struct LPoint	 Corners[3] = {
    {0L, 0L}, {639L, 0L}, {319L, 389L}
    };

struct NewScreen NScreen = {
	0,0,	/* screen XY origin relative to View */
	640,400,	/* screen width and height */
	2,	/* screen depth (number of bitplanes) */
	0,1,	/* detail and block pens */
	HIRES+LACE,	/* display modes for this screen */
	CUSTOMSCREEN,	/* screen type */
	NULL,	/* pointer to default screen font */
	(UBYTE *)"Chaos Reigns!  <click left mouse button to exit, right to pause>",	/* screen title */
	NULL,	/* first in list of custom screen gadgets */
	NULL	/* pointer to custom BitMap structure */
    };
struct NewWindow NWindow = {
	0,10,	/* window XY origin relative to TopLeft of screen */
	640,390,	/* window width and height */
	0,1,	/* detail and block pens */
	MOUSEBUTTONS,	/* IDCMP flags */
	BORDERLESS+ACTIVATE+RMBTRAP+NOCAREREFRESH,	/* other window flags */
	NULL,	/* first gadget in gadget list */
	NULL,	/* custom CHECKMARK imagery */
	NULL,	/* window title */
	NULL,	/* custom screen pointer */
	NULL,	/* custom bitmap */
	640,390,	/* minimum width and height */
	640,390,	/* maximum width and height */
	CUSTOMSCREEN	/* destination screen type */
    };

struct GfxBase		*GfxBase;
struct IntuitionBase	*IntuitionBase;
struct Screen		*Screen;
struct Window		*Window;

main(argc, argv)
short	 argc;
char	*argv[];
{
    /* regs for speed! */
    register struct IntuiMessage*Message;
    register short		 NextCorner;
    register long		 X,
				 Y;

    extern void			 DisplayBeep(),
				 Move(),
				 ReplyMsg(),
				 Terminate(),
				 WritePixel();
    extern long			 Wait();
    extern double		 ran();
    extern struct GfxBase	*GfxBase;
    extern struct IntuitionBase	*IntuitionBase;
    extern struct IntuiMessage	*GetMsg(),
				*WaitPort();
    extern struct Library	*OpenLibrary();
    extern struct LPoint	 Corners[3];
    extern struct NewWindow	 NWindow;
    extern struct Screen	*OpenScreen(),
				*Screen;
    extern struct Window	*OpenWindow(),
				*Window;

    /* open things */
    if ((IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0L)) == NULL) Terminate();
    if ((GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0L)) == NULL) Terminate();
    if ((Screen = OpenScreen(&NScreen)) == NULL) Terminate();
    NWindow.Screen = Screen;
    if ((Window = OpenWindow(&NWindow)) == NULL) Terminate();

    /* set up things */
    SetAPen(Window->RPort, 1L);
    SetBPen(Window->RPort, 0L);
    SetDrMd(Window->RPort, JAM1);

    /* set starting point */
    X = (long)(ran()*639.9);
    Y = (long)(ran()*389.9);

    /* plot initial points */
    WritePixel(Window->RPort, Corners[0].X, Corners[0].Y);
    WritePixel(Window->RPort, Corners[1].X, Corners[1].Y);
    WritePixel(Window->RPort, Corners[2].X, Corners[2].Y);

    /* enter main loop */
    FOREVER {
	if ((Message = GetMsg(Window->UserPort))!=NULL) {
	    if ((Message->Class ==  MOUSEBUTTONS) && (Message->Code == SELECTDOWN)) {
		ReplyMsg(Message);
		Terminate();
		}
	    else if (Message->Class ==  MOUSEBUTTONS) {
		ReplyMsg(Message);
		Message = WaitPort(Window->UserPort);	 /* pause until UP */
		Message = GetMsg(Window->UserPort);
		ReplyMsg(Message);		  /* reply to message ASAP */
		}
	    else ReplyMsg(Message);
	    };
	WritePixel(Window->RPort, X, Y);
	NextCorner = (short)(ran()*2.9);
	X = (Corners[NextCorner].X-X)/2+X;
	Y = (Corners[NextCorner].Y-Y)/2+Y;
	} /* end FOREVER */
} /* end main */

void Terminate()
{
    extern void			 CloseLibrary(),
				 CloseScreen(),
				 CloseWindow(),
				 exit();
    extern struct GfxBase	*GfxBase;
    extern struct IntuitionBase	*IntuitionBase;
    extern struct Screen	*Screen;
    extern struct Window	*Window;

    /* close everything up before ending */
    if (Window) CloseWindow(Window);
    if (Screen) CloseScreen(Screen);
    if (GfxBase) CloseLibrary(GfxBase);
    if (IntuitionBase) CloseLibrary(IntuitionBase);
    exit(0);				       /* completely exit program! */
} /* end Terminate() */

/* EOF - Chaos.c */
