[comp.sys.amiga] Cute and Quick Math Toy: Hopalong

ranjit@eniac.seas.upenn.edu (Ranjit Bhatnagar) (08/30/88)

OK, here's a little program that can make very pretty pictures.
It's primitive, but it works.  I figure 90% of you missed this
when it appeared in Scientific American, and another 9% didn't
feel like programming it yourself - well, there you go.  I
recommend a magnification of 10 to start with.

If you want the binary (11K before UUENCODing), send mail.  If lots
of people ask, I'll post it.

You'll have to cut this manually, since I don't know how to SHAR
things.  There might be extraneous junk in the .h file, since I
use the same .h (compiled) for lots of different programs.  Compile
with Manx 3.4b or better, link with the math library before the c
library.  I've never tried this except with 32 bits, large model.

=== CUT HERE for hop.c ===
/*
	First Wave program		Ranjit Bhatnagar 
					ranjit@eniac.seas.upenn.edu

	All this code is public domain - as if anyone would want
	to steal it.  I would love to see improved versions -
	a nicer interface, a fixed-point implementation for speed.

30 Aug '88
	Shell of First Wave has been
	modified to be a quick Hopalong - as described in Dewdney's
	Mathematical Games column, "Scientific American" Sept 86 -
	and invented by Barry Martin.

	Basically, it's an iterated function:
		x = 0
		y = 0
		for i = 1 to num
			plot (x, y)
			xx = y - sign(x)*sqrt[abs(b*x-c)]
			yy = a - x
			x = xx
			y = yy

	where a, b, and c are constants entered by the user.  (Some suggested
	values: -1000, .1, -10; -200, .1, -80; .4, 1, 0; -3.14, .3, .3)

	A simpler function (not implemented here) is

		x = y - sin(x)
		y = a - x

	Martin recommends values of a within .07 of pi for this one.

	user must also specify the range of values that will be visible on
	the screen. [INSTEAD I put in "magnification"]

	Things to do: 
		allow specification of visible range.  
		Clever colors.  
		Fixed-point for speed.

	the latest: changed to interlace, doubled pixel height, reduced
	frequency of checks for close-box...
*/



/* create a nice screen */	/* Thanks Rob Peck and "Programmer's Guide" */
struct TextAttr waveScrFont = {	/* for basic methods in Intuition */
	"topaz.font", 8, 0, 0
};

#define WID 640
#define HEI 400
struct NewScreen waveScr = {
	0, 0,			/* left and top edges */
	WID, HEI,		/* width and height   */
	4,				/* bitplanes	      */
	1, 0, 			/* detail and block pens */
	LACE|HIRES,			/* screen view type */
	CUSTOMSCREEN,	/* type */
	&waveScrFont,	/* font */
	"Hopalong",	/* title */
	NULL,			/* user gadgets */
	NULL			/* custom bitmap */
};


/* some pretty colors for it */
UWORD waveCols[] = {
	0x0000, 0x0e30, 0x0fff, 0x0b40,
	0x0b04, 0x05d0, 0x0ed0, 0x07df,
	0x069f, 0x0c0e, 0x0f2e, 0x0feb,
	0x0c96, 0x0bbb, 0x07df, 0x0bf0
};


/* and a nice window */
struct NewWindow waveWin = {
	0, 15, 			/* left and top edges */
	WID-1, HEI-16,	/* size */
	2, 3,			/* detail and block pens */
	CLOSEWINDOW,	/* flags */
	SIMPLE_REFRESH | WINDOWCLOSE | GIMMEZEROZERO,
	NULL, NULL,
	"Hopalong",
	NULL,			/* the screen */
	NULL,			/* the bitmap */
	10, 10, -1, -1, 
	CUSTOMSCREEN
};


/* the precomputed tables */
/* uncomment these if you decide to put fixedpoint into the program... */
/* extern WORD sinetab[];*/		/* 257 sines from 0 to 2pi, all 16 bits are frac */
/* extern WORD sqrttab[];*/		/* 257 sqrts from 0 to 256, low 12 bits are frac */

/* extern double ran(); */

/* globals */

struct Screen *scr = 0;
struct Window *win = 0;
struct RastPort *rp = 0;
struct ViewPort *vp = 0;

int GfxBase = 0;
int IntuitionBase = 0;



/* Open libraries & such */
OpenThings()
{
	GfxBase = OpenLibrary("graphics.library",0);
	if (GfxBase == 0) Die("Couldn't open graphics.library");
	diag("opened grafix");

	IntuitionBase = OpenLibrary("intuition.library",0);
	if (IntuitionBase == 0) Die("Couldn't open intuition.library");
	diag("opened intuition");

	scr = OpenScreen(&waveScr);
	if (scr == 0) Die("Screen nailed shut");
	diag("opened screen");

	vp = &(scr->ViewPort);

	waveWin.Screen = scr;
	win = OpenWindow(&waveWin);
	if (win == 0) Die("Window painted shut");
	diag("opened window");

	rp = win->RPort;
}


/* Fail */
Die(s)
char *s;
{
	printf("%s\nSo much for this program.\n",s);
	CloseThings();
}


/* Close libraries & such */
CloseThings()
{
	diag("Closing everything up.");
	if (win) CloseWindow(win);
	if (scr) CloseScreen(scr);
	if (IntuitionBase) CloseLibrary(IntuitionBase);
	if (GfxBase) CloseLibrary(GfxBase);
}


/* display a message */
diag(s)
char *s;
{
	printf("%s\n",s);
}



/* THIS IS IT */
main()
{
	struct IntuiMessage *msg;
	int i, j;	/* current pt */
	int m,n;		/* just keep track of how many pixels we've plotted */
	float a, b, c, x, y, xx, yy;
	int foo;	/* sure wish C had a "sign" function and an "abs" */
	float bar;
	float mag;


	OpenThings();

	LoadRGB4(vp, waveCols, 16);
	SetDrMd(rp, JAM1);

	n = x = y = 0;

	WBenchToFront();
	printf("Please enter values for a, b, c, and magnification: ");
	scanf("%e %e %e %e",&a,&b,&c,&mag);
	c = sin((double)b);	/* force math library to be loaded now */
	WBenchToBack();

	while (0 == (msg = (struct IntuiMessage *)GetMsg(win->UserPort))) {
		for (m=0; m<100; m++) { /* check for messages only every 100th */
			SetAPen(rp, (++n >> 8) % 16);/* for now, color changes every 256 pts */
			i = (int)(WID/2+mag*x) % 2000;	/* 2000 picked out of a hat */
			j = (int)(HEI/2+mag*y) % 2000;
			WritePixel(rp, i, j);
			WritePixel(rp, i, j+1); /* why?  To reduce interlace flicker */
			if (x<0) foo=-1; else foo=1;
			if ((bar=b*x-c)<0) bar=-bar; 
			xx = y - foo*sqrt((double)bar);
			yy = a - x;
			x = xx;
			y = yy;
		}
	}
	do {
		ReplyMsg(msg);
	} while (msg = (struct IntuiMessage *)GetMsg(win->UserPort));


	finish:
	CloseThings();
}


=== CUT HERE for hop.h ===


/*
	Include file for First Wave Program - 		started 10 Dec 87
	Appropriated for Hopalong, the program that will put
	me in the Hall of Fame -			        30 Aug 88
*/

#include <exec/types.h>
#include <intuition/intuition.h>
#include <graphics/gfxmacros.h>
#include <math.h>


=== CUT HERE for .signature and apology (not necessarily in that order) ===

This is not a very long posting, but if you think it's too long, sorry!



=== === ===         Pa!  Molly's dead!  She ate some leaves!       === === ===
"Trespassers w"   ranjit@eniac.seas.upenn.edu	ucbvax!rutgers!super!eniac!...
Ranjit Bhatnagar, Graduate Student     I'm not an actor, but I play one on TV.