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