home *** CD-ROM | disk | FTP | other *** search
- /* The Ant Automaton is based on an article in Scientific American, July 1994.
- * The original Fractint implementation was by Tim Wegner in Fractint 19.0.
- * This routine is a major rewrite by Luciano Genero & Fulvio Cappelli using
- * tables for speed, and adds a second ant type, multiple ants, and random
- * rules.
- *
- * Revision history:
- * 20 Mar 95 LG/FC First release of table driven version
- * 31 Mar 95 LG/FC Fixed a bug that writes one pixel off the screen
- * 31 Mar 95 LG/FC Changed ant type 1 to produce the same pattern as the
- * original implementation (they were mirrored on the
- * x axis)
- * 04 Apr 95 TW Added wrap option and further modified the code to match
- * the original algorithm. It now matches exactly.
- * 10 Apr 95 TW Suffix array does not contain enough memory. Crashes at
- * over 1024x768. Changed to extraseg.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "prototyp.h"
- #include "helpdefs.h"
-
- #define RANDOM(n) ((int)((long)((long)rand() * (long)(n)) >> 15)) /* Generate Random
- * Number 0 <= r < n */
- #define MAX_ANTS 256
- #define XO (xdots/2)
- #define YO (ydots/2)
- #define DIRS 4
- #define INNER_LOOP 100
-
- /* possible value of idir e relative movement in the 4 directions
- * for x 0, 1, 0, -1
- * for y 1, 0, -1, 0
- */
- static int far *incx[DIRS]; /* tab for 4 directions */
- static int far *incy[DIRS];
-
- void
- setwait(long *wait)
- {
- char msg[30];
- int kbdchar;
-
- for (;;)
- {
- sprintf(msg, "Delay %4ld", *wait);
- while (strlen(msg) < 15)
- strcat(msg, " ");
- msg[15] = '\0';
- showtempmsg((char far *) msg);
- kbdchar = getakey();
- switch (kbdchar)
- {
- case RIGHT_ARROW_2:
- case UP_ARROW_2:
- (*wait) += 100;
- break;
- case RIGHT_ARROW:
- case UP_ARROW:
- (*wait) += 10;
- break;
- case DOWN_ARROW_2:
- case LEFT_ARROW_2:
- (*wait) -= 100;
- break;
- case LEFT_ARROW:
- case DOWN_ARROW:
- (*wait) -= 10;
- break;
- default:
- cleartempmsg();
- return;
- }
- if (*wait < 0)
- *wait = 0;
- }
- }
-
- /* turkmite from scientific american july 1994 pag 91
- * Tweaked by Luciano Genero & Fulvio Cappelli
- */
- void
- TurkMite1(int maxtur, int rule_len, char *ru, long maxpts, long wait)
- {
- int color, ix, iy, idir, pixel, i;
- int kbdchar, step, antwrap;
- int x[MAX_ANTS + 1], y[MAX_ANTS + 1];
- int next_col[MAX_ANTS + 1], rule[MAX_ANTS + 1], dir[MAX_ANTS + 1];
- long count;
- antwrap = ((param[4] == 0) ? 0 : 1);
- step = (int) wait;
- if (step == 1)
- wait = 0;
- else
- step = 0;
- if (rule_len == 0)
- { /* random rule */
- for (color = 0; color < MAX_ANTS; color++)
- { /* init the rules and colors for the
- * turkmites: 1 turn left, -1 turn right */
- rule[color] = 1 - (RANDOM(2) * 2);
- next_col[color] = color + 1;
- }
- /* close the cycle */
- next_col[color] = 0;
- }
- else
- { /* user defined rule */
- for (color = 0; color < rule_len; color++)
- { /* init the rules and colors for the
- * turkmites: 1 turn left, -1 turn right */
- rule[color] = (ru[color] * 2) - 1;
- next_col[color] = color + 1;
- }
- /* repeats to last color */
- for (color = rule_len; color < MAX_ANTS; color++)
- { /* init the rules and colors for the
- * turkmites: 1 turn left, -1 turn right */
- rule[color] = rule[color % rule_len];
- next_col[color] = color + 1;
- }
- /* close the cycle */
- next_col[color] = 0;
- }
- for (color = maxtur; color; color--)
- { /* init the various turmites N.B. non usa
- * x[0], y[0], dir[0] */
- if (rule_len)
- {
- dir[color] = 1;
- x[color] = XO;
- y[color] = YO;
- }
- else
- {
- dir[color] = RANDOM(DIRS);
- x[color] = RANDOM(xdots);
- y[color] = RANDOM(ydots);
- }
- }
- maxpts = maxpts / (long) INNER_LOOP;
- for (count = 0; count < maxpts; count++)
- {
- /* check for a key only every inner_loop times */
- kbdchar = keypressed();
- if (kbdchar || step)
- {
- int done = 0;
- if (kbdchar == 0)
- kbdchar = getakey();
- switch (kbdchar)
- {
- case SPACE:
- step = 1 - step;
- break;
- case ESC:
- done = 1;
- break;
- case RIGHT_ARROW:
- case UP_ARROW:
- case DOWN_ARROW:
- case LEFT_ARROW:
- case RIGHT_ARROW_2:
- case UP_ARROW_2:
- case DOWN_ARROW_2:
- case LEFT_ARROW_2:
- setwait(&wait);
- break;
- default:
- done = 1;
- break;
- }
- if (done)
- goto exit_ant;
- if (keypressed())
- getakey();
- }
- for (i = INNER_LOOP; i; i--)
- {
- if (wait > 0 && step == 0)
- {
- for (color = maxtur; color; color--)
- { /* move the various turmites */
- ix = x[color]; /* temp vars */
- iy = y[color];
- idir = dir[color];
-
- pixel = getcolor(ix, iy);
- putcolor(ix, iy, 15);
- sleepms(wait);
- putcolor(ix, iy, next_col[pixel]);
- idir += rule[pixel];
- idir &= 3;
- if (antwrap == 0)
- if ((idir == 0 && iy == ydots - 1) ||
- (idir == 1 && ix == xdots - 1) ||
- (idir == 2 && iy == 0) ||
- (idir == 3 && ix == 0))
- goto exit_ant;
- x[color] = incx[idir][ix];
- y[color] = incy[idir][iy];
- dir[color] = idir;
- }
- }
- else
- {
- for (color = maxtur; color; color--)
- { /* move the various turmites without delay */
- ix = x[color]; /* temp vars */
- iy = y[color];
- idir = dir[color];
- pixel = getcolor(ix, iy);
- putcolor(ix, iy, next_col[pixel]);
- idir += rule[pixel];
- idir &= 3;
- if (antwrap == 0)
- if ((idir == 0 && iy == ydots - 1) ||
- (idir == 1 && ix == xdots - 1) ||
- (idir == 2 && iy == 0) ||
- (idir == 3 && ix == 0))
- goto exit_ant;
- x[color] = incx[idir][ix];
- y[color] = incy[idir][iy];
- dir[color] = idir;
- }
- }
- }
- }
- exit_ant:
- return;
- }
-
- /* this one ignore the color of the current cell is more like a white ant */
- void
- TurkMite2(int maxtur, int rule_len, char *ru, long maxpts, long wait)
- {
- int color, ix, iy, idir, pixel, dir[MAX_ANTS + 1], i;
- int kbdchar, step, antwrap;
- int x[MAX_ANTS + 1], y[MAX_ANTS + 1];
- int rule[MAX_ANTS + 1], rule_mask;
- long count;
-
- antwrap = ((param[4] == 0) ? 0 : 1);
-
- step = (int) wait;
- if (step == 1)
- wait = 0;
- else
- step = 0;
- if (rule_len == 0)
- { /* random rule */
- for (color = MAX_ANTS - 1; color; color--)
- { /* init the various turmites N.B. don't use
- * x[0], y[0], dir[0] */
- dir[color] = RANDOM(DIRS);
- rule[color] = (rand() << RANDOM(2)) | RANDOM(2);
- x[color] = RANDOM(xdots);
- y[color] = RANDOM(ydots);
- }
- }
- else
- { /* the same rule the user wants for every
- * turkmite (max rule_len = 16 bit) */
- rule_len = min(rule_len, 8 * sizeof(int));
- for (i = 0, rule[0] = 0; i < rule_len; i++)
- rule[0] = (rule[0] << 1) | ru[i];
- for (color = MAX_ANTS - 1; color; color--)
- { /* init the various turmites N.B. non usa
- * x[0], y[0], dir[0] */
- dir[color] = 0;
- rule[color] = rule[0];
- x[color] = XO;
- y[color] = YO;
- }
- }
- /* use this rule when a black pixel is found */
- rule[0] = 0;
- rule_mask = 1;
- maxpts = maxpts / (long) INNER_LOOP;
- for (count = 0; count < maxpts; count++)
- {
- /* check for a key only every inner_loop times */
- kbdchar = keypressed();
- if (kbdchar || step)
- {
- int done = 0;
- if (kbdchar == 0)
- kbdchar = getakey();
- switch (kbdchar)
- {
- case SPACE:
- step = 1 - step;
- break;
- case ESC:
- done = 1;
- break;
- case RIGHT_ARROW:
- case UP_ARROW:
- case DOWN_ARROW:
- case LEFT_ARROW:
- case RIGHT_ARROW_2:
- case UP_ARROW_2:
- case DOWN_ARROW_2:
- case LEFT_ARROW_2:
- setwait(&wait);
- break;
- default:
- done = 1;
- break;
- }
- if (done)
- goto exit_ant;
- if (keypressed())
- getakey();
- }
- for (i = INNER_LOOP; i; i--)
- {
- for (color = maxtur; color; color--)
- { /* move the various turmites */
- ix = x[color]; /* temp vars */
- iy = y[color];
- idir = dir[color];
- pixel = getcolor(ix, iy);
- putcolor(ix, iy, 15);
-
- if (wait > 0 && step == 0)
- sleepms(wait);
-
- if (rule[pixel] & rule_mask)
- { /* turn right */
- idir--;
- putcolor(ix, iy, 0);
- }
- else
- { /* turn left */
- idir++;
- putcolor(ix, iy, color);
- }
- idir &= 3;
- if (antwrap == 0)
- if ((idir == 0 && iy == ydots - 1) ||
- (idir == 1 && ix == xdots - 1) ||
- (idir == 2 && iy == 0) ||
- (idir == 3 && ix == 0))
- goto exit_ant;
- x[color] = incx[idir][ix];
- y[color] = incy[idir][iy];
- dir[color] = idir;
- }
- rule_mask = _rotl(rule_mask, 1);
- }
- }
- exit_ant:
- return;
- }
-
- /* N.B. use the common memory in extraseg - suffix not large enough*/
- int
- ant(void)
- {
- int maxants, type, i;
- int oldhelpmode, rule_len;
- long maxpts, wait;
- char rule[MAX_ANTS];
- char far *extra;
-
- extra = MK_FP(extraseg,0);
-
- for (i = 0; i < DIRS; i++)
- {
- incx[i] = (int far *) (extra + (xdots + 2) * sizeof(int) * i); /* steal some memory */
- incy[i] = (int far *) (extra + (xdots + 2) * sizeof(int) * DIRS + (ydots + 2) *sizeof(int) * i); /* steal some memory */
- }
-
- /* In this vectors put all the possible point that the ants can visit.
- * Wrap them from a side to the other insted of simply end calculation
- */
- for (i = 0; i < xdots; i++)
- {
- incx[0][i] = i;
- incx[2][i] = i;
- }
-
- for(i = 0; i < xdots; i++)
- incx[3][i] = i + 1;
- incx[3][xdots-1] = 0; /* wrap from right of the screen to left */
-
- for(i = 1; i < xdots; i++)
- incx[1][i] = i - 1;
- incx[1][0] = xdots-1; /* wrap from left of the screen to right */
-
- for (i = 0; i < ydots; i++)
- {
- incy[1][i] = i;
- incy[3][i] = i;
- }
- for (i = 0; i < ydots; i++)
- incy[0][i] = i + 1;
- incy[0][ydots - 1] = 0; /* wrap from the top of the screen to the
- * bottom */
- for (i = 1; i < ydots; i++)
- incy[2][i] = i - 1;
- incy[2][0] = ydots - 1; /* wrap from the bottom of the screen to the
- * top */
- oldhelpmode = helpmode;
- helpmode = ANTCOMMANDS;
- maxpts = (long) param[1];
- maxpts = labs(maxpts);
- wait = abs(orbit_delay);
- sprintf(rule, "%.17g", param[0]);
- rule_len = strlen(rule);
- if (rule_len > 1)
- { /* if rule_len == 0 random rule */
- for (i = 0; i < rule_len; i++)
- {
- if (rule[i] != '1')
- rule[i] = (char) 0;
- else
- rule[i] = (char) 1;
- }
- }
- else
- rule_len = 0;
- maxants = (int) param[2];
-
- /* set random seed for reproducibility */
- if ((!rflag) && param[5] == 1)
- --rseed;
- if (param[5] != 0 && param[5] != 1)
- rseed = (int)param[5];
-
- srand(rseed);
- if (!rflag) ++rseed;
-
- if (maxants < 1) /* if max_ants == 0 max_ants random */
- maxants = 2 + RANDOM(MAX_ANTS - 2);
- type = (int) param[3] - 1;
- if (type < 0 || type > 1)
- type = RANDOM(2); /* if type == 0 choose a random type */
- switch (type)
- {
- case 0:
- TurkMite1(maxants, rule_len, rule, maxpts, wait);
- break;
- case 1:
- TurkMite2(maxants, rule_len, rule, maxpts, wait);
- break;
- }
- helpmode = oldhelpmode;
- return 0;
- }