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