+++ /dev/null
-/* -*- Mode: C; tab-width: 4 -*- */
-/*-
- * ant --- Chris Langton's generalized turing machine ants (also known
- * as Greg Turk's turmites) whose tape is the screen
- */
-
-#if !defined( lint ) && !defined( SABER )
-static const char sccsid[] = "@(#)ant.c 4.11 98/06/18 xlockmore";
-
-#endif
-
-/*-
- * Copyright (c) 1995 by David Bagley.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation.
- *
- * This file is provided AS IS with no warranties of any kind. The author
- * shall have no liability with respect to the infringement of copyrights,
- * trade secrets or any patents by this file or any part thereof. In no
- * event will the author be liable for any lost revenue or profits or
- * other special, indirect and consequential damages.
- *
- * Revision History:
- * 10-May-97: Compatible with xscreensaver
- * 16-Apr-97: -neighbors 3 and 8 added
- * 01-Jan-97: Updated ant.c to handle more kinds of ants. Thanks to
- * J Austin David <Austin.David@tlogic.com>. Check it out in
- * java at http://havoc.gtf.gatech.edu/austin He thought up the
- * new Ladder ant.
- * 04-Apr-96: -neighbors 6 runtime-time option added for hexagonal ants
- * (bees), coded from an idea of Jim Propp's in Science News,
- * Oct 28, 1995 VOL. 148 page 287
- * 20-Sep-95: Memory leak in ant fixed. Now random colors.
- * 05-Sep-95: Coded from A.K. Dewdney's "Computer Recreations", Scientific
- * American Magazine" Sep 1989 pp 180-183, Mar 1990 p 121
- * Also used Ian Stewart's Mathematical Recreations, Scientific
- * American Jul 1994 pp 104-107
- * also used demon.c and life.c as a guide.
- */
-
-/*-
- Species Grid Number of Neigbors
- ------- ---- ------------------
- Ants Square 4 (or 8)
- Bees Hexagon 6
- Bees Triangle 3 (or 9, 12)
-
- Neighbors 6 and neighbors 3 produce the same Turk ants.
-*/
-
-#ifdef STANDALONE
-# define PROGCLASS "Ant"
-# define HACK_INIT init_ant
-# define HACK_DRAW draw_ant
-# define ant_opts xlockmore_opts
-# define DEFAULTS "*delay: 1000 \n" \
- "*count: -3 \n" \
- "*cycles: 40000 \n" \
- "*size: -12 \n" \
- "*ncolors: 64 \n" \
- "*neighbors: 0 \n" \
- "*sharpturn: False \n"
-# include "xlockmore.h" /* in xscreensaver distribution */
-# include "erase.h"
-#else /* STANDALONE */
-# include "xlock.h" /* in xlockmore distribution */
-#endif /* STANDALONE */
-
-#include "automata.h"
-
-/*-
- * neighbors of 0 randomizes it between 3, 4 and 6.
- * 8, 9 12 are available also but not recommended.
- */
-
-#ifdef STANDALONE
-static int neighbors;
-#else
-extern int neighbors;
-#endif /* !STANDALONE */
-
-#define DEF_TRUCHET "False"
-#define DEF_SHARPTURN "False"
-#define DEF_NEIGHBORS "0"
-
-static Bool truchet;
-static Bool sharpturn;
-
-static XrmOptionDescRec opts[] =
-{
- {"-truchet", ".ant.truchet", XrmoptionNoArg, (caddr_t) "on"},
- {"+truchet", ".ant.truchet", XrmoptionNoArg, (caddr_t) "off"},
- {"-sharpturn", ".ant.sharpturn", XrmoptionNoArg, (caddr_t) "on"},
- {"+sharpturn", ".ant.sharpturn", XrmoptionNoArg, (caddr_t) "off"},
-
-#ifdef STANDALONE
- {"-neighbors", ".ant.neighbors", XrmoptionSepArg, (caddr_t) 0},
- {"+neighbors", ".ant.neighbors", XrmoptionSepArg, (caddr_t) 0}
-#endif /* STANDALONE */
-
-};
-static argtype vars[] =
-{
- {(caddr_t *) & truchet, "truchet", "Truchet", DEF_TRUCHET, t_Bool},
- {(caddr_t *) & sharpturn, "sharpturn", "SharpTurn", DEF_SHARPTURN, t_Bool},
-#ifdef STANDALONE
- {(caddr_t *) & neighbors, "neighbors", "Neighbors", DEF_NEIGHBORS, t_Int}
-#endif /* STANDALONE */
-};
-static OptionStruct desc[] =
-{
- {"-/+truchet", "turn on/off Truchet lines"},
- {"-/+sharpturn", "turn on/off sharp turns (6 or 12 neighbors only)"}
-};
-
-ModeSpecOpt ant_opts =
-{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
-
-#ifdef USE_MODULES
-ModStruct ant_description =
-{"ant", "init_ant", "draw_ant", "release_ant",
- "refresh_ant", "init_ant", NULL, &ant_opts,
- 1000, -3, 40000, -12, 64, 1.0, "",
- "Shows Langton's and Turk's generalized ants", 0, NULL};
-
-#endif
-
-#define ANTBITS(n,w,h)\
- ap->pixmaps[ap->init_bits++]=\
- XCreatePixmapFromBitmapData(display,window,(char *)n,w,h,1,0,1)
-
-/* If you change the table you may have to change the following 2 constants */
-#define STATES 2
-#define MINANTS 1
-#define REDRAWSTEP 2000 /* How much tape to draw per cycle */
-#define MINGRIDSIZE 24
-#define MINSIZE 1
-#define MINRANDOMSIZE 5
-#define ANGLES 360
-
-
-typedef struct {
- unsigned char color;
- short direction;
- unsigned char next;
-} statestruct;
-
-typedef struct {
- int col, row;
- short direction;
- unsigned char state;
-} antstruct;
-
-typedef struct {
- Bool painted;
- int neighbors;
- int generation;
- int xs, ys;
- int xb, yb;
- int nrows, ncols;
- int width, height;
- unsigned char ncolors, nstates;
- int n;
- int redrawing, redrawpos;
- int truchet; /* Only for Turk modes */
- int sharpturn; /* Only for even neighbors > 4 (i.e. 6 and 12) */
- statestruct machine[NUMSTIPPLES * STATES];
- unsigned char *tape;
- unsigned char *truchet_state;
- antstruct *ants;
- int init_bits;
- unsigned char colors[NUMSTIPPLES - 1];
- GC stippledGC;
- Pixmap pixmaps[NUMSTIPPLES - 1];
- union {
- XPoint hexagon[7]; /* Need more than 6 for truchet */
- XPoint triangle[2][4]; /* Need more than 3 for truchet */
- } shape;
-} antfarmstruct;
-
-static char plots[] =
-{3,
-#if 1 /* Without this... this mode is misnamed... */
- 4,
-#endif
- 6}; /* Neighborhoods, 8 just makes a mess */
-
-#define NEIGHBORKINDS (long) (sizeof plots / sizeof *plots)
-
-/* Relative ant moves */
-#define FS 0 /* Step */
-#define TRS 1 /* Turn right, then step */
-#define THRS 2 /* Turn hard right, then step */
-#define TBS 3 /* Turn back, then step */
-#define THLS 4 /* Turn hard left, then step */
-#define TLS 5 /* Turn left, then step */
-#define SF 6 /* Step */
-#define STR 7 /* Step then turn right */
-#define STHR 8 /* Step then turn hard right */
-#define STB 9 /* Step then turn back */
-#define STHL 10 /* Step then turn hard left */
-#define STL 11 /* Step then turn left */
-
-static antfarmstruct *antfarms = NULL;
-
-/* LANGTON'S ANT (10) Chaotic after 500, Builder after 10,000 (104p) */
-/* TURK'S 100 ANT Always chaotic?, tested past 150,000,000 */
-/* TURK'S 101 ANT Always chaotic? */
-/* TURK'S 110 ANT Builder at 150 (18p) */
-/* TURK'S 1000 ANT Always chaotic? */
-/* TURK'S 1100 SYMMETRIC ANT all even run 1's and 0's are symmetric */
-/* other examples 1001, 110011, 110000, 1001101 */
-/* TURK'S 1101 ANT Builder after 250,000 (388p) */
-/* Once saw a chess horse type builder (i.e. non-45 degree builder) */
-
-/* BEE ONLY */
-/* All alternating 10 appear symmetric, no proof (i.e. 10, 1010, etc) */
-/* Even runs of 0's and 1's are also symmetric */
-/* I have seen Hexagonal builders but they are more rare. */
-
-static unsigned char tables[][3 * NUMSTIPPLES * STATES + 2] =
-{
-#if 0
- /* Here just so you can figure out notation */
- { /* Langton's ant */
- 2, 1,
- 1, TLS, 0, 0, TRS, 0
- },
-#else
- /* First 2 numbers are the size (ncolors, nstates) */
- { /* LADDER BUILDER */
- 4, 1,
- 1, STR, 0, 2, STL, 0, 3, TRS, 0, 0, TLS, 0
- },
- { /* SPIRALING PATTERN */
- 2, 2,
- 1, TLS, 0, 0, FS, 1,
- 1, TRS, 0, 1, TRS, 0
- },
- { /* SQUARE (HEXAGON) BUILDER */
- 2, 2,
- 1, TLS, 0, 0, FS, 1,
- 0, TRS, 0, 1, TRS, 0
- },
-#endif
-};
-
-#define NTABLES (sizeof tables / sizeof tables[0])
-
-static void
-position_of_neighbor(antfarmstruct * ap, int dir, int *pcol, int *prow)
-{
- int col = *pcol, row = *prow;
-
- if (ap->neighbors == 6) {
- switch (dir) {
- case 0:
- col = (col + 1 == ap->ncols) ? 0 : col + 1;
- break;
- case 60:
- if (!(row & 1))
- col = (col + 1 == ap->ncols) ? 0 : col + 1;
- row = (!row) ? ap->nrows - 1 : row - 1;
- break;
- case 120:
- if (row & 1)
- col = (!col) ? ap->ncols - 1 : col - 1;
- row = (!row) ? ap->nrows - 1 : row - 1;
- break;
- case 180:
- col = (!col) ? ap->ncols - 1 : col - 1;
- break;
- case 240:
- if (row & 1)
- col = (!col) ? ap->ncols - 1 : col - 1;
- row = (row + 1 == ap->nrows) ? 0 : row + 1;
- break;
- case 300:
- if (!(row & 1))
- col = (col + 1 == ap->ncols) ? 0 : col + 1;
- row = (row + 1 == ap->nrows) ? 0 : row + 1;
- break;
- default:
- (void) fprintf(stderr, "wrong direction %d\n", dir);
- }
- } else if (ap->neighbors == 4 || ap->neighbors == 8) {
- switch (dir) {
- case 0:
- col = (col + 1 == ap->ncols) ? 0 : col + 1;
- break;
- case 45:
- col = (col + 1 == ap->ncols) ? 0 : col + 1;
- row = (!row) ? ap->nrows - 1 : row - 1;
- break;
- case 90:
- row = (!row) ? ap->nrows - 1 : row - 1;
- break;
- case 135:
- col = (!col) ? ap->ncols - 1 : col - 1;
- row = (!row) ? ap->nrows - 1 : row - 1;
- break;
- case 180:
- col = (!col) ? ap->ncols - 1 : col - 1;
- break;
- case 225:
- col = (!col) ? ap->ncols - 1 : col - 1;
- row = (row + 1 == ap->nrows) ? 0 : row + 1;
- break;
- case 270:
- row = (row + 1 == ap->nrows) ? 0 : row + 1;
- break;
- case 315:
- col = (col + 1 == ap->ncols) ? 0 : col + 1;
- row = (row + 1 == ap->nrows) ? 0 : row + 1;
- break;
- default:
- (void) fprintf(stderr, "wrong direction %d\n", dir);
- }
- } else { /* TRI */
- if ((col + row) % 2) { /* right */
- switch (dir) {
- case 0:
- col = (!col) ? ap->ncols - 1 : col - 1;
- break;
- case 30:
- case 40:
- col = (!col) ? ap->ncols - 1 : col - 1;
- row = (!row) ? ap->nrows - 1 : row - 1;
- break;
- case 60:
- col = (!col) ? ap->ncols - 1 : col - 1;
- if (!row)
- row = ap->nrows - 2;
- else if (!(row - 1))
- row = ap->nrows - 1;
- else
- row = row - 2;
- break;
- case 80:
- case 90:
- if (!row)
- row = ap->nrows - 2;
- else if (!(row - 1))
- row = ap->nrows - 1;
- else
- row = row - 2;
- break;
- case 120:
- row = (!row) ? ap->nrows - 1 : row - 1;
- break;
- case 150:
- case 160:
- col = (col + 1 == ap->ncols) ? 0 : col + 1;
- row = (!row) ? ap->nrows - 1 : row - 1;
- break;
- case 180:
- col = (col + 1 == ap->ncols) ? 0 : col + 1;
- break;
- case 200:
- case 210:
- col = (col + 1 == ap->ncols) ? 0 : col + 1;
- row = (row + 1 == ap->nrows) ? 0 : row + 1;
- break;
- case 240:
- row = (row + 1 == ap->nrows) ? 0 : row + 1;
- break;
- case 270:
- case 280:
- if (row + 1 == ap->nrows)
- row = 1;
- else if (row + 2 == ap->nrows)
- row = 0;
- else
- row = row + 2;
- break;
- case 300:
- col = (!col) ? ap->ncols - 1 : col - 1;
- if (row + 1 == ap->nrows)
- row = 1;
- else if (row + 2 == ap->nrows)
- row = 0;
- else
- row = row + 2;
- break;
- case 320:
- case 330:
- col = (!col) ? ap->ncols - 1 : col - 1;
- row = (row + 1 == ap->nrows) ? 0 : row + 1;
- break;
- default:
- (void) fprintf(stderr, "wrong direction %d\n", dir);
- }
- } else { /* left */
- switch (dir) {
- case 0:
- col = (col + 1 == ap->ncols) ? 0 : col + 1;
- break;
- case 30:
- case 40:
- col = (col + 1 == ap->ncols) ? 0 : col + 1;
- row = (row + 1 == ap->nrows) ? 0 : row + 1;
- break;
- case 60:
- col = (col + 1 == ap->ncols) ? 0 : col + 1;
- if (row + 1 == ap->nrows)
- row = 1;
- else if (row + 2 == ap->nrows)
- row = 0;
- else
- row = row + 2;
- break;
- case 80:
- case 90:
- if (row + 1 == ap->nrows)
- row = 1;
- else if (row + 2 == ap->nrows)
- row = 0;
- else
- row = row + 2;
- break;
- case 120:
- row = (row + 1 == ap->nrows) ? 0 : row + 1;
- break;
- case 150:
- case 160:
- col = (!col) ? ap->ncols - 1 : col - 1;
- row = (row + 1 == ap->nrows) ? 0 : row + 1;
- break;
- case 180:
- col = (!col) ? ap->ncols - 1 : col - 1;
- break;
- case 200:
- case 210:
- col = (!col) ? ap->ncols - 1 : col - 1;
- row = (!row) ? ap->nrows - 1 : row - 1;
- break;
- case 240:
- row = (!row) ? ap->nrows - 1 : row - 1;
- break;
- case 270:
- case 280:
- if (!row)
- row = ap->nrows - 2;
- else if (row == 1)
- row = ap->nrows - 1;
- else
- row = row - 2;
- break;
- case 300:
- col = (col + 1 == ap->ncols) ? 0 : col + 1;
- if (!row)
- row = ap->nrows - 2;
- else if (row == 1)
- row = ap->nrows - 1;
- else
- row = row - 2;
- break;
- case 320:
- case 330:
- col = (col + 1 == ap->ncols) ? 0 : col + 1;
- row = (!row) ? ap->nrows - 1 : row - 1;
- break;
- default:
- (void) fprintf(stderr, "wrong direction %d\n", dir);
- }
- }
- }
- *pcol = col;
- *prow = row;
-}
-
-static void
-fillcell(ModeInfo * mi, GC gc, int col, int row)
-{
- antfarmstruct *ap = &antfarms[MI_SCREEN(mi)];
-
- if (ap->neighbors == 6) {
- int ccol = 2 * col + !(row & 1), crow = 2 * row;
-
- ap->shape.hexagon[0].x = ap->xb + ccol * ap->xs;
- ap->shape.hexagon[0].y = ap->yb + crow * ap->ys;
- if (ap->xs == 1 && ap->ys == 1)
- XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
- ap->shape.hexagon[0].x, ap->shape.hexagon[0].y, 1, 1);
- else
- XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
- ap->shape.hexagon, 6, Convex, CoordModePrevious);
- } else if (ap->neighbors == 4 || ap->neighbors == 8) {
- XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
- ap->xb + ap->xs * col, ap->yb + ap->ys * row,
- ap->xs - (ap->xs > 3), ap->ys - (ap->ys > 3));
- } else { /* TRI */
- int orient = (col + row) % 2; /* O left 1 right */
-
- ap->shape.triangle[orient][0].x = ap->xb + col * ap->xs;
- ap->shape.triangle[orient][0].y = ap->yb + row * ap->ys;
- if (ap->xs <= 3 || ap->ys <= 3)
- XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
- ((orient) ? -1 : 1) + ap->shape.triangle[orient][0].x,
- ap->shape.triangle[orient][0].y, 1, 1);
- else {
- if (orient)
- ap->shape.triangle[orient][0].x += (ap->xs / 2 - 1);
- else
- ap->shape.triangle[orient][0].x -= (ap->xs / 2 - 1);
- XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
- ap->shape.triangle[orient], 3, Convex, CoordModePrevious);
- }
- }
-}
-
-static void
-truchetcell(ModeInfo * mi, int col, int row, int truchetstate)
-{
- antfarmstruct *ap = &antfarms[MI_SCREEN(mi)];
-
- if (ap->neighbors == 6) {
-
- int ccol = 2 * col + !(row & 1), crow = 2 * row;
- int side;
- int fudge = 7; /* fudge because the hexagons are not exact */
- XPoint hex, hex2;
-
- if (ap->sharpturn) {
- hex.x = ap->xb + ccol * ap->xs - (int) ((double) ap->xs / 2.0) - 1;
- hex.y = ap->yb + crow * ap->ys - (int) ((double) ap->ys / 2.0) - 1;
- for (side = 0; side < 6; side++) {
- if (side > 0) {
- hex.x += ap->shape.hexagon[side].x;
- hex.y += ap->shape.hexagon[side].y;
- }
- if (truchetstate == side % 2)
- XDrawArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi),
- hex.x, hex.y, ap->xs, ap->ys,
- ((570 - (side * 60) + fudge) % 360) * 64, (120 - 2 * fudge) * 64);
- }
- } else {
-
- /* Very crude approx of Sqrt 3, so it will not cause drawing errors. */
- hex.x = ap->xb + ccol * ap->xs - (int) ((double) ap->xs * 1.6 / 2.0);
- hex.y = ap->yb + crow * ap->ys - (int) ((double) ap->ys * 1.6 / 2.0);
- for (side = 0; side < 6; side++) {
- if (side > 0) {
- hex.x += ap->shape.hexagon[side].x;
- hex.y += ap->shape.hexagon[side].y;
- }
- hex2.x = hex.x + ap->shape.hexagon[side + 1].x / 2;
- hex2.y = hex.y + ap->shape.hexagon[side + 1].y / 2;
- if (truchetstate == side % 3)
- /* Crude approx of 120 deg, so it will not cause drawing errors. */
- XDrawArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi),
- hex2.x, hex2.y,
- (int) ((double) ap->xs * 1.5), (int) ((double) ap->ys * 1.5),
- ((555 - (side * 60)) % 360) * 64, 90 * 64);
- }
- }
- } else if (ap->neighbors == 4) {
- if (truchetstate) {
- XDrawArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi),
- ap->xb + ap->xs * col - ap->xs / 2+ 1,
- ap->yb + ap->ys * row + ap->ys / 2 - 1,
- ap->xs - 2, ap->ys - 2,
- 0 * 64, 90 * 64);
- XDrawArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi),
- ap->xb + ap->xs * col + ap->xs / 2 - 1,
- ap->yb + ap->ys * row - ap->ys / 2 + 1,
- ap->xs - 2, ap->ys - 2,
- -90 * 64, -90 * 64);
- } else {
- XDrawArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi),
- ap->xb + ap->xs * col - ap->xs / 2 + 1,
- ap->yb + ap->ys * row - ap->ys / 2 + 1,
- ap->xs - 2, ap->ys - 2,
- 0 * 64, -90 * 64);
- XDrawArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi),
- ap->xb + ap->xs * col + ap->xs / 2 - 1,
- ap->yb + ap->ys * row + ap->ys / 2 - 1,
- ap->xs - 2, ap->ys - 2,
- 90 * 64, 90 * 64);
- }
- } else if (ap->neighbors == 3) {
- int orient = (col + row) % 2; /* O left 1 right */
- int side, ang;
- int fudge = 7; /* fudge because the triangles are not exact */
- XPoint tri;
-
- tri.x = ap->xb + col * ap->xs;
- tri.y = ap->yb + row * ap->ys;
- if (orient) {
- tri.x += (ap->xs / 2 - 1);
- } else {
- tri.x -= (ap->xs / 2 - 1);
- }
- for (side = 0; side < 3; side++) {
- if (side > 0) {
- tri.x += ap->shape.triangle[orient][side].x;
- tri.y += ap->shape.triangle[orient][side].y;
- }
- if (truchetstate == side % 3) {
- if (orient)
- ang = (510 - side * 120) % 360; /* Right */
- else
- ang = (690 - side * 120) % 360; /* Left */
- XDrawArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi),
- tri.x - ap->xs / 2, tri.y - 3 * ap->ys / 4,
- ap->xs, 3 * ap->ys / 2,
- (ang + fudge) * 64, (60 - 2 * fudge) * 64);
- }
- }
- }
-}
-
-static void
-drawcell(ModeInfo * mi, int col, int row, unsigned char color)
-{
- antfarmstruct *ap = &antfarms[MI_SCREEN(mi)];
- GC gc;
-
- if (!color) {
- XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi));
- gc = MI_GC(mi);
- } else if (MI_NPIXELS(mi) > 2) {
- XSetForeground(MI_DISPLAY(mi), MI_GC(mi),
- MI_PIXEL(mi, ap->colors[color - 1]));
- gc = MI_GC(mi);
- } else {
- XGCValues gcv;
-
- gcv.stipple = ap->pixmaps[color - 1];
- gcv.foreground = MI_WHITE_PIXEL(mi);
- gcv.background = MI_BLACK_PIXEL(mi);
- XChangeGC(MI_DISPLAY(mi), ap->stippledGC,
- GCStipple | GCForeground | GCBackground, &gcv);
- gc = ap->stippledGC;
- }
- fillcell(mi, gc, col, row);
-}
-
-static void
-drawtruchet(ModeInfo * mi, int col, int row,
- unsigned char color, unsigned char truchetstate)
-{
- antfarmstruct *ap = &antfarms[MI_SCREEN(mi)];
-
- if (!color)
- XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WHITE_PIXEL(mi));
- else if (MI_NPIXELS(mi) > 2 || color > ap->ncolors / 2)
- XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi));
- else
- XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WHITE_PIXEL(mi));
- truchetcell(mi, col, row, truchetstate);
-}
-
-static void
-draw_anant(ModeInfo * mi, int col, int row)
-{
- XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WHITE_PIXEL(mi));
- fillcell(mi, MI_GC(mi), col, row);
-#if 0 /* Can not see eyes */
- {
- antfarmstruct *ap = &antfarms[MI_SCREEN(mi)];
- Display *display = MI_DISPLAY(mi);
- Window window = MI_WINDOW(mi);
-
- if (ap->xs > 2 && ap->ys > 2) { /* Draw Eyes */
-
- XSetForeground(display, MI_GC(mi), MI_BLACK_PIXEL(mi));
- switch (direction) {
- case 0:
- XDrawPoint(display, window, MI_GC(mi),
- ap->xb + ap->xs - 1, ap->yb + 1);
- XDrawPoint(display, window, MI_GC(mi),
- ap->xb + ap->xs - 1, ap->yb + ap->ys - 2);
- break;
- case 180:
- XDrawPoint(display, window, MI_GC(mi), ap->xb, ap->yb + 1);
- XDrawPoint(display, window, MI_GC(mi), ap->xb, ap->yb + ap->ys - 2);
- break;
- if (neighbors == 4) {
- case 90:
- XDrawPoint(display, window, MI_GC(mi), ap->xb + 1, ap->yb);
- XDrawPoint(display, window, MI_GC(mi),
- ap->xb + ap->xs - 2, ap->yb);
- break;
- case 270:
- XDrawPoint(display, window, MI_GC(mi),
- ap->xb + 1, ap->yb + ap->ys - 1);
- XDrawPoint(display, window, MI_GC(mi),
- ap->xb + ap->xs - 2, ap->yb + ap->ys - 1);
- break;
- } /* else BEE */
- default:
- }
- }
- }
-#endif
-}
-
-#if 0
-static void
-RandomSoup(mi)
- ModeInfo *mi;
-{
- antfarmstruct *ap = &antfarms[MI_SCREEN(mi)];
- int row, col, mrow = 0;
-
- for (row = 0; row < ap->nrows; ++row) {
- for (col = 0; col < ap->ncols; ++col) {
- ap->old[col + mrow] = (unsigned char) NRAND((int) ap->ncolors);
- drawcell(mi, col, row, ap->old[col + mrow]);
- }
- mrow += ap->nrows;
- }
-}
-
-#endif
-
-static short
-fromTableDirection(unsigned char dir, int neighbors)
-{
- switch (dir) {
- case FS:
- return 0;
- case TRS:
- return (ANGLES / neighbors);
- case THRS:
- return (ANGLES / 2 - ANGLES / neighbors);
- case TBS:
- return (ANGLES / 2);
- case THLS:
- return (ANGLES / 2 + ANGLES / neighbors);
- case TLS:
- return (ANGLES - ANGLES / neighbors);
- case SF:
- return ANGLES;
- case STR:
- return (ANGLES + ANGLES / neighbors);
- case STHR:
- return (3 * ANGLES / 2 - ANGLES / neighbors);
- case STB:
- return (3 * ANGLES / 2);
- case STHL:
- return (3 * ANGLES / 2 + ANGLES / neighbors);
- case STL:
- return (2 * ANGLES - ANGLES / neighbors);
- default:
- (void) fprintf(stderr, "wrong direction %d\n", dir);
- }
- return -1;
-}
-
-static void
-getTable(ModeInfo * mi, int i)
-{
- antfarmstruct *ap = &antfarms[MI_SCREEN(mi)];
- int j, total;
- unsigned char *patptr;
-
- patptr = &tables[i][0];
- ap->ncolors = *patptr++;
- ap->nstates = *patptr++;
- total = ap->ncolors * ap->nstates;
- if (MI_IS_VERBOSE(mi))
- (void) fprintf(stdout,
- "ants %d, neighbors %d, table number %d, colors %d, states %d\n",
- ap->n, ap->neighbors, i, ap->ncolors, ap->nstates);
- for (j = 0; j < total; j++) {
- ap->machine[j].color = *patptr++;
- if (ap->sharpturn && ap->neighbors > 4 && !(ap->neighbors % 2)) {
- int k = *patptr++;
-
- switch (k) {
- case TRS:
- k = THRS;
- break;
- case THRS:
- k = TRS;
- break;
- case THLS:
- k = TLS;
- break;
- case TLS:
- k = THLS;
- break;
- case STR:
- k = STHR;
- break;
- case STHR:
- k = STR;
- break;
- case STHL:
- k = STL;
- break;
- case STL:
- k = STHL;
- break;
- default:
- break;
- }
- ap->machine[j].direction = fromTableDirection(k, ap->neighbors);
- } else {
- ap->machine[j].direction = fromTableDirection(*patptr++, ap->neighbors);
- }
- ap->machine[j].next = *patptr++;
- }
- ap->truchet = False;
-}
-
-static void
-getTurk(ModeInfo * mi, int i)
-{
- antfarmstruct *ap = &antfarms[MI_SCREEN(mi)];
- int power2, j, number, total;
-
- /* To force a number, say <i = 2;> has i + 2 (or 4) digits in binary */
- power2 = 1 << (i + 1);
- /* Dont want numbers which in binary are all 1's. */
- number = NRAND(power2 - 1) + power2;
- /* To force a particular number, say <number = 10;> */
-
- ap->ncolors = i + 2;
- ap->nstates = 1;
- total = ap->ncolors * ap->nstates;
- for (j = 0; j < total; j++) {
- ap->machine[j].color = (j + 1) % total;
- if (ap->sharpturn && ap->neighbors > 4 && !(ap->neighbors % 2)) {
- ap->machine[j].direction = (power2 & number) ?
- fromTableDirection(THRS, ap->neighbors) :
- fromTableDirection(THLS, ap->neighbors);
- } else {
- ap->machine[j].direction = (power2 & number) ?
- fromTableDirection(TRS, ap->neighbors) :
- fromTableDirection(TLS, ap->neighbors);
- }
- ap->machine[j].next = 0;
- power2 >>= 1;
- }
- ap->truchet = (ap->truchet && ap->xs > 2 && ap->ys > 2 &&
- (ap->neighbors == 3 || ap->neighbors == 4 || ap->neighbors == 6));
- if (MI_IS_VERBOSE(mi))
- (void) fprintf(stdout,
- "ants %d, neighbors %d, Turk's number %d, colors %d\n",
- ap->n, ap->neighbors, number, ap->ncolors);
-}
-
-void
-init_ant(ModeInfo * mi)
-{
- Display *display = MI_DISPLAY(mi);
- Window window = MI_WINDOW(mi);
- int size = MI_SIZE(mi);
- antfarmstruct *ap;
- int col, row, dir;
- long i;
-
- /* jwz sez: small sizes look like crap */
- if (size < 0)
- size = NRAND(-size)+1;
- if (size < 5)
- size += 5;
-
- if (antfarms == NULL) {
- if ((antfarms = (antfarmstruct *) calloc(MI_NUM_SCREENS(mi),
- sizeof (antfarmstruct))) == NULL)
- return;
- }
- ap = &antfarms[MI_SCREEN(mi)];
- ap->redrawing = 0;
- if (MI_NPIXELS(mi) <= 2) {
- if (ap->stippledGC == None) {
- XGCValues gcv;
-
- gcv.fill_style = FillOpaqueStippled;
- ap->stippledGC = XCreateGC(display, window, GCFillStyle, &gcv);
- }
- if (ap->init_bits == 0) {
- for (i = 1; i < NUMSTIPPLES; i++)
- ANTBITS(stipples[i], STIPPLESIZE, STIPPLESIZE);
- }
- }
- ap->generation = 0;
- ap->n = MI_COUNT(mi);
- if (ap->n < -MINANTS) {
- /* if ap->n is random ... the size can change */
- if (ap->ants != NULL) {
- (void) free((void *) ap->ants);
- ap->ants = NULL;
- }
- ap->n = NRAND(-ap->n - MINANTS + 1) + MINANTS;
- } else if (ap->n < MINANTS)
- ap->n = MINANTS;
-
- ap->width = MI_WIDTH(mi);
- ap->height = MI_HEIGHT(mi);
-
- if (neighbors == 8 || neighbors == 9 || neighbors == 12)
- ap->neighbors = neighbors; /* Discourage but not deny use... */
- else
- for (i = 0; i < NEIGHBORKINDS; i++) {
- if (neighbors == plots[i]) {
- ap->neighbors = plots[i];
- break;
- }
- if (i == NEIGHBORKINDS - 1) {
- ap->neighbors = plots[NRAND(NEIGHBORKINDS)];
- break;
- }
- }
-
- if (ap->neighbors == 6) {
- int nccols, ncrows;
-
- if (ap->width < 2)
- ap->width = 2;
- if (ap->height < 4)
- ap->height = 4;
- if (size < -MINSIZE) {
- ap->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(ap->width, ap->height) /
- MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
- if (ap->ys < MINRANDOMSIZE)
- ap->ys = MIN(MINRANDOMSIZE,
- MAX(MINSIZE, MIN(ap->width, ap->height) / MINGRIDSIZE));
- } else if (size < MINSIZE) {
- if (!size)
- ap->ys = MAX(MINSIZE, MIN(ap->width, ap->height) / MINGRIDSIZE);
- else
- ap->ys = MINSIZE;
- } else
- ap->ys = MIN(size, MAX(MINSIZE, MIN(ap->width, ap->height) /
- MINGRIDSIZE));
- ap->xs = ap->ys;
- nccols = MAX(ap->width / ap->xs - 2, 2);
- ncrows = MAX(ap->height / ap->ys - 1, 2);
- ap->ncols = nccols / 2;
- ap->nrows = 2 * (ncrows / 4);
- ap->xb = (ap->width - ap->xs * nccols) / 2 + ap->xs / 2;
- ap->yb = (ap->height - ap->ys * (ncrows / 2) * 2) / 2 + ap->ys;
- for (i = 0; i < 6; i++) {
- ap->shape.hexagon[i].x = (ap->xs - 1) * hexagonUnit[i].x;
- ap->shape.hexagon[i].y = ((ap->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3;
- }
- /* Avoid array bounds read of hexagonUnit */
- ap->shape.hexagon[6].x = 0;
- ap->shape.hexagon[6].y = 0;
- } else if (ap->neighbors == 4 || ap->neighbors == 8) {
- if (size < -MINSIZE) {
- ap->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(ap->width, ap->height) /
- MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
- if (ap->ys < MINRANDOMSIZE)
- ap->ys = MIN(MINRANDOMSIZE,
- MAX(MINSIZE, MIN(ap->width, ap->height) / MINGRIDSIZE));
- } else if (size < MINSIZE) {
- if (!size)
- ap->ys = MAX(MINSIZE, MIN(ap->width, ap->height) / MINGRIDSIZE);
- else
- ap->ys = MINSIZE;
- } else
- ap->ys = MIN(size, MAX(MINSIZE, MIN(ap->width, ap->height) /
- MINGRIDSIZE));
- ap->xs = ap->ys;
- ap->ncols = MAX(ap->width / ap->xs, 2);
- ap->nrows = MAX(ap->height / ap->ys, 2);
- ap->xb = (ap->width - ap->xs * ap->ncols) / 2;
- ap->yb = (ap->height - ap->ys * ap->nrows) / 2;
- } else { /* TRI */
- int orient;
-
- if (ap->width < 2)
- ap->width = 2;
- if (ap->height < 2)
- ap->height = 2;
- if (size < -MINSIZE) {
- ap->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(ap->width, ap->height) /
- MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
- if (ap->ys < MINRANDOMSIZE)
- ap->ys = MIN(MINRANDOMSIZE,
- MAX(MINSIZE, MIN(ap->width, ap->height) / MINGRIDSIZE));
- } else if (size < MINSIZE) {
- if (!size)
- ap->ys = MAX(MINSIZE, MIN(ap->width, ap->height) / MINGRIDSIZE);
- else
- ap->ys = MINSIZE;
- } else
- ap->ys = MIN(size, MAX(MINSIZE, MIN(ap->width, ap->height) /
- MINGRIDSIZE));
- ap->xs = (int) (1.52 * ap->ys);
- ap->ncols = (MAX(ap->width / ap->xs - 1, 2) / 2) * 2;
- ap->nrows = (MAX(ap->height / ap->ys - 1, 2) / 2) * 2;
- ap->xb = (ap->width - ap->xs * ap->ncols) / 2 + ap->xs / 2;
- ap->yb = (ap->height - ap->ys * ap->nrows) / 2 + ap->ys;
- for (orient = 0; orient < 2; orient++) {
- for (i = 0; i < 3; i++) {
- ap->shape.triangle[orient][i].x =
- (ap->xs - 2) * triangleUnit[orient][i].x;
- ap->shape.triangle[orient][i].y =
- (ap->ys - 2) * triangleUnit[orient][i].y;
- }
- /* Avoid array bounds read of triangleUnit */
- ap->shape.triangle[orient][3].x = 0;
- ap->shape.triangle[orient][3].y = 0;
- }
- }
-
- XSetLineAttributes(display, MI_GC(mi), 1, LineSolid, CapNotLast, JoinMiter);
- MI_CLEARWINDOW(mi);
- ap->painted = False;
-
- if (MI_IS_FULLRANDOM(mi)) {
- ap->truchet = (Bool) (LRAND() & 1);
- ap->sharpturn = (Bool) (LRAND() & 1);
- } else {
- ap->truchet = truchet;
- ap->sharpturn = sharpturn;
- }
- /* Exclude odd # of neighbors, stepping forward not defined */
- if (!NRAND(NUMSTIPPLES) && ((ap->neighbors + 1) % 2)) {
- getTable(mi, (int) (NRAND(NTABLES)));
- } else
- getTurk(mi, (int) (NRAND(NUMSTIPPLES - 1)));
- if (MI_NPIXELS(mi) > 2)
- for (i = 0; i < (int) ap->ncolors - 1; i++)
- ap->colors[i] = (unsigned char) (NRAND(MI_NPIXELS(mi)) +
- i * MI_NPIXELS(mi)) / ((int) (ap->ncolors - 1));
- if (ap->ants == NULL)
- ap->ants = (antstruct *) malloc(ap->n * sizeof (antstruct));
- if (ap->tape != NULL)
- (void) free((void *) ap->tape);
- ap->tape = (unsigned char *)
- calloc(ap->ncols * ap->nrows, sizeof (unsigned char));
-
- if (ap->truchet_state != NULL)
- (void) free((void *) ap->truchet_state);
- ap->truchet_state = (unsigned char *)
- calloc(ap->ncols * ap->nrows, sizeof (unsigned char));
-
- col = ap->ncols / 2;
- row = ap->nrows / 2;
- dir = NRAND(ap->neighbors) * ANGLES / ap->neighbors;
- /* Have them all start in the same spot, why not? */
- for (i = 0; i < ap->n; i++) {
- ap->ants[i].col = col;
- ap->ants[i].row = row;
- ap->ants[i].direction = dir;
- ap->ants[i].state = 0;
- }
- draw_anant(mi, col, row);
-}
-
-void
-draw_ant(ModeInfo * mi)
-{
- antfarmstruct *ap = &antfarms[MI_SCREEN(mi)];
- antstruct *anant;
- statestruct *status;
- int i, state_pos, tape_pos;
- unsigned char color;
- short chg_dir, old_dir;
-
- MI_IS_DRAWN(mi) = True;
-
- ap->painted = True;
- for (i = 0; i < ap->n; i++) {
- anant = &ap->ants[i];
- tape_pos = anant->col + anant->row * ap->ncols;
- color = ap->tape[tape_pos]; /* read tape */
- state_pos = color + anant->state * ap->ncolors;
- status = &(ap->machine[state_pos]);
- drawcell(mi, anant->col, anant->row, status->color);
- ap->tape[tape_pos] = status->color; /* write on tape */
-
- /* Find direction of Bees or Ants. */
- /* Translate relative direction to actual direction */
- old_dir = anant->direction;
- chg_dir = (2 * ANGLES - status->direction) % ANGLES;
- anant->direction = (chg_dir + old_dir) % ANGLES;
- if (ap->truchet) {
- int a = 0, b;
-
- if (ap->neighbors == 6) {
- if (ap->sharpturn) {
- a = (chg_dir / 120 == 2);
- drawtruchet(mi, anant->col, anant->row, status->color, a);
- } else {
- a = (old_dir / 60) % 3;
- b = (anant->direction / 60) % 3;
- a = (a + b + 1) % 3;
- drawtruchet(mi, anant->col, anant->row, status->color, a);
- }
- } else if (ap->neighbors == 4) {
- a = old_dir / 180;
- b = anant->direction / 180;
- a = ((a && !b) || (b && !a));
- drawtruchet(mi, anant->col, anant->row, status->color, a);
- } else if (ap->neighbors == 3) {
- if (chg_dir == 240)
- a = (2 + anant->direction / 120) % 3;
- else
- a = (1 + anant->direction / 120) % 3;
- drawtruchet(mi, anant->col, anant->row, status->color, a);
- }
- ap->truchet_state[tape_pos] = a + 1;
- }
- anant->state = status->next;
-
- /* If edge than wrap it */
- old_dir = ((status->direction < ANGLES) ? anant->direction : old_dir);
- position_of_neighbor(ap, old_dir, &(anant->col), &(anant->row));
- draw_anant(mi, anant->col, anant->row);
- }
- if (++ap->generation > MI_CYCLES(mi)) {
-#ifdef STANDALONE
- erase_full_window(MI_DISPLAY(mi), MI_WINDOW(mi));
-#endif
- init_ant(mi);
- }
- if (ap->redrawing) {
- for (i = 0; i < REDRAWSTEP; i++) {
- if (ap->tape[ap->redrawpos] ||
- (ap->truchet && ap->truchet_state[ap->redrawpos])) {
- drawcell(mi, ap->redrawpos % ap->ncols, ap->redrawpos / ap->ncols,
- ap->tape[ap->redrawpos]);
- if (ap->truchet)
- drawtruchet(mi, ap->redrawpos % ap->ncols, ap->redrawpos / ap->ncols,
- ap->tape[ap->redrawpos],
- ap->truchet_state[ap->redrawpos] - 1);
- }
- if (++(ap->redrawpos) >= ap->ncols * ap->nrows) {
- ap->redrawing = 0;
- break;
- }
- }
- }
-}
-
-void
-release_ant(ModeInfo * mi)
-{
- if (antfarms != NULL) {
- int screen;
-
- for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
- antfarmstruct *ap = &antfarms[screen];
- int shade;
-
- if (ap->stippledGC != None) {
- XFreeGC(MI_DISPLAY(mi), ap->stippledGC);
- }
- for (shade = 0; shade < ap->init_bits; shade++)
- XFreePixmap(MI_DISPLAY(mi), ap->pixmaps[shade]);
- if (ap->tape != NULL)
- (void) free((void *) ap->tape);
- if (ap->ants != NULL)
- (void) free((void *) ap->ants);
- if (ap->truchet_state != NULL)
- (void) free((void *) ap->truchet_state);
- }
- (void) free((void *) antfarms);
- antfarms = NULL;
- }
-}
-
-void
-refresh_ant(ModeInfo * mi)
-{
- antfarmstruct *ap = &antfarms[MI_SCREEN(mi)];
-
- if (ap->painted) {
- MI_CLEARWINDOW(mi);
- ap->redrawing = 1;
- ap->redrawpos = 0;
- }
-}