X-Google-Language: ENGLISH,ASCII X-Google-Thread: f996b,dab8ab4f0301b6aa,start X-Google-Attributes: gidf996b,public X-Google-ArrivalTime: 1994-11-14 10:49:16 PST Path: nntp.gmd.de!Germany.EU.net!netmbx.de!CNB.CompuNet.DE!zrz.TU-Berlin.DE!math.fu-berlin.de!zib-berlin.de!xlink.net!howland.reston.ans.net!news.sprintlink.net!uunet!sunic!news.funet.fi!news.cc.tut.fi!proffa.cc.tut.fi!not-for-mail From: t150315@proffa.cc.tut.fi (Tamminen Eero) Newsgroups: alt.ascii-art Subject: C-SOURCE: Ascii-Chaos v. 0.9 Date: 14 Nov 1994 20:49:16 +0200 Organization: Tampere University of Technology, Computing Centre Lines: 548 Distribution: world Message-ID: <3a8bfc$666@proffa.cc.tut.fi> NNTP-Posting-Host: proffa.cc.tut.fi Summary: A program for doing chaos in 'ascii' Keywords: chaos, ascii Here's a little program i put together during the weekend. It outputs chaotical pictures in modulo, height or shade coloring (8 ascii 'rasters') in 2D and 3D :) to the screen or file. Compile it and give me comments... - Eero - ---- /* Ascii-Chaos v. 0.9 */ /* 1994 (C) Eero Tamminen */ /* Compile with : gcc -O -o aos aos.c */ #include #include #include #include #include #ifndef TRUE #define FALSE 0 #define TRUE !FALSE #endif /* Chaos type */ #define ANT 1 #define MANDEL 2 /* output view */ #define NORMAL 1 #define EYE 2 /* coloring scheme */ #define MODULO 0 #define HEIGHT 1 #define ANGLE 2 /* save file format */ #define ASCII 1 #define PGM 2 /* percpective viewing direction */ #define TOP 1 #define BOTTOM 2 /* -------------------------------------------------------------------- */ /* globals and defaults */ /* max. lenght for raster array */ #define HEIGHTS 8 int Heights = HEIGHTS; char Rasters[HEIGHTS+1] = ".*#%=+:-."; int Columns = 38, Rows = 22; /* 'screen' size */ short Seed = 0x2; /* move sequence bin. string */ short Lenght = 2; /* Lenght of seq. (2-16) */ long Iterations = 2000; int Chaos_mode = ANT; int View_mode = NORMAL; /* 2D or perspective */ int Color_mode = MODULO; /* height / steepness / modulo */ int Head_mode = BOTTOM; /* viewing direction */ int File_mode = FALSE; /* Save to file (ascii / pgm) */ int Pscale = FALSE; /* perspective scaling */ /* -------------------------------------------------------------------- */ int parse(int argc, char *argv[]); /* parser command line */ void help(); short do_mandel(short *grid); /* do Mandelbrot */ short do_ant(short *grid); /* do 'The Ant Walk' */ int do_color(short *grid, unsigned char *pict, int mode, short value); int do_ortho(unsigned char **pict, int range); int angle2num(int angle); /* -------------------------------------------------------------------- */ /* main */ int main(int argc, char *argv[]) { FILE *fp; int antx, anty; short *grid, value; unsigned char *pict; long line; puts("\nAscii-Chaos v. 0.9 (C) 1994 Eero Tamminen"); puts(""); /* get command line args */ if(parse(argc, argv)) { /* create and initialize the grid 'arrays' */ grid = (short *) malloc(2L * Columns * Rows); pict = (unsigned char *) malloc((long)Columns * Rows); if(!(grid && pict)) { puts("Not enough memory!"); return(1); } for(anty = 0; anty < Rows; anty ++) { line = (long)anty * Columns; for(antx = 0; antx < Columns; antx ++) { *(grid + line + antx) = 0; *(pict + line + antx) = ' '; } *(pict + line + antx - 1) = '\0'; } /* make the view */ puts("Building Chaos..."); if(Chaos_mode == ANT) value = do_ant(grid); else value = do_mandel(grid); puts("Visualizing it..."); if(View_mode == EYE) { value = do_color(grid, pict, (Color_mode == ANGLE ? HEIGHT : Color_mode), value); puts("Putting it into perspective..."); do_ortho(&pict, value); } else do_color(grid, pict, Color_mode, value); if(File_mode != PGM && View_mode == EYE) *Rasters = ' '; /* initialize save files */ if(File_mode) { puts("Saving..."); fp = fopen((File_mode == ASCII ? "aos_out.asc" : "aos_out.ppm"), "wb"); if(File_mode == PGM) fprintf(fp, "P2\n%d %d\n255\n", Columns-1, Rows); fprintf(fp, "# Produced with Ascii-Chaos v 0.9 (C) 1994 by Eero Tamminen.\n"); } else fp = stdout; /* save / show the results */ for(anty = 0; anty < Rows; anty ++) { line = (long)anty * Columns; for(antx = 0; antx < Columns - 1; antx ++) if(File_mode == PGM) fprintf(fp, "%d ", *(pict + line + antx)); else fprintf(fp, "%c", Rasters[*(pict + line + antx)]); fprintf(fp, "\n"); } if(File_mode) { puts("Done."); fclose(fp); } /* free 'arrays' */ free(pict); free(grid); } return(0); } int parse(int argc, char *argv[]) { /* change global variables etc. */ int i, idx; char mark; i = 0; while(++i < argc) { /* check all arguments */ mark = toupper(argv[i][0]); /* first character... */ switch(mark) { case '-': /* get 'color' string */ switch(toupper(argv[i][1])) { case 'D': View_mode = EYE; break; case 'Z': Pscale = max(2, atoi(&argv[i][2]) & 0xFF); break; case 'T': Head_mode = TOP; break; case 'B': Head_mode = BOTTOM; break; case 'A': File_mode = ASCII; break; case 'P': File_mode = PGM; Heights = 256; break; case 'H': Color_mode = HEIGHT; break; case 'S': Color_mode = ANGLE; break; case 'M': Color_mode = MODULO; break; case 'X': /* screen width */ Columns = max(8, atoi(&argv[i][2]) & 0xFFF); break; case 'Y': /* screen height */ Rows = max(8, atoi(&argv[i][2])) & 0xFFF; break; default: /* unrecogniced option */ help(); return(FALSE); } break; case 'M': Chaos_mode = MANDEL; Lenght = HEIGHTS; Iterations = 8; break; case 'R': /* new Seed */ case 'L': Seed = 0; idx = 1; do { Seed =(Seed << 1); if(mark == 'R') Seed |= 1; idx++; mark = toupper(argv[i][idx]); } while(idx < HEIGHTS && (mark == 'R' || mark == 'L')); Lenght = idx - 1; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': Iterations = max(4, atol(argv[i])); break; default: /* unrecogniced option */ help(); return(FALSE); } } return(TRUE); } void help() { puts("Options controlling the output:"); puts(" -x32 Set area width to 32 characters / pixels."); puts(" -y32 Set area height to 32 characters / pixels."); puts(" -h/-s/-m Color according to height / steepness / sequence modulo."); puts(" -d Select a 3D (perspective) view instead of a flat 2D."); puts(" -z32 Scale perspective view height to an absolute value 32."); puts(" -t/-b Set perspective viewing direction to top or bottom."); puts(""); puts(" -a/-p Output into a file in ascii / portable greymap format."); puts(""); puts("Ant-walk (default):"); puts(" An example: aos rllllr 2000"); puts(" rllllr Ant's movement sequence (R = right, L = left)."); puts(" 2000 How many moves are put into doing the Anthill."); puts(""); puts("Mandelbrot:"); puts(" An example: m 32 -h -p -x64 -y64"); puts(" m Use Mandelbrot instead of Ant-walk."); puts(" 32 How many iterations before deciding point to be inside."); } /* Calculate the 'standard' Mandelbrot's image: * Iterate 'Z = Z� + c' until it zooms to infinity or count is reached. * z and c are complex numbers! * Point's color = count. */ short do_mandel(short *grid) { /* Values x1 = -2.75, y1 = -2.4, x2 = 2.0, y2 = 2.4, limit = 8.0 * are shifted left 10 times to be able to calculate with integers. */ /* Define the place of the calculation on the imaginary plane. */ long x1 = -2816L, y1 = -2457L, x2 = 2048L, y2 = 2457L; /* Define 'step's and 'infinity'^2 and max. iteration count. */ long dx, dy, limit = 0x2000000L; /* Variables for calculation: */ long imag, real, x, y, a; int count, xx, yy = 0; long line; dx = (x2 - x1) / Columns; dy = (y2 - y1) / Rows; /* imaginary axis */ for(imag = y1; imag < y2; imag += dy) { xx = 0; line = (long)yy * Columns; /* real axis */ for(real = x1; real < x2; real += dx) { /* calculate one pixel's 'escape' value ie. color/height */ x = y = 0L; count = 0; do { a = x; x = ((x * x - y * y) >> 10) + real; y = (2 * a * y >> 10) + imag; count ++; } while((count < Iterations) && (x * x + y * y <= limit)); *(grid + line + xx) = count; xx ++; } yy ++; } return(Iterations); } /* -------------------------------------------------------------------- */ /* 'Do the Ant Walk' */ short do_ant(short *grid) { int antx, anty, heading = 0; short *value, max_val = 0; long move = 0; antx = Columns >> 1; /* initial position */ anty = Rows >> 1; /* at center */ do { value = grid + anty * Columns + antx; /* use modulo to get new heading and increase the grid value */ if(Seed & (1 << (*value % Lenght))) { if((++ heading) > 3) /* new heading */ heading = 0; } else if((-- heading) < 0) heading = 3; if(++(*value) > max_val) { max_val = *value; /* check for short overshoot */ if(max_val > 32000) move = Iterations; } switch(heading) { /* new place */ case 0: anty ++; /* down */ break; case 1: antx --; /* left */ break; case 2: anty --; /* up */ break; case 3: antx ++; /* right */ break; } if(antx >= Columns) /* check boundarys */ antx = 0; if(anty >= Rows) anty = 0; if(antx < 0) antx = Columns - 1; if(anty < 0) anty = Rows - 1; } while(move++ < Iterations); /* until a key is hit */ return(max_val); } int do_color(short *grid, unsigned char *pict, int mode, short divide) { int i, antx, anty, angle, mini = 0; long place, line; if(mode == HEIGHT) { /* search the smallest value on grid (for bump map scaling) */ mini = divide; for(anty = 0; anty < Rows; anty ++) line = (long)anty * Columns; for(antx = 0; antx < Columns - 1; antx ++) { i = *(grid + line + antx); if(i < mini) mini = i; } divide -= mini; } for(anty = 0; anty < Rows; anty ++) { line = (long)anty * Columns; for(antx = 0; antx < Columns - 1; antx ++) { place = line + antx; switch(mode) { case MODULO: *(pict + place) = *(grid + place) % Lenght; break; case HEIGHT: *(pict + place) = (long)(*(grid + place) - mini) * Heights / divide; break; case ANGLE: angle = angle2num(*(grid + place + 1) - *(grid + place)); *(pict + place) = angle; if(angle > mini) mini = angle; break; } } } switch(mode) { case MODULO: return(Lenght); case HEIGHT: return(Heights); case ANGLE: return(mini); default: return(256); } } int angle2num(int angle) { if(File_mode == PGM) angle += 127; else { angle += 4; if(angle > 8) angle = 8; else if(angle < 2) angle = 2; } return(angle); } int do_ortho(unsigned char **pict, int range) { int i, x, y, xx, yy, ox, oy, offset, oy1, oy2, hz, oz, eye, height; unsigned char *view, tag; long place, line; /* relative eye place & orthogonal view area */ eye = Rows * 2; oz = Columns / 2; xx = Columns; if(Pscale) height = Pscale; else height = range; oy = height / 2; offset = oy / 2; height += oy; yy = height - offset + 1; if(!(view = (unsigned char *)malloc((long)xx * yy))) { puts("Not enough memory!"); return(FALSE); } /* empty area */ for(place = 0; place < (long)xx*yy; place ++) view[place] = '\0'; /* move calculated values into orhtogonal an 'area' */ for(y = Rows; --y >= 0;) { if(Head_mode == TOP) line = (long)y * Columns; else line = (long)(Rows - y - 1) * Columns; oy2 = eye * height / (eye + y); for(x = 0; x < Columns - 1; x ++) { tag = *((*pict) + line + x); if(Pscale) hz = tag * Pscale / range; else hz = tag; if(Color_mode == ANGLE) tag = angle2num(*((*pict) + line + x + 1) - tag); ox = eye * (x - oz) / (eye + y) + oz; oy1 = eye * (height - hz) / (eye + y); place = (long)(oy1 - offset) * xx + ox; for(i = oy1; i < oy2; i ++) { view[place] = tag; place += xx; } } view[(long)y * xx + x] = '\0'; } free(*pict); (*pict) = view; Columns = xx; Rows = yy; return(TRUE); } /* Perspective used: * * Z * * ^ Y * | _ * | /| * |/ * \------> X * * Normal 2D view for the 'anthill': * * Y * * ^ * | * | * \-----> X */