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