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