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