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