http://ftp.aanet.ru/pub/Linux/X11/apps/xscreensaver-2.31.tar.gz
[xscreensaver] / hacks / ant.c
1 /* -*- Mode: C; tab-width: 4 -*- */
2 /*-
3  * ant --- Chris Langton's generalized turing machine ants (also known
4  *         as Greg Turk's turmites) whose tape is the screen
5  */
6
7 #if !defined( lint ) && !defined( SABER )
8 static const char sccsid[] = "@(#)ant.c 4.11 98/06/18 xlockmore";
9
10 #endif
11
12 /*-
13  * Copyright (c) 1995 by David Bagley.
14  *
15  * Permission to use, copy, modify, and distribute this software and its
16  * documentation for any purpose and without fee is hereby granted,
17  * provided that the above copyright notice appear in all copies and that
18  * both that copyright notice and this permission notice appear in
19  * supporting documentation.
20  *
21  * This file is provided AS IS with no warranties of any kind.  The author
22  * shall have no liability with respect to the infringement of copyrights,
23  * trade secrets or any patents by this file or any part thereof.  In no
24  * event will the author be liable for any lost revenue or profits or
25  * other special, indirect and consequential damages.
26  *
27  * Revision History:
28  * 10-May-97: Compatible with xscreensaver
29  * 16-Apr-97: -neighbors 3 and 8 added
30  * 01-Jan-97: Updated ant.c to handle more kinds of ants.  Thanks to
31  *            J Austin David <Austin.David@tlogic.com>.  Check it out in
32  *            java at http://havoc.gtf.gatech.edu/austin  He thought up the
33  *            new Ladder ant.
34  * 04-Apr-96: -neighbors 6 runtime-time option added for hexagonal ants
35  *            (bees), coded from an idea of Jim Propp's in Science News,
36  *            Oct 28, 1995 VOL. 148 page 287
37  * 20-Sep-95: Memory leak in ant fixed.  Now random colors.
38  * 05-Sep-95: Coded from A.K. Dewdney's "Computer Recreations", Scientific
39  *            American Magazine" Sep 1989 pp 180-183, Mar 1990 p 121
40  *            Also used Ian Stewart's Mathematical Recreations, Scientific
41  *            American Jul 1994 pp 104-107
42  *            also used demon.c and life.c as a guide.
43  */
44
45 /*-
46   Species Grid     Number of Neigbors
47   ------- ----     ------------------
48   Ants    Square   4 (or 8)
49   Bees    Hexagon  6
50   Bees    Triangle 3 (or 9, 12)
51
52   Neighbors 6 and neighbors 3 produce the same Turk ants.
53 */
54
55 #ifdef STANDALONE
56 # define PROGCLASS "Ant"
57 # define HACK_INIT init_ant
58 # define HACK_DRAW draw_ant
59 # define ant_opts xlockmore_opts
60 # define DEFAULTS       "*delay:   1000 \n"             \
61                                         "*count:  -3 \n"                \
62                                         "*cycles:  40000 \n"    \
63                                         "*size:   -12 \n"               \
64                                         "*ncolors: 64 \n"               \
65                                         "*neighbors: 0 \n"              \
66                                         "*sharpturn: False \n"
67 # include "xlockmore.h"         /* in xscreensaver distribution */
68 # include "erase.h"
69 #else /* STANDALONE */
70 # include "xlock.h"             /* in xlockmore distribution */
71 # include "automata.h"
72 #endif /* STANDALONE */
73
74 /*-
75  * neighbors of 0 randomizes it between 3, 4 and 6.
76  * 8, 9 12 are available also but not recommended.
77  */
78
79 #ifdef STANDALONE
80 static int neighbors;
81 #else
82 extern int  neighbors;
83 #endif /* !STANDALONE */
84
85 #define DEF_TRUCHET  "False"
86 #define DEF_SHARPTURN  "False"
87
88 static Bool truchet;
89 static Bool sharpturn;
90
91 static XrmOptionDescRec opts[] =
92 {
93         {"-truchet", ".ant.truchet", XrmoptionNoArg, (caddr_t) "on"},
94         {"+truchet", ".ant.truchet", XrmoptionNoArg, (caddr_t) "off"},
95         {"-sharpturn", ".ant.sharpturn", XrmoptionNoArg, (caddr_t) "on"},
96         {"+sharpturn", ".ant.sharpturn", XrmoptionNoArg, (caddr_t) "off"},
97
98 #ifdef STANDALONE
99         {"-neighbors", ".ant.neighbors", XrmoptionSepArg, (caddr_t) 0},
100         {"+neighbors", ".ant.neighbors", XrmoptionSepArg, (caddr_t) 0}
101 #endif /* STANDALONE */
102
103 };
104 static argtype vars[] =
105 {
106         {(caddr_t *) & truchet, "truchet", "Truchet", DEF_TRUCHET, t_Bool},
107    {(caddr_t *) & sharpturn, "sharpturn", "SharpTurn", DEF_SHARPTURN, t_Bool},
108 #ifdef STANDALONE
109         {(caddr_t *) & neighbors, "neighbors", "Neighbors", 0, t_Int}
110 #endif /* STANDALONE */
111 };
112 static OptionStruct desc[] =
113 {
114         {"-/+truchet", "turn on/off Truchet lines"},
115         {"-/+sharpturn", "turn on/off sharp turns (6 or 12 neighbors only)"}
116 };
117
118 ModeSpecOpt ant_opts =
119 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
120
121 #ifdef USE_MODULES
122 ModStruct   ant_description =
123 {"ant", "init_ant", "draw_ant", "release_ant",
124  "refresh_ant", "init_ant", NULL, &ant_opts,
125  1000, -3, 40000, -12, 64, 1.0, "",
126  "Shows Langton's and Turk's generalized ants", 0, NULL};
127
128 #endif
129
130 #define ANTBITS(n,w,h)\
131   ap->pixmaps[ap->init_bits++]=\
132   XCreatePixmapFromBitmapData(display,window,(char *)n,w,h,1,0,1)
133
134 /* If you change the table you may have to change the following 2 constants */
135 #define STATES 2
136 #define MINANTS 1
137 #define REDRAWSTEP 2000         /* How much tape to draw per cycle */
138 #define MINGRIDSIZE 24
139 #define MINSIZE 1
140 #define MINRANDOMSIZE 5
141 #define ANGLES 360
142
143 #ifdef STANDALONE
144
145 #define NUMSTIPPLES 11
146 #define STIPPLESIZE 8
147
148 static XPoint hexagonUnit[6] =
149 {
150         {0, 0},
151         {1, 1},
152         {0, 2},
153         {-1, 1},
154         {-1, -1},
155         {0, -2}
156 };
157
158 static XPoint triangleUnit[2][3] =
159 {
160         {
161                 {0, 0},
162                 {1, -1},
163                 {0, 2}
164         },
165         {
166                 {0, 0},
167                 {-1, 1},
168                 {0, -2}
169         }
170 };
171
172
173 static unsigned char stipples[NUMSTIPPLES][STIPPLESIZE] =
174 {
175         {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},       /* white */
176         {0x11, 0x22, 0x11, 0x22, 0x11, 0x22, 0x11, 0x22},       /* grey+white | stripe */
177         {0x00, 0x66, 0x66, 0x00, 0x00, 0x66, 0x66, 0x00},       /* spots */
178         {0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11},       /* lt. / stripe */
179         {0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66},       /* | bars */
180         {0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa},       /* 50% grey */
181         {0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00},       /* - bars */
182         {0xee, 0xdd, 0xbb, 0x77, 0xee, 0xdd, 0xbb, 0x77},       /* dark \ stripe */
183         {0xff, 0x99, 0x99, 0xff, 0xff, 0x99, 0x99, 0xff},       /* spots */
184         {0xaa, 0xff, 0xff, 0x55, 0xaa, 0xff, 0xff, 0x55},       /* black+grey - stripe */
185         {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}        /* black */
186 };
187
188 #endif /* STANDALONE */
189
190 typedef struct {
191         unsigned char color;
192         short       direction;
193         unsigned char next;
194 } statestruct;
195
196 typedef struct {
197         int         col, row;
198         short       direction;
199         unsigned char state;
200 } antstruct;
201
202 typedef struct {
203         Bool        painted;
204         int         neighbors;
205         int         generation;
206         int         xs, ys;
207         int         xb, yb;
208         int         nrows, ncols;
209         int         width, height;
210         unsigned char ncolors, nstates;
211         int         n;
212         int         redrawing, redrawpos;
213         int         truchet;    /* Only for Turk modes */
214         int         sharpturn;  /* Only for even neighbors > 4 (i.e. 6 and 12) */
215         statestruct machine[NUMSTIPPLES * STATES];
216         unsigned char *tape;
217         unsigned char *truchet_state;
218         antstruct  *ants;
219         int         init_bits;
220         unsigned char colors[NUMSTIPPLES - 1];
221         GC          stippledGC;
222         Pixmap      pixmaps[NUMSTIPPLES - 1];
223         union {
224                 XPoint      hexagon[7];         /* Need more than 6 for truchet */
225                 XPoint      triangle[2][4];     /* Need more than 3 for truchet */
226         } shape;
227 } antfarmstruct;
228
229 static char plots[] =
230 {3,
231 #if 1                           /* Without this... this mode is misnamed... */
232  4,
233 #endif
234  6};                            /* Neighborhoods, 8 just makes a mess */
235
236 #define NEIGHBORKINDS (long) (sizeof plots / sizeof *plots)
237
238 /* Relative ant moves */
239 #define FS 0                    /* Step */
240 #define TRS 1                   /* Turn right, then step */
241 #define THRS 2                  /* Turn hard right, then step */
242 #define TBS 3                   /* Turn back, then step */
243 #define THLS 4                  /* Turn hard left, then step */
244 #define TLS 5                   /* Turn left, then step */
245 #define SF 6                    /* Step */
246 #define STR 7                   /* Step then turn right */
247 #define STHR 8                  /* Step then turn hard right */
248 #define STB 9                   /* Step then turn back */
249 #define STHL 10                 /* Step then turn hard left */
250 #define STL 11                  /* Step then turn left */
251
252 static antfarmstruct *antfarms = NULL;
253
254 /* LANGTON'S ANT (10) Chaotic after 500, Builder after 10,000 (104p) */
255 /* TURK'S 100 ANT Always chaotic?, tested past 150,000,000 */
256 /* TURK'S 101 ANT Always chaotic? */
257 /* TURK'S 110 ANT Builder at 150 (18p) */
258 /* TURK'S 1000 ANT Always chaotic? */
259 /* TURK'S 1100 SYMMETRIC ANT  all even run 1's and 0's are symmetric */
260 /* other examples 1001, 110011, 110000, 1001101 */
261 /* TURK'S 1101 ANT Builder after 250,000 (388p) */
262 /* Once saw a chess horse type builder (i.e. non-45 degree builder) */
263
264 /* BEE ONLY */
265 /* All alternating 10 appear symmetric, no proof (i.e. 10, 1010, etc) */
266 /* Even runs of 0's and 1's are also symmetric */
267 /* I have seen Hexagonal builders but they are more rare. */
268
269 static unsigned char tables[][3 * NUMSTIPPLES * STATES + 2] =
270 {
271 #if 0
272   /* Here just so you can figure out notation */
273         {                       /* Langton's ant */
274                 2, 1,
275                 1, TLS, 0, 0, TRS, 0
276         },
277 #else
278   /* First 2 numbers are the size (ncolors, nstates) */
279         {                       /* LADDER BUILDER */
280                 4, 1,
281                 1, STR, 0, 2, STL, 0, 3, TRS, 0, 0, TLS, 0
282         },
283         {                       /* SPIRALING PATTERN */
284                 2, 2,
285                 1, TLS, 0, 0, FS, 1,
286                 1, TRS, 0, 1, TRS, 0
287         },
288         {                       /* SQUARE (HEXAGON) BUILDER */
289                 2, 2,
290                 1, TLS, 0, 0, FS, 1,
291                 0, TRS, 0, 1, TRS, 0
292         },
293 #endif
294 };
295
296 #define NTABLES   (sizeof tables / sizeof tables[0])
297
298 static void
299 position_of_neighbor(antfarmstruct * ap, int dir, int *pcol, int *prow)
300 {
301         int         col = *pcol, row = *prow;
302
303         if (ap->neighbors == 6) {
304                 switch (dir) {
305                         case 0:
306                                 col = (col + 1 == ap->ncols) ? 0 : col + 1;
307                                 break;
308                         case 60:
309                                 if (!(row & 1))
310                                         col = (col + 1 == ap->ncols) ? 0 : col + 1;
311                                 row = (!row) ? ap->nrows - 1 : row - 1;
312                                 break;
313                         case 120:
314                                 if (row & 1)
315                                         col = (!col) ? ap->ncols - 1 : col - 1;
316                                 row = (!row) ? ap->nrows - 1 : row - 1;
317                                 break;
318                         case 180:
319                                 col = (!col) ? ap->ncols - 1 : col - 1;
320                                 break;
321                         case 240:
322                                 if (row & 1)
323                                         col = (!col) ? ap->ncols - 1 : col - 1;
324                                 row = (row + 1 == ap->nrows) ? 0 : row + 1;
325                                 break;
326                         case 300:
327                                 if (!(row & 1))
328                                         col = (col + 1 == ap->ncols) ? 0 : col + 1;
329                                 row = (row + 1 == ap->nrows) ? 0 : row + 1;
330                                 break;
331                         default:
332                                 (void) fprintf(stderr, "wrong direction %d\n", dir);
333                 }
334         } else if (ap->neighbors == 4 || ap->neighbors == 8) {
335                 switch (dir) {
336                         case 0:
337                                 col = (col + 1 == ap->ncols) ? 0 : col + 1;
338                                 break;
339                         case 45:
340                                 col = (col + 1 == ap->ncols) ? 0 : col + 1;
341                                 row = (!row) ? ap->nrows - 1 : row - 1;
342                                 break;
343                         case 90:
344                                 row = (!row) ? ap->nrows - 1 : row - 1;
345                                 break;
346                         case 135:
347                                 col = (!col) ? ap->ncols - 1 : col - 1;
348                                 row = (!row) ? ap->nrows - 1 : row - 1;
349                                 break;
350                         case 180:
351                                 col = (!col) ? ap->ncols - 1 : col - 1;
352                                 break;
353                         case 225:
354                                 col = (!col) ? ap->ncols - 1 : col - 1;
355                                 row = (row + 1 == ap->nrows) ? 0 : row + 1;
356                                 break;
357                         case 270:
358                                 row = (row + 1 == ap->nrows) ? 0 : row + 1;
359                                 break;
360                         case 315:
361                                 col = (col + 1 == ap->ncols) ? 0 : col + 1;
362                                 row = (row + 1 == ap->nrows) ? 0 : row + 1;
363                                 break;
364                         default:
365                                 (void) fprintf(stderr, "wrong direction %d\n", dir);
366                 }
367         } else {                /* TRI */
368                 if ((col + row) % 2) {  /* right */
369                         switch (dir) {
370                                 case 0:
371                                         col = (!col) ? ap->ncols - 1 : col - 1;
372                                         break;
373                                 case 30:
374                                 case 40:
375                                         col = (!col) ? ap->ncols - 1 : col - 1;
376                                         row = (!row) ? ap->nrows - 1 : row - 1;
377                                         break;
378                                 case 60:
379                                         col = (!col) ? ap->ncols - 1 : col - 1;
380                                         if (!row)
381                                                 row = ap->nrows - 2;
382                                         else if (!(row - 1))
383                                                 row = ap->nrows - 1;
384                                         else
385                                                 row = row - 2;
386                                         break;
387                                 case 80:
388                                 case 90:
389                                         if (!row)
390                                                 row = ap->nrows - 2;
391                                         else if (!(row - 1))
392                                                 row = ap->nrows - 1;
393                                         else
394                                                 row = row - 2;
395                                         break;
396                                 case 120:
397                                         row = (!row) ? ap->nrows - 1 : row - 1;
398                                         break;
399                                 case 150:
400                                 case 160:
401                                         col = (col + 1 == ap->ncols) ? 0 : col + 1;
402                                         row = (!row) ? ap->nrows - 1 : row - 1;
403                                         break;
404                                 case 180:
405                                         col = (col + 1 == ap->ncols) ? 0 : col + 1;
406                                         break;
407                                 case 200:
408                                 case 210:
409                                         col = (col + 1 == ap->ncols) ? 0 : col + 1;
410                                         row = (row + 1 == ap->nrows) ? 0 : row + 1;
411                                         break;
412                                 case 240:
413                                         row = (row + 1 == ap->nrows) ? 0 : row + 1;
414                                         break;
415                                 case 270:
416                                 case 280:
417                                         if (row + 1 == ap->nrows)
418                                                 row = 1;
419                                         else if (row + 2 == ap->nrows)
420                                                 row = 0;
421                                         else
422                                                 row = row + 2;
423                                         break;
424                                 case 300:
425                                         col = (!col) ? ap->ncols - 1 : col - 1;
426                                         if (row + 1 == ap->nrows)
427                                                 row = 1;
428                                         else if (row + 2 == ap->nrows)
429                                                 row = 0;
430                                         else
431                                                 row = row + 2;
432                                         break;
433                                 case 320:
434                                 case 330:
435                                         col = (!col) ? ap->ncols - 1 : col - 1;
436                                         row = (row + 1 == ap->nrows) ? 0 : row + 1;
437                                         break;
438                                 default:
439                                         (void) fprintf(stderr, "wrong direction %d\n", dir);
440                         }
441                 } else {        /* left */
442                         switch (dir) {
443                                 case 0:
444                                         col = (col + 1 == ap->ncols) ? 0 : col + 1;
445                                         break;
446                                 case 30:
447                                 case 40:
448                                         col = (col + 1 == ap->ncols) ? 0 : col + 1;
449                                         row = (row + 1 == ap->nrows) ? 0 : row + 1;
450                                         break;
451                                 case 60:
452                                         col = (col + 1 == ap->ncols) ? 0 : col + 1;
453                                         if (row + 1 == ap->nrows)
454                                                 row = 1;
455                                         else if (row + 2 == ap->nrows)
456                                                 row = 0;
457                                         else
458                                                 row = row + 2;
459                                         break;
460                                 case 80:
461                                 case 90:
462                                         if (row + 1 == ap->nrows)
463                                                 row = 1;
464                                         else if (row + 2 == ap->nrows)
465                                                 row = 0;
466                                         else
467                                                 row = row + 2;
468                                         break;
469                                 case 120:
470                                         row = (row + 1 == ap->nrows) ? 0 : row + 1;
471                                         break;
472                                 case 150:
473                                 case 160:
474                                         col = (!col) ? ap->ncols - 1 : col - 1;
475                                         row = (row + 1 == ap->nrows) ? 0 : row + 1;
476                                         break;
477                                 case 180:
478                                         col = (!col) ? ap->ncols - 1 : col - 1;
479                                         break;
480                                 case 200:
481                                 case 210:
482                                         col = (!col) ? ap->ncols - 1 : col - 1;
483                                         row = (!row) ? ap->nrows - 1 : row - 1;
484                                         break;
485                                 case 240:
486                                         row = (!row) ? ap->nrows - 1 : row - 1;
487                                         break;
488                                 case 270:
489                                 case 280:
490                                         if (!row)
491                                                 row = ap->nrows - 2;
492                                         else if (row == 1)
493                                                 row = ap->nrows - 1;
494                                         else
495                                                 row = row - 2;
496                                         break;
497                                 case 300:
498                                         col = (col + 1 == ap->ncols) ? 0 : col + 1;
499                                         if (!row)
500                                                 row = ap->nrows - 2;
501                                         else if (row == 1)
502                                                 row = ap->nrows - 1;
503                                         else
504                                                 row = row - 2;
505                                         break;
506                                 case 320:
507                                 case 330:
508                                         col = (col + 1 == ap->ncols) ? 0 : col + 1;
509                                         row = (!row) ? ap->nrows - 1 : row - 1;
510                                         break;
511                                 default:
512                                         (void) fprintf(stderr, "wrong direction %d\n", dir);
513                         }
514                 }
515         }
516         *pcol = col;
517         *prow = row;
518 }
519
520 static void
521 fillcell(ModeInfo * mi, GC gc, int col, int row)
522 {
523         antfarmstruct *ap = &antfarms[MI_SCREEN(mi)];
524
525         if (ap->neighbors == 6) {
526                 int         ccol = 2 * col + !(row & 1), crow = 2 * row;
527
528                 ap->shape.hexagon[0].x = ap->xb + ccol * ap->xs;
529                 ap->shape.hexagon[0].y = ap->yb + crow * ap->ys;
530                 if (ap->xs == 1 && ap->ys == 1)
531                         XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
532                         ap->shape.hexagon[0].x, ap->shape.hexagon[0].y, 1, 1);
533                 else
534                         XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
535                             ap->shape.hexagon, 6, Convex, CoordModePrevious);
536         } else if (ap->neighbors == 4 || ap->neighbors == 8) {
537                 XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
538                 ap->xb + ap->xs * col, ap->yb + ap->ys * row,
539                 ap->xs - (ap->xs > 3), ap->ys - (ap->ys > 3));
540         } else {                /* TRI */
541                 int         orient = (col + row) % 2;   /* O left 1 right */
542
543                 ap->shape.triangle[orient][0].x = ap->xb + col * ap->xs;
544                 ap->shape.triangle[orient][0].y = ap->yb + row * ap->ys;
545                 if (ap->xs <= 3 || ap->ys <= 3)
546                         XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
547                         ((orient) ? -1 : 1) + ap->shape.triangle[orient][0].x,
548                                        ap->shape.triangle[orient][0].y, 1, 1);
549                 else {
550                         if (orient)
551                                 ap->shape.triangle[orient][0].x += (ap->xs / 2 - 1);
552                         else
553                                 ap->shape.triangle[orient][0].x -= (ap->xs / 2 - 1);
554                         XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
555                                      ap->shape.triangle[orient], 3, Convex, CoordModePrevious);
556                 }
557         }
558 }
559
560 static void
561 truchetcell(ModeInfo * mi, int col, int row, int truchetstate)
562 {
563         antfarmstruct *ap = &antfarms[MI_SCREEN(mi)];
564
565         if (ap->neighbors == 6) {
566
567                 int         ccol = 2 * col + !(row & 1), crow = 2 * row;
568                 int         side;
569                 int         fudge = 7;  /* fudge because the hexagons are not exact */
570                 XPoint      hex, hex2;
571
572                 if (ap->sharpturn) {
573                         hex.x = ap->xb + ccol * ap->xs - (int) ((double) ap->xs / 2.0) - 1;
574                         hex.y = ap->yb + crow * ap->ys - (int) ((double) ap->ys / 2.0) - 1;
575                         for (side = 0; side < 6; side++) {
576                                 if (side > 0) {
577                                         hex.x += ap->shape.hexagon[side].x;
578                                         hex.y += ap->shape.hexagon[side].y;
579                                 }
580                                 if (truchetstate == side % 2)
581                                         XDrawArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi),
582                                                  hex.x, hex.y, ap->xs, ap->ys,
583                                                  ((570 - (side * 60) + fudge) % 360) * 64, (120 - 2 * fudge) * 64);
584                         }
585                 } else {
586
587                         /* Very crude approx of Sqrt 3, so it will not cause drawing errors. */
588                         hex.x = ap->xb + ccol * ap->xs - (int) ((double) ap->xs * 1.6 / 2.0);
589                         hex.y = ap->yb + crow * ap->ys - (int) ((double) ap->ys * 1.6 / 2.0);
590                         for (side = 0; side < 6; side++) {
591                                 if (side > 0) {
592                                         hex.x += ap->shape.hexagon[side].x;
593                                         hex.y += ap->shape.hexagon[side].y;
594                                 }
595                                 hex2.x = hex.x + ap->shape.hexagon[side + 1].x / 2;
596                                 hex2.y = hex.y + ap->shape.hexagon[side + 1].y / 2;
597                                 if (truchetstate == side % 3)
598                                         /* Crude approx of 120 deg, so it will not cause drawing errors. */
599                                         XDrawArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi),
600                                                  hex2.x, hex2.y,
601                                                  (int) ((double) ap->xs * 1.5), (int) ((double) ap->ys * 1.5),
602                                                  ((555 - (side * 60)) % 360) * 64, 90 * 64);
603                         }
604                 }
605         } else if (ap->neighbors == 4) {
606                 if (truchetstate) {
607                         XDrawArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi),
608                                  ap->xb + ap->xs * col - ap->xs / 2+ 1,
609                                  ap->yb + ap->ys * row + ap->ys / 2 - 1,
610                                  ap->xs - 2, ap->ys - 2,
611                                  0 * 64, 90 * 64);
612                         XDrawArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi),
613                                  ap->xb + ap->xs * col + ap->xs / 2 - 1,
614                                  ap->yb + ap->ys * row - ap->ys / 2 + 1,
615                                  ap->xs - 2, ap->ys - 2,
616                                  -90 * 64, -90 * 64);
617                 } else {
618                         XDrawArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi),
619                                  ap->xb + ap->xs * col - ap->xs / 2 + 1,
620                                  ap->yb + ap->ys * row - ap->ys / 2 + 1,
621                                  ap->xs - 2, ap->ys - 2,
622                                  0 * 64, -90 * 64);
623                         XDrawArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi),
624                                  ap->xb + ap->xs * col + ap->xs / 2 - 1,
625                                  ap->yb + ap->ys * row + ap->ys / 2 - 1,
626                                  ap->xs - 2, ap->ys - 2,
627                                  90 * 64, 90 * 64);
628                 }
629         } else if (ap->neighbors == 3) {
630                 int         orient = (col + row) % 2;   /* O left 1 right */
631                 int         side, ang;
632                 int         fudge = 7;  /* fudge because the triangles are not exact */
633                 XPoint      tri;
634
635                 tri.x = ap->xb + col * ap->xs;
636                 tri.y = ap->yb + row * ap->ys;
637                 if (orient) {
638                         tri.x += (ap->xs / 2 - 1);
639                 } else {
640                         tri.x -= (ap->xs / 2 - 1);
641                 }
642                 for (side = 0; side < 3; side++) {
643                         if (side > 0) {
644                                 tri.x += ap->shape.triangle[orient][side].x;
645                                 tri.y += ap->shape.triangle[orient][side].y;
646                         }
647                         if (truchetstate == side % 3) {
648                                 if (orient)
649                                         ang = (510 - side * 120) % 360;         /* Right */
650                                 else
651                                         ang = (690 - side * 120) % 360;         /* Left */
652                                 XDrawArc(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi),
653                                   tri.x - ap->xs / 2, tri.y - 3 * ap->ys / 4,
654                                          ap->xs, 3 * ap->ys / 2,
655                                   (ang + fudge) * 64, (60 - 2 * fudge) * 64);
656                         }
657                 }
658         }
659 }
660
661 static void
662 drawcell(ModeInfo * mi, int col, int row, unsigned char color)
663 {
664         antfarmstruct *ap = &antfarms[MI_SCREEN(mi)];
665         GC          gc;
666
667         if (!color) {
668                 XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi));
669                 gc = MI_GC(mi);
670         } else if (MI_NPIXELS(mi) > 2) {
671                 XSetForeground(MI_DISPLAY(mi), MI_GC(mi),
672                                MI_PIXEL(mi, ap->colors[color - 1]));
673                 gc = MI_GC(mi);
674         } else {
675                 XGCValues   gcv;
676
677                 gcv.stipple = ap->pixmaps[color - 1];
678                 gcv.foreground = MI_WHITE_PIXEL(mi);
679                 gcv.background = MI_BLACK_PIXEL(mi);
680                 XChangeGC(MI_DISPLAY(mi), ap->stippledGC,
681                           GCStipple | GCForeground | GCBackground, &gcv);
682                 gc = ap->stippledGC;
683         }
684         fillcell(mi, gc, col, row);
685 }
686
687 static void
688 drawtruchet(ModeInfo * mi, int col, int row,
689             unsigned char color, unsigned char truchetstate)
690 {
691         antfarmstruct *ap = &antfarms[MI_SCREEN(mi)];
692
693         if (!color)
694                 XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WHITE_PIXEL(mi));
695         else if (MI_NPIXELS(mi) > 2 || color > ap->ncolors / 2)
696                 XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi));
697         else
698                 XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WHITE_PIXEL(mi));
699         truchetcell(mi, col, row, truchetstate);
700 }
701
702 static void
703 draw_anant(ModeInfo * mi, int col, int row)
704 {
705         XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WHITE_PIXEL(mi));
706         fillcell(mi, MI_GC(mi), col, row);
707 #if 0                           /* Can not see eyes */
708         {
709                 antfarmstruct *ap = &antfarms[MI_SCREEN(mi)];
710                 Display    *display = MI_DISPLAY(mi);
711                 Window      window = MI_WINDOW(mi);
712
713                 if (ap->xs > 2 && ap->ys > 2) {         /* Draw Eyes */
714
715                         XSetForeground(display, MI_GC(mi), MI_BLACK_PIXEL(mi));
716                         switch (direction) {
717                                 case 0:
718                                         XDrawPoint(display, window, MI_GC(mi),
719                                             ap->xb + ap->xs - 1, ap->yb + 1);
720                                         XDrawPoint(display, window, MI_GC(mi),
721                                                    ap->xb + ap->xs - 1, ap->yb + ap->ys - 2);
722                                         break;
723                                 case 180:
724                                         XDrawPoint(display, window, MI_GC(mi), ap->xb, ap->yb + 1);
725                                         XDrawPoint(display, window, MI_GC(mi), ap->xb, ap->yb + ap->ys - 2);
726                                         break;
727                                         if (neighbors == 4) {
728                                 case 90:
729                                                 XDrawPoint(display, window, MI_GC(mi), ap->xb + 1, ap->yb);
730                                                 XDrawPoint(display, window, MI_GC(mi),
731                                                 ap->xb + ap->xs - 2, ap->yb);
732                                                 break;
733                                 case 270:
734                                                 XDrawPoint(display, window, MI_GC(mi),
735                                                            ap->xb + 1, ap->yb + ap->ys - 1);
736                                                 XDrawPoint(display, window, MI_GC(mi),
737                                                            ap->xb + ap->xs - 2, ap->yb + ap->ys - 1);
738                                                 break;
739                                         }       /* else BEE */
740                                 default:
741                         }
742                 }
743         }
744 #endif
745 }
746
747 #if 0
748 static void
749 RandomSoup(mi)
750         ModeInfo   *mi;
751 {
752         antfarmstruct *ap = &antfarms[MI_SCREEN(mi)];
753         int         row, col, mrow = 0;
754
755         for (row = 0; row < ap->nrows; ++row) {
756                 for (col = 0; col < ap->ncols; ++col) {
757                         ap->old[col + mrow] = (unsigned char) NRAND((int) ap->ncolors);
758                         drawcell(mi, col, row, ap->old[col + mrow]);
759                 }
760                 mrow += ap->nrows;
761         }
762 }
763
764 #endif
765
766 static short
767 fromTableDirection(unsigned char dir, int neighbors)
768 {
769         switch (dir) {
770                 case FS:
771                         return 0;
772                 case TRS:
773                         return (ANGLES / neighbors);
774                 case THRS:
775                         return (ANGLES / 2 - ANGLES / neighbors);
776                 case TBS:
777                         return (ANGLES / 2);
778                 case THLS:
779                         return (ANGLES / 2 + ANGLES / neighbors);
780                 case TLS:
781                         return (ANGLES - ANGLES / neighbors);
782                 case SF:
783                         return ANGLES;
784                 case STR:
785                         return (ANGLES + ANGLES / neighbors);
786                 case STHR:
787                         return (3 * ANGLES / 2 - ANGLES / neighbors);
788                 case STB:
789                         return (3 * ANGLES / 2);
790                 case STHL:
791                         return (3 * ANGLES / 2 + ANGLES / neighbors);
792                 case STL:
793                         return (2 * ANGLES - ANGLES / neighbors);
794                 default:
795                         (void) fprintf(stderr, "wrong direction %d\n", dir);
796         }
797         return -1;
798 }
799
800 static void
801 getTable(ModeInfo * mi, int i)
802 {
803         antfarmstruct *ap = &antfarms[MI_SCREEN(mi)];
804         int         j, total;
805         unsigned char *patptr;
806
807         patptr = &tables[i][0];
808         ap->ncolors = *patptr++;
809         ap->nstates = *patptr++;
810         total = ap->ncolors * ap->nstates;
811         if (MI_IS_VERBOSE(mi))
812                 (void) fprintf(stdout,
813                                "ants %d, neighbors %d, table number %d, colors %d, states %d\n",
814                           ap->n, ap->neighbors, i, ap->ncolors, ap->nstates);
815         for (j = 0; j < total; j++) {
816                 ap->machine[j].color = *patptr++;
817                 if (ap->sharpturn && ap->neighbors > 4 && !(ap->neighbors % 2)) {
818                         int         k = *patptr++;
819
820                         switch (k) {
821                                 case TRS:
822                                         k = THRS;
823                                         break;
824                                 case THRS:
825                                         k = TRS;
826                                         break;
827                                 case THLS:
828                                         k = TLS;
829                                         break;
830                                 case TLS:
831                                         k = THLS;
832                                         break;
833                                 case STR:
834                                         k = STHR;
835                                         break;
836                                 case STHR:
837                                         k = STR;
838                                         break;
839                                 case STHL:
840                                         k = STL;
841                                         break;
842                                 case STL:
843                                         k = STHL;
844                                         break;
845                                 default:
846                                         break;
847                         }
848                         ap->machine[j].direction = fromTableDirection(k, ap->neighbors);
849                 } else {
850                         ap->machine[j].direction = fromTableDirection(*patptr++, ap->neighbors);
851                 }
852                 ap->machine[j].next = *patptr++;
853         }
854         ap->truchet = False;
855 }
856
857 static void
858 getTurk(ModeInfo * mi, int i)
859 {
860         antfarmstruct *ap = &antfarms[MI_SCREEN(mi)];
861         int         power2, j, number, total;
862
863         /* To force a number, say <i = 2;> has  i + 2 (or 4) digits in binary */
864         power2 = 1 << (i + 1);
865         /* Dont want numbers which in binary are all 1's. */
866         number = NRAND(power2 - 1) + power2;
867         /* To force a particular number, say <number = 10;> */
868
869         ap->ncolors = i + 2;
870         ap->nstates = 1;
871         total = ap->ncolors * ap->nstates;
872         for (j = 0; j < total; j++) {
873                 ap->machine[j].color = (j + 1) % total;
874                 if (ap->sharpturn && ap->neighbors > 4 && !(ap->neighbors % 2)) {
875                         ap->machine[j].direction = (power2 & number) ?
876                                 fromTableDirection(THRS, ap->neighbors) :
877                                 fromTableDirection(THLS, ap->neighbors);
878                 } else {
879                         ap->machine[j].direction = (power2 & number) ?
880                                 fromTableDirection(TRS, ap->neighbors) :
881                                 fromTableDirection(TLS, ap->neighbors);
882                 }
883                 ap->machine[j].next = 0;
884                 power2 >>= 1;
885         }
886         ap->truchet = (ap->truchet && ap->xs > 2 && ap->ys > 2 &&
887            (ap->neighbors == 3 || ap->neighbors == 4 || ap->neighbors == 6));
888         if (MI_IS_VERBOSE(mi))
889                 (void) fprintf(stdout,
890                       "ants %d, neighbors %d, Turk's number %d, colors %d\n",
891                                ap->n, ap->neighbors, number, ap->ncolors);
892 }
893
894 void
895 init_ant(ModeInfo * mi)
896 {
897         Display    *display = MI_DISPLAY(mi);
898         Window      window = MI_WINDOW(mi);
899         int         size = MI_SIZE(mi);
900         antfarmstruct *ap;
901         int         col, row, dir;
902         long        i;
903
904         /* jwz sez: small sizes look like crap */
905         if (size < 0)
906           size = NRAND(-size)+1;
907         if (size < 5)
908           size += 5;
909
910         if (antfarms == NULL) {
911                 if ((antfarms = (antfarmstruct *) calloc(MI_NUM_SCREENS(mi),
912                                             sizeof (antfarmstruct))) == NULL)
913                         return;
914         }
915         ap = &antfarms[MI_SCREEN(mi)];
916         ap->redrawing = 0;
917         if (MI_NPIXELS(mi) <= 2) {
918                 if (ap->stippledGC == None) {
919                         XGCValues   gcv;
920
921                         gcv.fill_style = FillOpaqueStippled;
922                         ap->stippledGC = XCreateGC(display, window, GCFillStyle, &gcv);
923                 }
924                 if (ap->init_bits == 0) {
925                         for (i = 1; i < NUMSTIPPLES; i++)
926                                 ANTBITS(stipples[i], STIPPLESIZE, STIPPLESIZE);
927                 }
928         }
929         ap->generation = 0;
930         ap->n = MI_COUNT(mi);
931         if (ap->n < -MINANTS) {
932                 /* if ap->n is random ... the size can change */
933                 if (ap->ants != NULL) {
934                         (void) free((void *) ap->ants);
935                         ap->ants = NULL;
936                 }
937                 ap->n = NRAND(-ap->n - MINANTS + 1) + MINANTS;
938         } else if (ap->n < MINANTS)
939                 ap->n = MINANTS;
940
941         ap->width = MI_WIDTH(mi);
942         ap->height = MI_HEIGHT(mi);
943
944         if (neighbors == 8 || neighbors == 9 || neighbors == 12)
945                 ap->neighbors = neighbors;      /* Discourage but not deny use... */
946         else
947                 for (i = 0; i < NEIGHBORKINDS; i++) {
948                         if (neighbors == plots[i]) {
949                                 ap->neighbors = plots[i];
950                                 break;
951                         }
952                         if (i == NEIGHBORKINDS - 1) {
953                                 ap->neighbors = plots[NRAND(NEIGHBORKINDS)];
954                                 break;
955                         }
956                 }
957
958         if (ap->neighbors == 6) {
959                 int         nccols, ncrows;
960
961                 if (ap->width < 2)
962                         ap->width = 2;
963                 if (ap->height < 4)
964                         ap->height = 4;
965                 if (size < -MINSIZE) {
966                         ap->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(ap->width, ap->height) /
967                                       MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
968                         if (ap->ys < MINRANDOMSIZE)
969                                 ap->ys = MIN(MINRANDOMSIZE,
970                                              MAX(MINSIZE, MIN(ap->width, ap->height) / MINGRIDSIZE));
971                 } else if (size < MINSIZE) {
972                         if (!size)
973                                 ap->ys = MAX(MINSIZE, MIN(ap->width, ap->height) / MINGRIDSIZE);
974                         else
975                                 ap->ys = MINSIZE;
976                 } else
977                         ap->ys = MIN(size, MAX(MINSIZE, MIN(ap->width, ap->height) /
978                                                MINGRIDSIZE));
979                 ap->xs = ap->ys;
980                 nccols = MAX(ap->width / ap->xs - 2, 2);
981                 ncrows = MAX(ap->height / ap->ys - 1, 2);
982                 ap->ncols = nccols / 2;
983                 ap->nrows = 2 * (ncrows / 4);
984                 ap->xb = (ap->width - ap->xs * nccols) / 2 + ap->xs / 2;
985                 ap->yb = (ap->height - ap->ys * (ncrows / 2) * 2) / 2 + ap->ys;
986                 for (i = 0; i < 6; i++) {
987                         ap->shape.hexagon[i].x = (ap->xs - 1) * hexagonUnit[i].x;
988                         ap->shape.hexagon[i].y = ((ap->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3;
989                 }
990                 /* Avoid array bounds read of hexagonUnit */
991                 ap->shape.hexagon[6].x = 0;
992                 ap->shape.hexagon[6].y = 0;
993         } else if (ap->neighbors == 4 || ap->neighbors == 8) {
994                 if (size < -MINSIZE) {
995                         ap->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(ap->width, ap->height) /
996                                       MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
997                         if (ap->ys < MINRANDOMSIZE)
998                                 ap->ys = MIN(MINRANDOMSIZE,
999                                              MAX(MINSIZE, MIN(ap->width, ap->height) / MINGRIDSIZE));
1000                 } else if (size < MINSIZE) {
1001                         if (!size)
1002                                 ap->ys = MAX(MINSIZE, MIN(ap->width, ap->height) / MINGRIDSIZE);
1003                         else
1004                                 ap->ys = MINSIZE;
1005                 } else
1006                         ap->ys = MIN(size, MAX(MINSIZE, MIN(ap->width, ap->height) /
1007                                                MINGRIDSIZE));
1008                 ap->xs = ap->ys;
1009                 ap->ncols = MAX(ap->width / ap->xs, 2);
1010                 ap->nrows = MAX(ap->height / ap->ys, 2);
1011                 ap->xb = (ap->width - ap->xs * ap->ncols) / 2;
1012                 ap->yb = (ap->height - ap->ys * ap->nrows) / 2;
1013         } else {                /* TRI */
1014                 int         orient;
1015
1016                 if (ap->width < 2)
1017                         ap->width = 2;
1018                 if (ap->height < 2)
1019                         ap->height = 2;
1020                 if (size < -MINSIZE) {
1021                         ap->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(ap->width, ap->height) /
1022                                       MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
1023                         if (ap->ys < MINRANDOMSIZE)
1024                                 ap->ys = MIN(MINRANDOMSIZE,
1025                                              MAX(MINSIZE, MIN(ap->width, ap->height) / MINGRIDSIZE));
1026                 } else if (size < MINSIZE) {
1027                         if (!size)
1028                                 ap->ys = MAX(MINSIZE, MIN(ap->width, ap->height) / MINGRIDSIZE);
1029                         else
1030                                 ap->ys = MINSIZE;
1031                 } else
1032                         ap->ys = MIN(size, MAX(MINSIZE, MIN(ap->width, ap->height) /
1033                                                MINGRIDSIZE));
1034                 ap->xs = (int) (1.52 * ap->ys);
1035                 ap->ncols = (MAX(ap->width / ap->xs - 1, 2) / 2) * 2;
1036                 ap->nrows = (MAX(ap->height / ap->ys - 1, 2) / 2) * 2;
1037                 ap->xb = (ap->width - ap->xs * ap->ncols) / 2 + ap->xs / 2;
1038                 ap->yb = (ap->height - ap->ys * ap->nrows) / 2 + ap->ys;
1039                 for (orient = 0; orient < 2; orient++) {
1040                         for (i = 0; i < 3; i++) {
1041                                 ap->shape.triangle[orient][i].x =
1042                                         (ap->xs - 2) * triangleUnit[orient][i].x;
1043                                 ap->shape.triangle[orient][i].y =
1044                                         (ap->ys - 2) * triangleUnit[orient][i].y;
1045                         }
1046                         /* Avoid array bounds read of triangleUnit */
1047                         ap->shape.triangle[orient][3].x = 0;
1048                         ap->shape.triangle[orient][3].y = 0;
1049                 }
1050         }
1051
1052         XSetLineAttributes(display, MI_GC(mi), 1, LineSolid, CapNotLast, JoinMiter);
1053         MI_CLEARWINDOW(mi);
1054         ap->painted = False;
1055
1056         if (MI_IS_FULLRANDOM(mi)) {
1057                 ap->truchet = (Bool) (LRAND() & 1);
1058                 ap->sharpturn = (Bool) (LRAND() & 1);
1059         } else {
1060                 ap->truchet = truchet;
1061                 ap->sharpturn = sharpturn;
1062         }
1063         /* Exclude odd # of neighbors, stepping forward not defined */
1064         if (!NRAND(NUMSTIPPLES) && ((ap->neighbors + 1) % 2)) {
1065                 getTable(mi, (int) (NRAND(NTABLES)));
1066         } else
1067                 getTurk(mi, (int) (NRAND(NUMSTIPPLES - 1)));
1068         if (MI_NPIXELS(mi) > 2)
1069                 for (i = 0; i < (int) ap->ncolors - 1; i++)
1070                         ap->colors[i] = (unsigned char) (NRAND(MI_NPIXELS(mi)) +
1071                              i * MI_NPIXELS(mi)) / ((int) (ap->ncolors - 1));
1072         if (ap->ants == NULL)
1073                 ap->ants = (antstruct *) malloc(ap->n * sizeof (antstruct));
1074         if (ap->tape != NULL)
1075                 (void) free((void *) ap->tape);
1076         ap->tape = (unsigned char *)
1077                 calloc(ap->ncols * ap->nrows, sizeof (unsigned char));
1078
1079         if (ap->truchet_state != NULL)
1080                 (void) free((void *) ap->truchet_state);
1081         ap->truchet_state = (unsigned char *)
1082                 calloc(ap->ncols * ap->nrows, sizeof (unsigned char));
1083
1084         col = ap->ncols / 2;
1085         row = ap->nrows / 2;
1086         dir = NRAND(ap->neighbors) * ANGLES / ap->neighbors;
1087         /* Have them all start in the same spot, why not? */
1088         for (i = 0; i < ap->n; i++) {
1089                 ap->ants[i].col = col;
1090                 ap->ants[i].row = row;
1091                 ap->ants[i].direction = dir;
1092                 ap->ants[i].state = 0;
1093         }
1094         draw_anant(mi, col, row);
1095 }
1096
1097 void
1098 draw_ant(ModeInfo * mi)
1099 {
1100         antfarmstruct *ap = &antfarms[MI_SCREEN(mi)];
1101         antstruct  *anant;
1102         statestruct *status;
1103         int         i, state_pos, tape_pos;
1104         unsigned char color;
1105         short       chg_dir, old_dir;
1106
1107         MI_IS_DRAWN(mi) = True;
1108
1109         ap->painted = True;
1110         for (i = 0; i < ap->n; i++) {
1111                 anant = &ap->ants[i];
1112                 tape_pos = anant->col + anant->row * ap->ncols;
1113                 color = ap->tape[tape_pos];     /* read tape */
1114                 state_pos = color + anant->state * ap->ncolors;
1115                 status = &(ap->machine[state_pos]);
1116                 drawcell(mi, anant->col, anant->row, status->color);
1117                 ap->tape[tape_pos] = status->color;     /* write on tape */
1118
1119                 /* Find direction of Bees or Ants. */
1120                 /* Translate relative direction to actual direction */
1121                 old_dir = anant->direction;
1122                 chg_dir = (2 * ANGLES - status->direction) % ANGLES;
1123                 anant->direction = (chg_dir + old_dir) % ANGLES;
1124                 if (ap->truchet) {
1125                         int         a = 0, b;
1126
1127                         if (ap->neighbors == 6) {
1128                                 if (ap->sharpturn) {
1129                                         a = (chg_dir / 120 == 2);
1130                                         drawtruchet(mi, anant->col, anant->row, status->color, a);
1131                                 } else {
1132                                         a = (old_dir / 60) % 3;
1133                                         b = (anant->direction / 60) % 3;
1134                                         a = (a + b + 1) % 3;
1135                                         drawtruchet(mi, anant->col, anant->row, status->color, a);
1136                                 }
1137                         } else if (ap->neighbors == 4) {
1138                                 a = old_dir / 180;
1139                                 b = anant->direction / 180;
1140                                 a = ((a && !b) || (b && !a));
1141                                 drawtruchet(mi, anant->col, anant->row, status->color, a);
1142                         } else if (ap->neighbors == 3) {
1143                                 if (chg_dir == 240)
1144                                         a = (2 + anant->direction / 120) % 3;
1145                                 else
1146                                         a = (1 + anant->direction / 120) % 3;
1147                                 drawtruchet(mi, anant->col, anant->row, status->color, a);
1148                         }
1149                         ap->truchet_state[tape_pos] = a + 1;
1150                 }
1151                 anant->state = status->next;
1152
1153                 /* If edge than wrap it */
1154                 old_dir = ((status->direction < ANGLES) ? anant->direction : old_dir);
1155                 position_of_neighbor(ap, old_dir, &(anant->col), &(anant->row));
1156                 draw_anant(mi, anant->col, anant->row);
1157         }
1158         if (++ap->generation > MI_CYCLES(mi)) {
1159 #ifdef STANDALONE
1160           erase_full_window(MI_DISPLAY(mi), MI_WINDOW(mi));
1161 #endif
1162                 init_ant(mi);
1163         }
1164         if (ap->redrawing) {
1165                 for (i = 0; i < REDRAWSTEP; i++) {
1166                         if (ap->tape[ap->redrawpos] ||
1167                          (ap->truchet && ap->truchet_state[ap->redrawpos])) {
1168                                 drawcell(mi, ap->redrawpos % ap->ncols, ap->redrawpos / ap->ncols,
1169                                          ap->tape[ap->redrawpos]);
1170                                 if (ap->truchet)
1171                                         drawtruchet(mi, ap->redrawpos % ap->ncols, ap->redrawpos / ap->ncols,
1172                                                     ap->tape[ap->redrawpos],
1173                                         ap->truchet_state[ap->redrawpos] - 1);
1174                         }
1175                         if (++(ap->redrawpos) >= ap->ncols * ap->nrows) {
1176                                 ap->redrawing = 0;
1177                                 break;
1178                         }
1179                 }
1180         }
1181 }
1182
1183 void
1184 release_ant(ModeInfo * mi)
1185 {
1186         if (antfarms != NULL) {
1187                 int         screen;
1188
1189                 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
1190                         antfarmstruct *ap = &antfarms[screen];
1191                         int         shade;
1192
1193                         if (ap->stippledGC != None) {
1194                                 XFreeGC(MI_DISPLAY(mi), ap->stippledGC);
1195                         }
1196                         for (shade = 0; shade < ap->init_bits; shade++)
1197                                 XFreePixmap(MI_DISPLAY(mi), ap->pixmaps[shade]);
1198                         if (ap->tape != NULL)
1199                                 (void) free((void *) ap->tape);
1200                         if (ap->ants != NULL)
1201                                 (void) free((void *) ap->ants);
1202                         if (ap->truchet_state != NULL)
1203                                 (void) free((void *) ap->truchet_state);
1204                 }
1205                 (void) free((void *) antfarms);
1206                 antfarms = NULL;
1207         }
1208 }
1209
1210 void
1211 refresh_ant(ModeInfo * mi)
1212 {
1213         antfarmstruct *ap = &antfarms[MI_SCREEN(mi)];
1214
1215         if (ap->painted) {
1216                 MI_CLEARWINDOW(mi);
1217                 ap->redrawing = 1;
1218                 ap->redrawpos = 0;
1219         }
1220 }