/**************************************************************** * Fractal.c © John M. Olsen. 9-1-86 * This is a fractal program which produces random square fractal * terrain, with resolution where the size of the sides is * 2^n + 1 where n is between 0 and 6. * The 3D view uses a light source off to the upper left. * * This program requires both c.lib and m.lib when linked. It was written for * Aztec and I have no idea what it will do when compiled with Lettuce C. * * This program is freely distributable as long as this notice remains * with it. Do not use any part of this program in a commercial application * without written consent from the author: * * John M. Olsen * 1547 Jamestown Drive * Salt Lake City, UT 84121 ****************************************************************/ #define MAXFRACT 65 /* This must be 2^something + 1 */ #define EVEN(a) (!(a & 1)) #define ODD(a) (a & 1) #include #include #include #include #include #include #include #include void *OpenLibrary(), *ScreenToBack(), *ScreenToFront(); struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; struct Screen *OpenScreen(), *s; struct Window *OpenWindow(), *w; struct IntuiMessage *GetMsg(); float myrand(); BYTE *AllocRaster(); WORD areabuffer[250]; struct TmpRas tmpras; struct AreaInfo myAreaInfo; struct NewScreen ss = { 0, 0, 320, 200, /* Edges & size */ 5, 0, 1, /* Depth, pens */ NULL, CUSTOMSCREEN, /* Viewmodes, type */ NULL, /* *font */ (UBYTE *) "3D Random Fractal Terrain", NULL, NULL /* Gadgets, bit map */ }; float p[MAXFRACT][MAXFRACT], divisor, scale; int shadows, degree, size; main() { long sc, mc; printf("Fractal generator by John M. Olsen ©1986\n\n"); printf("This program is freely distributable so long as the above\n"); printf("notice remains in it.\n"); printf("After a fractal has been computed and drawn, you need to\n"); printf("push the picture screen back, bringing this screen foreward\n"); printf("before trying to enter more data.\n"); if(!(GfxBase = OpenLibrary("graphics.library",0l))) die(1); if(!(IntuitionBase = OpenLibrary("intuition.library"))) die(2); if(!(s = OpenScreen(&ss))) die(3); InitArea(&myAreaInfo, areabuffer, 100l); s->RastPort.AreaInfo = &myAreaInfo; tmpras.RasPtr = AllocRaster(320l, 200l); tmpras.Size = (long) RASSIZE(320l, 200l); s->RastPort.TmpRas = &tmpras; ScreenToBack(s); docolors(&(s->RastPort)); while(1) { CurrentTime(&sc,&mc); /* Seed the random number by time */ myrand(-(int)sc); getsize(); /* Exits from this routine. */ compute(); ScreenToFront(s); draw(&(s->RastPort)); } } /* Compute the array. */ compute() { float tempscale, rnum, t1, t2, t3, t4; int x, y, n; /* Zero out the corner of the array. */ for(x = 0;x < 2; x++) for(y = 0; y < 2; y++) p[x][y] = 0; tempscale = 64.0; size = 1; for(n = 1; n <= degree; n++) { size *= 2; for(x = size; x >= 0; x--) { for(y = size; y >= 0; y--) { t1 = p[x / 2][y / 2]; t2 = p[(x+1) / 2][(y+1) / 2]; t3 = p[x / 2][(y + 1) / 2]; t4 = p[(x + 1) / 2][y / 2]; rnum = myrand(0) - .5; rnum *= tempscale; if(ODD(x) && EVEN(y)) { p[x][y] = (t1 + t4) / 2.0 + rnum; } else if(EVEN(x) && ODD(y)) { p[x][y] = (t1 + t3) / 2.0 + rnum; } else if(ODD(x) && ODD(y)) { p[x][y] = (t1+t2+t3+t4) / 4.0 + rnum; } else if(EVEN(x) && EVEN(y)) { p[x][y] = t1; } else printf("Toasted.\n"); } } tempscale /= divisor; } /* now run it through the scaler. */ for(x = 0; x <= size; x++) for(y = 0; y <= size; y++) p[x][y] *= scale; } die(kind) int kind; { static char *errortext[] = { "No error.\n", "Unable to open graphics.\n", "Unable to open Intuition.\n", "Unable to open screen.\n", "4\n", "5\n", "6\n" }; if(kind) puts(errortext[kind]); if(tmpras.RasPtr) FreeRaster(tmpras.RasPtr,320l,200l); if(s) CloseScreen(s); if(GfxBase) CloseLibrary(GfxBase); if(IntuitionBase) CloseLibrary(IntuitionBase); exit(kind); } float myrand(seed) int seed; { static unsigned int val; if(seed < 0) val = - seed; val *= 25173; val += 13849; val %= 32768; return((float) val / 32768.0); } draw(r) struct RastPort *r; { int h, x, y, cl, sz; float slopex, slopey; SetAPen(r, 0l); RectFill(r, 0l,10l,320l,200l); /* SetRast(r,0l); this line took out the title bar.*/ h = 150; /* use this many of the 200 lines. */ for(y = 1; y <= size; y++) { for(x = 1; x <= size; x++) { if(shadows) { slopex = p[x][y-1]; slopex += p[x][y]; slopex -= p[x-1][y-1]; slopex -= p[x-1][y]; slopey = p[x][y]; slopey -= p[x][y-1]; slopey -= p[x-1][y-1]; slopey += p[x-1][y]; cl = (int) (slopex + slopey) + 15; } else { cl = (int) p[x][y]; cl += (int) p[x-1][y]; cl += (int) p[x][y-1]; cl += (int) p[x-1][y-1]; cl /= 8; cl += 16; } sz = h / (size + 1); if(cl > 31) cl = 31; if(cl < 1) cl = 1; SetAPen(r, (long)cl); AreaMove(r, (long)(50+((x-1)*sz+(size-y+1)*60/size)+1), (long)(((y-1)*sz-(int)p[x-1][y-1])+30)); /*+1extra*/ AreaDraw(r, (long)(50+(x*sz+(size-y+1)*60/size)+1), (long)(((y-1)*sz-(int)p[x][y-1])+30)); /*+1 extra*/ AreaDraw(r, (long)(50+(x*sz+(size-y)*60/size)+1), /*+1 extra*/ (long)((y*sz-(int)p[x][y])+30)); AreaDraw(r, (long)(50+((x-1)*sz+(size-y)*60/size)+1), (long)((y*sz-(int)p[x-1][y])+30)); AreaEnd(r); } } } /********************* Set up the colors to 32 gray shades. *********************/ docolors(r) struct RastPort *r; { long loop; r = &(s->RastPort); for(loop = 1l; loop < 32l; loop++) SetRGB4(&s->ViewPort, loop, loop/2l, (loop - 1)/2l, loop/2l); } getsize() { printf("Enter the degree(1-6 or invalid to quit): "); scanf(" %d", °ree); if(degree < 1 || degree > 6) die(0); printf("Enter the scale(0.0 to 3.0, 1.0 is standard): "); scanf(" %f", &scale); if(scale > 3.0 || scale < 0.0) die(0); printf("Enter the divisor(1.0 to 4.0, 2.0 is standard): "); scanf(" %f", &divisor); if(divisor > 4.0 || divisor < 1.0) die(0); printf("Altitudes (0) or shadows(non-zero)? "); scanf(" %d", &shadows); }