home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD1.img
/
d1xx
/
d188
/
fastgro
/
fastgro.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-02-26
|
11KB
|
386 lines
/* FastGro 1.0 - a simulation of Diffusion-Limited Aggregation
Copyright (c) 1989 Doug Houck (03-Feb-89)
This program has been placed in the PUBLIC DOMAIN, so anyone,
anywhere can do anything they want with it.
This was compiled with the Aztec C compiler, version 3.6a, using
the large data, large code, small integer model. "cc +d +d ..."
and linked with "ln FastGro.o Wander.o -lml -lcl"
*/
#include <exec/types.h>
#include <intuition/intuition.h>
#include <functions.h> /* learn about system */
#define RANDOMS 50437 /* how many random #s to generate */
#define STARTING_POINTS 200 /* points around circle for starting */
#define ffp long /* Motorola Fast Floating Point */
extern ffp
ran(), /* use manx random # generator */
SPFlt(), SPFix(), SPMul(), SPDiv(),
SPSin(), SPCos(), SPAdd(), SPSub();
struct Screen *hires_screen = NULL;
struct Window *hires_window = NULL;
struct RastPort *hires_rp = NULL;
struct MsgPort *window_port = NULL;
long MathBase = NULL, /* library bases */
MathTransBase = NULL,
IntuitionBase = NULL,
GfxBase = NULL;
int rows, columns, /* size of screen in pixels */
maxrow, maxcolumn,
columnsdiv8; /* in bytes */
long radius, color_iterations,
points, points_to_go; /* parameters for drawing */
char *row[550]; /* pointers to rows */
char *row_memory = NULL; /* in row memory */
char *border[550]; /* pointers to rows */
char *border_memory = NULL; /* in border memory */
long optimizer_memory; /* how much space used */
char *randoms = NULL; /* pointer to random array */
char *next_random; /* index into randoms */
struct start_t /* cache starting points */
{ int x, y;
};
struct start_t start[STARTING_POINTS];
struct NewScreen new_hires_screen =
{ 0,0,
640, STDSCREENHEIGHT, /* size from Workbench screen */
4, /* 16 colors */
2,1, /* pens */
HIRES | LACE,
CUSTOMSCREEN | SHOWTITLE | SCREENQUIET | SCREENBEHIND,
NULL,
NULL,
NULL,
NULL
};
struct NewWindow new_hires_window =
{ 0,0, /* coords */
640,400,
0,1, /* pens */
MOUSEBUTTONS,
BACKDROP | BORDERLESS,
NULL,
NULL,
NULL, /* title */
NULL, /* screen */
NULL, /* bitmap */
0,0,0,0, /* min, max */
CUSTOMSCREEN
};
initialize(argc, argv) /* open libraries, allocate memory... */
int argc;
char **argv;
{
IntuitionBase = (long)OpenLibrary( "intuition.library",33L);
if (!IntuitionBase)
{ ReportProblem("I Really Needed Kickstart/Workbench 1.2");
return(0);
}
GfxBase = (long)OpenLibrary( "graphics.library",33L);
if (!GfxBase)
{ ReportProblem("can't open graphics.library");
return(FALSE);
}
MathBase = (long)OpenLibrary( "mathffp.library",33L);
if (!MathBase)
{ ReportProblem("can't open mathffp.library");
return(FALSE);
}
MathTransBase = (long)OpenLibrary( "mathtrans.library",33L);
if (!MathTransBase)
{ ReportProblem("Would kinda liketa have 'mathtrans.library' 1.2, mebbee?");
return(FALSE);
}
rows = DisplayRows()<<1; /* get # of rows in WB screen */
maxrow = rows-1;
columns = DisplayColumns()<<1; /* get # of columns in WB screen */
columnsdiv8 = (columns+7)>>3;
maxcolumn = columns-1;
optimizer_memory = rows * columnsdiv8; /* space arrays will use */
/* ------------------------------- display screen ---------------------- */
new_hires_screen.Height = rows;
new_hires_screen.Width = columns;
hires_screen = OpenScreen( &new_hires_screen );
if (!hires_screen)
{ ReportProblem("No Memory for HiRes Screen. Sorry!");
return(0);
}
new_hires_window.Screen = hires_screen;
new_hires_window.Width = hires_screen->Width;
new_hires_window.Height = hires_screen->Height;
hires_window = OpenWindow( &new_hires_window );
if (!hires_window )
{ ReportProblem("Can't open hires window");
return(0);
}
hires_rp = hires_window->RPort;
window_port = hires_window->UserPort;
{ long red, green, blue; /* set up colors */
green = 12;
for( red = 0, blue = 15;
red <= 15;
red++, blue--
)
SetRGB4( &hires_screen->ViewPort, red, red, green, blue );
SetRGB4( &hires_screen->ViewPort, 0L, 0L, 0L, 0L );
}
/* ---------------------- allocate optimizing arrays --------------------- */
row_memory = (char*)AllocMem( optimizer_memory, 0L );
border_memory = (char*)AllocMem( optimizer_memory, 0L );
if (!row_memory || !border_memory)
{ ReportProblem("No Memory For Auxiliary Arrays");
return(FALSE);
}
{ int i = 0; /* init row pointers into arrays */
char *row_ptr = row_memory;
char *border_ptr = border_memory;
for( i=0; i < rows; i++ )
{ row[i] = row_ptr;
border[i] = border_ptr;
row_ptr += columnsdiv8;
border_ptr += columnsdiv8;
}
}
randoms = (char*)AllocMem( (long)RANDOMS, 0L );
if (!randoms)
{ ReportProblem( "no random array");
return(0);
}
{ long counter = RANDOMS-1; /* init random array */
register char *ptr = randoms;
long scaler;
scaler = SPFlt( 254L );
while(--counter)
*ptr++ = SPFix( SPMul(ran(), scaler ) )+ 1;
*ptr = 0; /* 0 marks the end */
next_random = randoms;
}
radius = 70;
color_iterations = 100;
points = 5000;
return( TRUE );
}
wrapup() /* clean up, close libraries, deallocate, wipe nose, etc */
{
if (randoms) FreeMem ( randoms, (long)RANDOMS );
if (row_memory) FreeMem ( row_memory, optimizer_memory );
if (border_memory) FreeMem ( border_memory, optimizer_memory );
if (hires_window) CloseWindow ( hires_window );
if (hires_screen) CloseScreen ( hires_screen );
if (IntuitionBase) CloseLibrary ( IntuitionBase );
if (GfxBase) CloseLibrary ( GfxBase );
if (MathTransBase) CloseLibrary ( MathTransBase );
if (MathBase) CloseLibrary ( MathBase );
exit( 0 );
}
ReportProblem( text )
char *text;
{ char answer[64];
printf("Had a slight problem...\n\n");
printf(" %s\n\n", text);
printf("Press <RETURN> to abort. ");
gets( answer );
}
mark_perimeter( x, y ) /* mark perimeter around a pixel */
int x, y;
{ setbit( row, x, y );
if (y>0) setbit( row, x , y-1 ); /* careful of edges... */
if (y<maxrow) setbit( row, x , y+1 );
if (x>0)
{ if (y>0) setbit( row, x-1, y-1 );
setbit( row, x-1, y );
if (y<maxrow) setbit( row, x-1, y+1 );
}
if (x<maxcolumn)
{ if (y>0) setbit( row, x+1, y-1 );
setbit( row, x+1, y );
if (y<maxrow) setbit( row, x+1, y+1 );
}
}
set_up_optimizing( radius )
long radius;
{ int x, y;
long midx, midy;
int steps, s, thick;
ffp theta, stepsize, radi;
midx = columns / 2;
midy = rows / 2;
for(y = 0; y<rows; y++) /* clear everything first */
for(x=0; x<columnsdiv8; x++)
{ row[y][x] = 0;
border[y][x] = 0;
}
steps = radius * 12; /* mark border of circle */
stepsize = SPDiv( SPFlt((long)steps), /* 2 pi / steps */
SPDiv( SPFlt(1000L), SPFlt( 6283L) ) );
radi = SPFlt( radius );
for(thick = 0; thick<4; thick++ ) /* make sure no leaks */
{ for( theta = 0, s = steps;
s;
s--, theta = SPAdd(theta, stepsize ) )
{ x = midx + SPFix(SPMul( SPCos(theta), radi ));
y = midy + SPFix(SPMul( SPSin(theta), radi ));
setbit( row, x, y );
setbit( border, x, y );
}
radi = SPSub( SPDiv( SPFlt(3L),SPFlt(1L)), radi );
}
/* set up starting points */
steps = STARTING_POINTS;
stepsize = SPDiv( SPFlt((long)steps),SPDiv( SPFlt(1000L), SPFlt( 6283L) ) );
radi = SPFlt( radius - 3L );
for( theta = 0, steps = 0;
steps < STARTING_POINTS;
steps++, theta = SPAdd(theta, stepsize )
)
{ start[steps].x = midx + SPFix(SPMul( SPCos(theta), radi ));
start[steps].y = midy + SPFix(SPMul( SPSin(theta), radi ));
}
}
draw_fractal()
{ long max_radius, color_counter, color;
int x,y;
ffp start_scale;
int start_location;
struct IntuiMessage *im;
char answer[64];
max_radius = rows/2 - 2;
start_scale = SPFlt( (long)STARTING_POINTS );
printf("\n\nRadius (10..%ld) [%ld] ",max_radius, radius); /* get parms */
gets( answer );
if (answer[0])
{ sscanf(answer, "%ld", &radius );
if (radius < 10) radius = 10;
if (radius > max_radius) radius = max_radius;
}
printf("Particles (1..1000000) [%ld] ",points);
gets( answer );
if (answer[0])
sscanf(answer, "%ld", &points );
points_to_go = points;
printf("Change Color After (1..1000000) [%ld] ",color_iterations);
gets( answer );
if (answer[0])
sscanf( answer, "%ld", &color_iterations );
color = 1;
color_counter = color_iterations;
printf("To abort drawing, click anywhere on drawing.\n");
printf("Setting up...\n");
set_up_optimizing( radius);
x = columns / 2; /* seed the center */
y = rows / 2;
mark_perimeter(x,y);
WritePixel( hires_rp, (long)x, (long)y );
SetAPen( hires_rp, 1L ); /* erase window */
SetDrMd( hires_rp, JAM2 );
SetRast( hires_rp, 0L );
ScreenToFront( hires_screen );
/* clean out port */
while( im = (struct IntuiMessage*)GetMsg( window_port) )
ReplyMsg( im );
while(!IsMessageWaiting(window_port) && (points_to_go> 0 ))
{ start_location = SPFix(SPMul( ran(), start_scale ));
x = start[start_location].x;
y = start[start_location].y;
wander_asm( &x, &y ); /* do the time-consuming stuff */
if (!checkbit( border, x, y ) ) /* not a border hit? OK! */
{ mark_perimeter(x,y);
WritePixel( hires_rp, (long)x, (long)y );
points_to_go--;
if( !(--color_counter) )
{ color_counter = color_iterations;
color++;
if (color > 15) color = 1;
SetAPen( hires_rp, color );
}
}
}
ScreenToBack( hires_screen);
}
main( argc, argv )
int argc;
char **argv;
{ char answer[32];
printf("Welcome to FastGro, a fractal program by Doug Houck,\n");
printf("simulating Diffusion-Limited Aggregation. The purpose\n");
printf("of this program is to demonstrate how selected\n");
printf("optimizations can improve the speed of a program by\n");
printf("an order of magnitude. Meanwhile, I'm setting up...\n");
if (!initialize( argc, argv ))
wrapup();
do
{ draw_fractal();
printf("More? (Y/N) [Yes] ");
gets( answer );
}
while ( ! ((answer[0]=='N') || (answer[0]=='n')) );
wrapup();
}