http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.14.tar.gz
[xscreensaver] / hacks / penrose.c
1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* penrose --- quasiperiodic tilings */
3
4 /*  As reported in News of the Weird:
5
6           In April, Sir Roger Penrose, a British math professor who has worked
7           with Stephen Hawking on such topics as relativity, black holes, and
8           whether time has a beginning, filed a copyright-infringement lawsuit
9           against the Kimberly-Clark Corporation, which Penrose said copied a
10           pattern he created (a pattern demonstrating that "a nonrepeating
11           pattern could exist in nature") for its Kleenex quilted toilet paper.
12           Penrose said he doesn't like litigation but, "When it comes to the
13           population of Great Britain being invited by a multinational to wipe
14           their bottoms on what appears to be the work of a Knight of the
15           Realm, then a last stand must be taken."
16
17                                 NOTW #491, 4-jul-1997, by Chuck Shepherd.
18                                 http://www.nine.org/notw/notw.html
19  */
20
21 #if 0
22 static const char sccsid[] = "@(#)penrose.c     5.00 2000/11/01 xlockmore";
23 #endif
24
25 /*-
26  * Copyright (c) 1996 by Timo Korvola <tkorvola@dopey.hut.fi>
27  *
28  * Permission to use, copy, modify, and distribute this software and its
29  * documentation for any purpose and without fee is hereby granted,
30  * provided that the above copyright notice appear in all copies and that
31  * both that copyright notice and this permission notice appear in
32  * supporting documentation.
33  *
34  * This file is provided AS IS with no warranties of any kind.  The author
35  * shall have no liability with respect to the infringement of copyrights,
36  * trade secrets or any patents by this file or any part thereof.  In no
37  * event will the author be liable for any lost revenue or profits or
38  * other special, indirect and consequential damages.
39  *
40  * Revision History:
41  * 01-Nov-2000: Allocation checks
42  * 10-May-1997: Jamie Zawinski <jwz@jwz.org> compatible with xscreensaver
43  * 09-Sep-1996: Written.
44  */
45
46 /*-
47 Be careful, this probably still has a few bugs (many of which may only
48 appear with a very low probability).  These are seen with -verbose .
49 If one of these are hit penrose will reinitialize.
50 */
51
52 /*-
53  * See Onoda, Steinhardt, DiVincenzo and Socolar in
54  * Phys. Rev. Lett. 60, #25, 1988 or
55  * Strandburg in Computers in Physics, Sep/Oct 1991.
56  *
57  * This implementation uses the simpler version of the growth
58  * algorithm, i.e., if there are no forced vertices, a randomly chosen
59  * tile is added to a randomly chosen vertex (no preference for those
60  * 108 degree angles).
61  *
62  * There are two essential differences to the algorithm presented in
63  * the literature: First, we do not allow the tiling to enclose an
64  * untiled area.  Whenever this is in danger of happening, we just
65  * do not add the tile, hoping for a better random choice the next
66  * time.  Second, when choosing a vertex randomly, we will take
67  * one that lies within the viewport if available.  If this seems to
68  * cause enclosures in the forced rule case, we will allow invisible
69  * vertices to be chosen.
70  *
71  * Tiling is restarted whenever one of the following happens: there
72  * are no incomplete vertices within the viewport or the tiling has
73  * extended a window's length beyond the edge of the window
74  * horizontally or vertically or forced rule choice has failed 100
75  * times due to areas about to become enclosed.
76  *
77  * Introductory info:
78  * Science News March 23 1985 Vol 127, No. 12
79  * Science News July 16 1988 Vol 134, No. 3
80  * The Economist Sept 17 1988 pg. 100
81  *
82  */
83
84 #ifdef STANDALONE
85 #define MODE_penrose
86 #define PROGCLASS "Penrose"
87 #define HACK_INIT init_penrose
88 #define HACK_DRAW draw_penrose
89 #define penrose_opts xlockmore_opts
90 #define DEFAULTS "*delay: 10000 \n" \
91  "*size: 40 \n" \
92  "*ncolors: 64 \n"
93 #include "xlockmore.h"          /* from the xscreensaver distribution */
94 #else /* !STANDALONE */
95 #include "xlock.h"              /* from the xlockmore distribution */
96 #endif /* !STANDALONE */
97
98 #ifdef MODE_penrose
99
100 #define DEF_AMMANN  "False"
101
102 static Bool ammann;
103
104 static XrmOptionDescRec opts[] =
105 {
106         {(char *) "-ammann", (char *) ".penrose.ammann", XrmoptionNoArg, (caddr_t) "on"},
107         {(char *) "+ammann", (char *) ".penrose.ammann", XrmoptionNoArg, (caddr_t) "off"}
108 };
109 static argtype vars[] =
110 {
111         {(caddr_t *) & ammann, (char *) "ammann", (char *) "Ammann", (char *) DEF_AMMANN, t_Bool}
112 };
113 static OptionStruct desc[] =
114 {
115         {(char *) "-/+ammann", (char *) "turn on/off Ammann lines"}
116 };
117
118 ModeSpecOpt penrose_opts =
119 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
120
121 #ifdef USE_MODULES
122 ModStruct   penrose_description =
123 {"penrose", "init_penrose", "draw_penrose", "release_penrose",
124  "init_penrose", "init_penrose", (char *) NULL, &penrose_opts,
125  10000, 1, 1, -40, 64, 1.0, "",
126  "Shows Penrose's quasiperiodic tilings", 0, NULL};
127
128 #endif
129
130 /*-
131  * Annoyingly the ANSI C library people have reserved all identifiers
132  * ending with _t for future use.  Hence we use _c as a suffix for
133  * typedefs (c for class, although this is not C++).
134  */
135
136 #define MINSIZE 5
137
138 /*-
139  * In theory one could fit 10 tiles to a single vertex.  However, the
140  * vertex rules only allow at most seven tiles to meet at a vertex.
141  */
142
143 #define CELEBRATE 31415         /* This causes a pause, an error occurred. */
144 #define COMPLETION 3141         /* This causes a pause, tiles filled up screen. */
145
146 #define MAX_TILES_PER_VERTEX 7
147 #define N_VERTEX_RULES 8
148 #define ALLOC_NODE(type) (type *)malloc(sizeof (type))
149
150 /*-
151  * These are used to specify directions.  They can also be used in bit
152  * masks to specify a combination of directions.
153  */
154 #define S_LEFT 1
155 #define S_RIGHT 2
156
157
158 /*-
159  * We do not actually maintain objects corresponding to the tiles since
160  * we do not really need them and they would only consume memory and
161  * cause additional bookkeeping.  Instead we only have vertices, and
162  * each vertex lists the type of each adjacent tile as well as the
163  * position of the vertex on the tile (hereafter refered to as
164  * "corner").  These positions are numbered in counterclockwise order
165  * so that 0 is where two double arrows meet (see one of the
166  * articles).  The tile type and vertex number are stored in a single
167  * integer (we use char, and even most of it remains unused).
168  *
169  * The primary use of tile objects would be draw traversal, but we do
170  * not currently do redraws at all (we just start over).
171  */
172 #define VT_CORNER_MASK 0x3
173 #define VT_TYPE_MASK 0x4
174 #define VT_THIN 0
175 #define VT_THICK 0x4
176 #define VT_BITS 3
177 #define VT_TOTAL_MASK 0x7
178
179 typedef unsigned char vertex_type_c;
180
181 /*-
182  * These allow one to compute the types of the other corners of the tile.  If
183  * you are standing at a vertex of type vt looking towards the middle of the
184  * tile, VT_LEFT( vt) is the vertex on your left etc.
185  */
186 #define VT_LEFT( vt) ((((vt) - 1) & VT_CORNER_MASK) | (((vt) & VT_TYPE_MASK)))
187 #define VT_RIGHT( vt) ((((vt) + 1) & VT_CORNER_MASK) | (((vt) & VT_TYPE_MASK)))
188 #define VT_FAR( vt) ((vt) ^ 2)
189
190
191 /*-
192  * Since we do not do redraws, we only store the vertices we need.  These are
193  * the ones with still some empty space around them for the growth algorithm
194  * to fill.
195  *
196  * Here we use a doubly chained ring-like structure as vertices often need
197  * to be removed or inserted (they are kept in geometrical order
198  * circling the tiled area counterclockwise).  The ring is refered to by
199  * a pointer to one more or less random node.  When deleting nodes one
200  * must make sure that this pointer continues to refer to a valid
201  * node.  A vertex count is maintained to make it easier to pick
202  * vertices randomly.
203  */
204 typedef struct forced_node forced_node_c;
205
206 typedef struct fringe_node {
207         struct fringe_node *prev;
208         struct fringe_node *next;
209         /* These are numbered counterclockwise.  The gap, if any, lies
210            between the last and first tiles.  */
211         vertex_type_c tiles[MAX_TILES_PER_VERTEX];
212         int         n_tiles;
213         /* A bit mask used to indicate vertex rules that are still applicable for
214            completing this vertex.  Initialize this to (1 << N_VERTEX_RULES) - 1,
215            i.e., all ones, and the rule matching functions will automatically mask
216            out rules that no longer match. */
217         unsigned char rule_mask;
218         /* If the vertex is on the forced vertex list, this points to the
219            pointer to the appropriate node in the list.  To remove the
220            vertex from the list just set *list_ptr to the next node,
221            deallocate and decrement node count. */
222         struct forced_node **list_ptr;
223         /* Screen coordinates. */
224         XPoint      loc;
225         /* We also keep track of 5D coordinates to avoid rounding errors.
226            These are in units of edge length. */
227         int         fived[5];
228         /* This is used to quickly check if a vertex is visible. */
229         unsigned char off_screen;
230 } fringe_node_c;
231
232 typedef struct {
233         fringe_node_c *nodes;
234         /* This does not count off-screen nodes. */
235         int         n_nodes;
236 } fringe_c;
237
238
239 /*-
240  * The forced vertex pool contains vertices where at least one
241  * side of the tiled region can only be extended in one way.  Note
242  * that this does not necessarily mean that there would only be one
243  * applicable rule.  forced_sides are specified using S_LEFT and
244  * S_RIGHT as if looking at the untiled region from the vertex.
245  */
246 struct forced_node {
247         fringe_node_c *vertex;
248         unsigned    forced_sides;
249         struct forced_node *next;
250 };
251
252 typedef struct {
253         forced_node_c *first;
254         int         n_nodes, n_visible;
255 } forced_pool_c;
256
257
258 /* This is the data related to the tiling of one screen. */
259 typedef struct {
260         int         width, height;
261         XPoint      origin;
262         int         edge_length;
263         fringe_c    fringe;
264         forced_pool_c forced;
265         int         done, failures;
266         unsigned long thick_color, thin_color;
267         int         busyLoop;
268         Bool        ammann;
269 } tiling_c;
270
271 static tiling_c *tilings = (tiling_c *) NULL;
272
273 /* The tiles are listed in counterclockwise order. */
274 typedef struct {
275         vertex_type_c tiles[MAX_TILES_PER_VERTEX];
276         int         n_tiles;
277 } vertex_rule_c;
278
279 static vertex_rule_c vertex_rules[N_VERTEX_RULES] =
280 {
281         {
282   {VT_THICK | 2, VT_THICK | 2, VT_THICK | 2, VT_THICK | 2, VT_THICK | 2}, 5},
283         {
284   {VT_THICK | 0, VT_THICK | 0, VT_THICK | 0, VT_THICK | 0, VT_THICK | 0}, 5},
285         {
286                 {VT_THICK | 0, VT_THICK | 0, VT_THICK | 0, VT_THIN | 0}, 4},
287         {
288          {VT_THICK | 2, VT_THICK | 2, VT_THIN | 1, VT_THIN | 3, VT_THICK | 2,
289           VT_THIN | 1, VT_THIN | 3}, 7},
290         {
291                 {VT_THICK | 2, VT_THICK | 2, VT_THICK | 2, VT_THICK | 2,
292                  VT_THIN | 1, VT_THIN | 3}, 6},
293         {
294                 {VT_THICK | 1, VT_THICK | 3, VT_THIN | 2}, 3},
295         {
296                 {VT_THICK | 0, VT_THIN | 0, VT_THIN | 0}, 3},
297         {
298      {VT_THICK | 2, VT_THIN | 1, VT_THICK | 3, VT_THICK | 1, VT_THIN | 3}, 5}
299 };
300
301
302 /* Match information returned by match_rules. */
303 typedef struct {
304         int         rule;
305         int         pos;
306 } rule_match_c;
307
308
309 /* Occasionally floating point coordinates are needed. */
310 typedef struct {
311         float       x, y;
312 } fcoord_c;
313
314
315 /* All angles are measured in multiples of 36 degrees. */
316 typedef int angle_c;
317
318 static angle_c vtype_angles[] =
319 {4, 1, 4, 1, 2, 3, 2, 3};
320
321 #define vtype_angle( v) (vtype_angles[ v])
322
323
324 /* Direction angle of an edge. */
325 static      angle_c
326 vertex_dir(ModeInfo * mi, fringe_node_c * vertex, unsigned side)
327 {
328         tiling_c   *tp = &tilings[MI_SCREEN(mi)];
329         fringe_node_c *v2 =
330         (side == S_LEFT ? vertex->next : vertex->prev);
331         register int i;
332
333         for (i = 0; i < 5; i++)
334                 switch (v2->fived[i] - vertex->fived[i]) {
335                         case 1:
336                                 return 2 * i;
337                         case -1:
338                                 return (2 * i + 5) % 10;
339                 }
340         tp->done = True;
341         if (MI_IS_VERBOSE(mi)) {
342                 (void) fprintf(stderr,
343                        "Weirdness in vertex_dir (this has been reported)\n");
344                 for (i = 0; i < 5; i++)
345                         (void) fprintf(stderr, "v2->fived[%d]=%d, vertex->fived[%d]=%d\n",
346                                        i, v2->fived[i], i, vertex->fived[i]);
347         }
348         tp->busyLoop = CELEBRATE;
349         return 0;
350 }
351
352
353 /* Move one step to a given direction. */
354 static void
355 add_unit_vec(angle_c dir, int *fived)
356 {
357         static int  dir2i[] =
358         {0, 3, 1, 4, 2};
359
360         while (dir < 0)
361                 dir += 10;
362         fived[dir2i[dir % 5]] += (dir % 2 ? -1 : 1);
363 }
364
365
366 /* For comparing coordinates. */
367 #define fived_equal( f1, f2) (!memcmp( (f1), (f2), 5 * sizeof( int)))
368
369
370 /*-
371  * This computes screen coordinates from 5D representation.  Note that X
372  * uses left-handed coordinates (y increases downwards).
373  */
374 static void
375 fived_to_loc(int fived[], tiling_c * tp, XPoint *pt)
376 {
377         static fcoord_c fived_table[5] =
378         {
379                 {.0, .0}};
380         float       fifth = 8 * atan(1.) / 5;
381         register int i;
382         register float r;
383         register fcoord_c offset;
384
385         *pt = tp->origin;
386         offset.x = 0.0;
387         offset.y = 0.0;
388         if (fived_table[0].x == .0)
389                 for (i = 0; i < 5; i++) {
390                         fived_table[i].x = cos(fifth * i);
391                         fived_table[i].y = sin(fifth * i);
392                 }
393         for (i = 0; i < 5; i++) {
394                 r = fived[i] * tp->edge_length;
395                 offset.x += r * fived_table[i].x;
396                 offset.y -= r * fived_table[i].y;
397         }
398         (*pt).x += (int) (offset.x + .5);
399         (*pt).y += (int) (offset.y + .5);
400 }
401
402
403 /* Mop up dynamic data for one screen. */
404 static void
405 free_penrose(tiling_c * tp)
406 {
407         register fringe_node_c *fp1, *fp2;
408         register forced_node_c *lp1, *lp2;
409
410         if (tp->fringe.nodes == NULL)
411                 return;
412         fp1 = tp->fringe.nodes;
413         do {
414                 fp2 = fp1;
415                 fp1 = fp1->next;
416                 (void) free((void *) fp2);
417         } while (fp1 != tp->fringe.nodes);
418         tp->fringe.nodes = (fringe_node_c *) NULL;
419         for (lp1 = tp->forced.first; lp1 != 0;) {
420                 lp2 = lp1;
421                 lp1 = lp1->next;
422                 (void) free((void *) lp2);
423         }
424         tp->forced.first = 0;
425 }
426
427
428 /* Called to init the mode. */
429 void
430 init_penrose(ModeInfo * mi)
431 {
432         tiling_c   *tp;
433         fringe_node_c *fp;
434         int         i, size;
435
436         if (tilings == NULL) {
437                 if ((tilings = (tiling_c *) calloc(MI_NUM_SCREENS(mi),
438                                                  sizeof (tiling_c))) == NULL)
439                         return;
440         }
441         tp = &tilings[MI_SCREEN(mi)];
442
443 #if 0 /* if you do this, then the -ammann and -no-ammann options don't work.
444          -- jwz */
445         if (MI_IS_FULLRANDOM(mi))
446                 tp->ammann = (Bool) (LRAND() & 1);
447         else
448 #endif /* 0 */
449                 tp->ammann = ammann;
450
451         tp->done = False;
452         tp->busyLoop = 0;
453         tp->failures = 0;
454         tp->width = MI_WIDTH(mi);
455         tp->height = MI_HEIGHT(mi);
456         if (MI_NPIXELS(mi) > 2) {
457                 tp->thick_color = NRAND(MI_NPIXELS(mi));
458                 /* Insure good contrast */
459                 tp->thin_color = (NRAND(2 * MI_NPIXELS(mi) / 3) + tp->thick_color +
460                                   MI_NPIXELS(mi) / 6) % MI_NPIXELS(mi);
461         }
462         size = MI_SIZE(mi);
463         if (size < -MINSIZE)
464                 tp->edge_length = NRAND(MIN(-size, MAX(MINSIZE,
465                    MIN(tp->width, tp->height) / 2)) - MINSIZE + 1) + MINSIZE;
466         else if (size < MINSIZE) {
467                 if (!size)
468                         tp->edge_length = MAX(MINSIZE, MIN(tp->width, tp->height) / 2);
469                 else
470                         tp->edge_length = MINSIZE;
471         } else
472                 tp->edge_length = MIN(size, MAX(MINSIZE,
473                                             MIN(tp->width, tp->height) / 2));
474         tp->origin.x = (tp->width / 2 + NRAND(tp->width)) / 2;
475         tp->origin.y = (tp->height / 2 + NRAND(tp->height)) / 2;
476         tp->fringe.n_nodes = 2;
477         if (tp->fringe.nodes != NULL)
478                 free_penrose(tp);
479         if (tp->fringe.nodes != NULL || tp->forced.first != 0) {
480                 if (MI_IS_VERBOSE(mi)) {
481                         (void) fprintf(stderr, "Weirdness in init_penrose()\n");
482                         (void) fprintf(stderr, "tp->fringe.nodes = NULL && tp->forced.first = 0\n");
483                 }
484                 free_penrose(tp);       /* Try again */
485                 tp->done = True;
486         }
487         tp->forced.n_nodes = tp->forced.n_visible = 0;
488         if ((fp = tp->fringe.nodes = ALLOC_NODE(fringe_node_c)) == NULL) {
489                 free_penrose(tp);
490                 return;
491         }
492         if (fp == 0) {
493                 if (MI_IS_VERBOSE(mi)) {
494                         (void) fprintf(stderr, "Weirdness in init_penrose()\n");
495                         (void) fprintf(stderr, "fp = 0\n");
496                 }
497                 if ((fp = tp->fringe.nodes = ALLOC_NODE(fringe_node_c)) == NULL) {
498                         free_penrose(tp);
499                         return;
500                 }
501                 tp->done = True;
502         }
503         /* First vertex. */
504         fp->rule_mask = (1 << N_VERTEX_RULES) - 1;
505         fp->list_ptr = 0;
506         if  ((fp->prev = fp->next = ALLOC_NODE(fringe_node_c)) == NULL) {
507                 free_penrose(tp);
508                 return;
509         }
510         if (fp->next == 0) {
511                 if (MI_IS_VERBOSE(mi)) {
512                         (void) fprintf(stderr, "Weirdness in init_penrose()\n");
513                         (void) fprintf(stderr, "fp->next = 0\n");
514                 }
515                 if ((fp->prev = fp->next = ALLOC_NODE(fringe_node_c)) == NULL) {
516                         free_penrose(tp);
517                         return;
518                 }
519                 tp->done = True;
520         }
521         fp->n_tiles = 0;
522         fp->loc = tp->origin;
523         fp->off_screen = False;
524         for (i = 0; i < 5; i++)
525                 fp->fived[i] = 0;
526
527         /* Second vertex. */
528         *(fp->next) = *fp;
529         fp->next->prev = fp->next->next = fp;
530         fp = fp->next;
531         i = NRAND(5);
532         fp->fived[i] = 2 * NRAND(2) - 1;
533         fived_to_loc(fp->fived, tp, &(fp->loc));
534         /* That's it!  We have created our first edge. */
535 }
536
537 /*-
538  * This attempts to match the configuration of vertex with the vertex
539  * rules.   The return value is a total match count.  If matches is
540  * non-null, it will be used to store information about the matches
541  * and must be large enough to contain it.  To play it absolutely
542  * safe, allocate room for MAX_TILES_PER_VERTEX * N_VERTEX_RULES
543  * entries when searching all matches.   The rule mask of vertex will
544  * be applied and rules masked out will not be searched.  Only strict
545  * subsequences match.  If first_only is true, the search stops when
546  * the first match is found.  Otherwise all matches will be found and
547  * the rule_mask of vertex will be updated, which also happens in
548  * single-match mode if no match is found.
549  */
550 static int
551 match_rules(fringe_node_c * vertex, rule_match_c * matches, int first_only)
552 {
553         /* I will assume that I can fit all the relevant bits in vertex->tiles
554            into one unsigned long.  With 3 bits per element and at most 7
555            elements this means 21 bits, which should leave plenty of room.
556            After packing the bits the rest is just integer comparisons and
557            some bit shuffling.  This is essentially Rabin-Karp without
558            congruence arithmetic. */
559         register int i, j;
560         int         hits = 0, good_rules[N_VERTEX_RULES], n_good = 0;
561         unsigned long
562                     vertex_hash = 0, lower_bits_mask = ~(VT_TOTAL_MASK << VT_BITS * (vertex->n_tiles - 1));
563         unsigned    new_rule_mask = 0;
564
565         for (i = 0; i < N_VERTEX_RULES; i++)
566                 if (vertex->n_tiles >= vertex_rules[i].n_tiles)
567                         vertex->rule_mask &= ~(1 << i);
568                 else if (vertex->rule_mask & 1 << i)
569                         good_rules[n_good++] = i;
570         for (i = 0; i < vertex->n_tiles; i++)
571                 vertex_hash |= (unsigned long) vertex->tiles[i] << (VT_BITS * i);
572
573         for (j = 0; j < n_good; j++) {
574                 unsigned long rule_hash = 0;
575                 vertex_rule_c *vr = vertex_rules + good_rules[j];
576
577                 for (i = 0; i < vertex->n_tiles; i++)
578                         rule_hash |= (unsigned long) vr->tiles[i] << (VT_BITS * i);
579                 if (rule_hash == vertex_hash) {
580                         if (matches != 0) {
581                                 matches[hits].rule = good_rules[j];
582                                 matches[hits].pos = 0;
583                         }
584                         hits++;
585                         if (first_only)
586                                 return hits;
587                         else
588                                 new_rule_mask |= 1 << good_rules[j];
589                 }
590                 for (i = vr->n_tiles - 1; i > 0; i--) {
591                         rule_hash = vr->tiles[i] | (rule_hash & lower_bits_mask) << VT_BITS;
592                         if (vertex_hash == rule_hash) {
593                                 if (matches != 0) {
594                                         matches[hits].rule = good_rules[j];
595                                         matches[hits].pos = i;
596                                 }
597                                 hits++;
598                                 if (first_only)
599                                         return hits;
600                                 else
601                                         new_rule_mask |= 1 << good_rules[j];
602                         }
603                 }
604         }
605         vertex->rule_mask = new_rule_mask;
606         return hits;
607 }
608
609
610 /*-
611  * find_completions finds the possible ways to add a tile to a vertex.
612  * The return values is the number of such possibilities.  You must
613  * first call match_rules to produce matches and n_matches.  sides
614  * specifies which side of the vertex to extend and can be S_LEFT or
615  * S_RIGHT.  If results is non-null, it should point to an array large
616  * enough to contain the results, which will be stored there.
617  * MAX_COMPL elements will always suffice.  If first_only is true we
618  * stop as soon as we find one possibility (NOT USED).
619  */
620 #define MAX_COMPL 2
621
622 static int
623 find_completions(fringe_node_c * vertex, rule_match_c * matches, int n_matches,
624                unsigned side, vertex_type_c * results /*, int first_only */ )
625 {
626         int         n_res = 0, cont;
627         register int i, j;
628         vertex_type_c buf[MAX_COMPL];
629
630         if (results == 0)
631                 results = buf;
632         if (n_matches <= 0)
633                 return 0;
634         for (i = 0; i < n_matches; i++) {
635                 vertex_rule_c *rule = vertex_rules + matches[i].rule;
636                 int         pos = (matches[i].pos
637                    + (side == S_RIGHT ? vertex->n_tiles : rule->n_tiles - 1))
638                 % rule->n_tiles;
639                 vertex_type_c vtype = rule->tiles[pos];
640
641                 cont = 1;
642                 for (j = 0; j < n_res; j++)
643                         if (vtype == results[j]) {
644                                 cont = 0;
645                                 break;
646                         }
647                 if (cont)
648                         results[n_res++] = vtype;
649         }
650         return n_res;
651 }
652
653
654 /*-
655  * Draw a tile on the display.  Vertices must be given in a
656  * counterclockwise order.  vtype is the vertex type of v1 (and thus
657  * also gives the tile type).
658  */
659 static void
660 draw_tile(fringe_node_c * v1, fringe_node_c * v2,
661           fringe_node_c * v3, fringe_node_c * v4,
662           vertex_type_c vtype, ModeInfo * mi)
663 {
664         Display    *display = MI_DISPLAY(mi);
665         Window      window = MI_WINDOW(mi);
666         GC          gc = MI_GC(mi);
667         tiling_c   *tp = &tilings[MI_SCREEN(mi)];
668         XPoint      pts[5];
669         vertex_type_c corner = vtype & VT_CORNER_MASK;
670
671         if (v1->off_screen && v2->off_screen && v3->off_screen && v4->off_screen)
672                 return;
673         pts[corner] = v1->loc;
674         pts[VT_RIGHT(corner)] = v2->loc;
675         pts[VT_FAR(corner)] = v3->loc;
676         pts[VT_LEFT(corner)] = v4->loc;
677         pts[4] = pts[0];
678         if (MI_NPIXELS(mi) > 2) {
679                 if ((vtype & VT_TYPE_MASK) == VT_THICK)
680                         XSetForeground(display, gc, MI_PIXEL(mi, tp->thick_color));
681                 else
682                         XSetForeground(display, gc, MI_PIXEL(mi, tp->thin_color));
683         } else
684                 XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
685         XFillPolygon(display, window, gc, pts, 4, Convex, CoordModeOrigin);
686         XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
687         XDrawLines(display, window, gc, pts, 5, CoordModeOrigin);
688
689         if (tp->ammann) {
690                 /* Draw some Ammann lines for debugging purposes.  This will probably
691                    fail miserably on a b&w display. */
692
693                 if ((vtype & VT_TYPE_MASK) == VT_THICK) {
694                         static float r = .0;
695
696                         if (r == .0) {
697                                 float       pi10 = 2 * atan(1.) / 5;
698
699                                 r = 1 - sin(pi10) / (2 * sin(3 * pi10));
700                         }
701                         if (MI_NPIXELS(mi) > 2)
702                                 XSetForeground(display, gc, MI_PIXEL(mi, tp->thin_color));
703                         else {
704                                 XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
705                                 XSetLineAttributes(display, gc, 1, LineOnOffDash, CapNotLast, JoinMiter);
706                         }
707                         XDrawLine(display, window, gc,
708                               (int) (r * pts[3].x + (1 - r) * pts[0].x + .5),
709                               (int) (r * pts[3].y + (1 - r) * pts[0].y + .5),
710                               (int) (r * pts[1].x + (1 - r) * pts[0].x + .5),
711                              (int) (r * pts[1].y + (1 - r) * pts[0].y + .5));
712                         if (MI_NPIXELS(mi) <= 2)
713                                 XSetLineAttributes(display, gc, 1, LineSolid, CapNotLast, JoinMiter);
714                 } else {
715                         if (MI_NPIXELS(mi) > 2)
716                                 XSetForeground(display, gc, MI_PIXEL(mi, tp->thick_color));
717                         else {
718                                 XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
719                                 XSetLineAttributes(display, gc, 1, LineOnOffDash, CapNotLast, JoinMiter);
720                         }
721                         XDrawLine(display, window, gc,
722                                   (int) ((pts[3].x + pts[2].x) / 2 + .5),
723                                   (int) ((pts[3].y + pts[2].y) / 2 + .5),
724                                   (int) ((pts[1].x + pts[2].x) / 2 + .5),
725                                   (int) ((pts[1].y + pts[2].y) / 2 + .5));
726                         if (MI_NPIXELS(mi) <= 2)
727                                 XSetLineAttributes(display, gc, 1, LineSolid, CapNotLast, JoinMiter);
728                 }
729         }
730 }
731
732 /*-
733  * Update the status of this vertex on the forced vertex queue.  If
734  * the vertex has become untileable set tp->done.  This is supposed
735  * to detect dislocations -- never call this routine with a completely
736  * tiled vertex.
737  *
738  * Check for untileable vertices in check_vertex and stop tiling as
739  * soon as one finds one.  I don't know if it is possible to run out
740  * of forced vertices while untileable vertices exist (or will
741  * cavities inevitably appear).  If this can happen, add_random_tile
742  * might get called with an untileable vertex, causing ( n <= 1).
743  * (This is what the tp->done checks for).
744  *
745  * A delayLoop celebrates the dislocation.
746  */
747 static void
748 check_vertex(ModeInfo * mi, fringe_node_c * vertex, tiling_c * tp)
749 {
750         rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES];
751         int         n_hits = match_rules(vertex, hits, False);
752         unsigned    forced_sides = 0;
753
754         if (vertex->rule_mask == 0) {
755                 tp->done = True;
756                 if (MI_IS_VERBOSE(mi)) {
757                         (void) fprintf(stderr, "Dislocation occurred!\n");
758                 }
759                 tp->busyLoop = CELEBRATE;       /* Should be able to recover */
760         }
761         if (1 == find_completions(vertex, hits, n_hits, S_LEFT, 0 /*, False */ ))
762                 forced_sides |= S_LEFT;
763         if (1 == find_completions(vertex, hits, n_hits, S_RIGHT, 0 /*, False */ ))
764                 forced_sides |= S_RIGHT;
765         if (forced_sides == 0) {
766                 if (vertex->list_ptr != 0) {
767                         forced_node_c *node = *vertex->list_ptr;
768
769                         *vertex->list_ptr = node->next;
770                         if (node->next != 0)
771                                 node->next->vertex->list_ptr = vertex->list_ptr;
772                         (void) free((void *) node);
773                         tp->forced.n_nodes--;
774                         if (!vertex->off_screen)
775                                 tp->forced.n_visible--;
776                         vertex->list_ptr = 0;
777                 }
778         } else {
779                 forced_node_c *node;
780
781                 if (vertex->list_ptr == 0) {
782                         if ((node = ALLOC_NODE(forced_node_c)) == NULL)
783                                 return;
784                         node->vertex = vertex;
785                         node->next = tp->forced.first;
786                         if (tp->forced.first != 0)
787                                 tp->forced.first->vertex->list_ptr = &(node->next);
788                         tp->forced.first = node;
789                         vertex->list_ptr = &(tp->forced.first);
790                         tp->forced.n_nodes++;
791                         if (!vertex->off_screen)
792                                 tp->forced.n_visible++;
793                 } else
794                         node = *vertex->list_ptr;
795                 node->forced_sides = forced_sides;
796         }
797 }
798
799
800 /*-
801  * Delete this vertex.  If the vertex is a member of the forced vertex queue,
802  * also remove that entry.  We assume that the vertex is no longer
803  * connected to the fringe.  Note that tp->fringe.nodes must not point to
804  * the vertex being deleted.
805  */
806 static void
807 delete_vertex(ModeInfo * mi, fringe_node_c * vertex, tiling_c * tp)
808 {
809         if (tp->fringe.nodes == vertex) {
810                 tp->done = True;
811                 if (MI_IS_VERBOSE(mi)) {
812                         (void) fprintf(stderr, "Weirdness in delete_penrose()\n");
813                         (void) fprintf(stderr, "tp->fringe.nodes == vertex\n");
814                 }
815                 tp->busyLoop = CELEBRATE;
816         }
817         if (vertex->list_ptr != 0) {
818                 forced_node_c *node = *vertex->list_ptr;
819
820                 *vertex->list_ptr = node->next;
821                 if (node->next != 0)
822                         node->next->vertex->list_ptr = vertex->list_ptr;
823                 (void) free((void *) node);
824                 tp->forced.n_nodes--;
825                 if (!vertex->off_screen)
826                         tp->forced.n_visible--;
827         }
828         if (!vertex->off_screen)
829                 tp->fringe.n_nodes--;
830         (void) free((void *) vertex);
831 }
832
833
834 /*-
835  * Check whether the addition of a tile of type vtype would completely fill
836  * the space available at vertex.
837  */
838 static int
839 fills_vertex(ModeInfo * mi, vertex_type_c vtype, fringe_node_c * vertex)
840 {
841         return
842                 (vertex_dir(mi, vertex, S_LEFT) - vertex_dir(mi, vertex, S_RIGHT)
843                  - vtype_angle(vtype)) % 10 == 0;
844 }
845
846
847 /*-
848  * If you were to add a tile of type vtype to a specified side of
849  * vertex, fringe_changes tells you which other vertices it would
850  * attach to.  The addresses of these vertices will be stored in the
851  * last three arguments.  Null is stored if the corresponding vertex
852  * would need to be allocated.
853  *
854  * The function also analyzes which vertices would be swallowed by the tiling
855  * and thus cut off from the fringe.  The result is returned as a bit pattern.
856  */
857 #define FC_BAG 1                /* Total enclosure.  Should never occur. */
858 #define FC_NEW_RIGHT 2
859 #define FC_NEW_FAR 4
860 #define FC_NEW_LEFT 8
861 #define FC_NEW_MASK 0xe
862 #define FC_CUT_THIS 0x10
863 #define FC_CUT_RIGHT 0x20
864 #define FC_CUT_FAR 0x40
865 #define FC_CUT_LEFT 0x80
866 #define FC_CUT_MASK 0xf0
867 #define FC_TOTAL_MASK 0xff
868
869 static unsigned
870 fringe_changes(ModeInfo * mi, fringe_node_c * vertex,
871                unsigned side, vertex_type_c vtype,
872                fringe_node_c ** right, fringe_node_c ** far,
873                fringe_node_c ** left)
874 {
875         fringe_node_c *v, *f = (fringe_node_c *) NULL;
876         unsigned    result = FC_NEW_FAR;        /* We clear this later if necessary. */
877
878         if (far)
879                 *far = 0;
880         if (fills_vertex(mi, vtype, vertex)) {
881                 result |= FC_CUT_THIS;
882         } else if (side == S_LEFT) {
883                 result |= FC_NEW_RIGHT;
884                 if (right)
885                         *right = 0;
886         } else {
887                 result |= FC_NEW_LEFT;
888                 if (left)
889                         *left = 0;
890         }
891
892         if (!(result & FC_NEW_LEFT)) {
893                 v = vertex->next;
894                 if (left)
895                         *left = v;
896                 if (fills_vertex(mi, VT_LEFT(vtype), v)) {
897                         result = (result & ~FC_NEW_FAR) | FC_CUT_LEFT;
898                         f = v->next;
899                         if (far)
900                                 *far = f;
901                 }
902         }
903         if (!(result & FC_NEW_RIGHT)) {
904                 v = vertex->prev;
905                 if (right)
906                         *right = v;
907                 if (fills_vertex(mi, VT_RIGHT(vtype), v)) {
908                         result = (result & ~FC_NEW_FAR) | FC_CUT_RIGHT;
909                         f = v->prev;
910                         if (far)
911                                 *far = f;
912                 }
913         }
914         if (!(result & FC_NEW_FAR)
915             && fills_vertex(mi, VT_FAR(vtype), f)) {
916                 result |= FC_CUT_FAR;
917                 result &= (~FC_NEW_LEFT & ~FC_NEW_RIGHT);
918                 if (right && (result & FC_CUT_LEFT))
919                         *right = f->next;
920                 if (left && (result & FC_CUT_RIGHT))
921                         *left = f->prev;
922         }
923         if (((result & FC_CUT_LEFT) && (result & FC_CUT_RIGHT))
924             || ((result & FC_CUT_THIS) && (result & FC_CUT_FAR)))
925                 result |= FC_BAG;
926         return result;
927 }
928
929
930 /* A couple of lesser helper functions for add_tile. */
931 static void
932 add_vtype(fringe_node_c * vertex, unsigned side, vertex_type_c vtype)
933 {
934         if (side == S_RIGHT)
935                 vertex->tiles[vertex->n_tiles++] = vtype;
936         else {
937                 register int i;
938
939                 for (i = vertex->n_tiles; i > 0; i--)
940                         vertex->tiles[i] = vertex->tiles[i - 1];
941                 vertex->tiles[0] = vtype;
942                 vertex->n_tiles++;
943         }
944 }
945
946 static fringe_node_c *
947 alloc_vertex(ModeInfo * mi, angle_c dir, fringe_node_c * from, tiling_c * tp)
948 {
949         fringe_node_c *v;
950
951         if ((v = ALLOC_NODE(fringe_node_c)) == NULL) {
952                 tp->done = True;
953                 if (MI_IS_VERBOSE(mi)) {
954                         (void) fprintf(stderr, "No memory in alloc_vertex()\n");
955                 }
956                 tp->busyLoop = CELEBRATE;
957                 return v;
958         }
959         *v = *from;
960         add_unit_vec(dir, v->fived);
961         fived_to_loc(v->fived, tp, &(v->loc));
962         if (v->loc.x < 0 || v->loc.y < 0
963             || v->loc.x >= tp->width || v->loc.y >= tp->height) {
964                 v->off_screen = True;
965                 if (v->loc.x < -tp->width || v->loc.y < -tp->height
966                   || v->loc.x >= 2 * tp->width || v->loc.y >= 2 * tp->height)
967                         tp->done = True;
968         } else {
969                 v->off_screen = False;
970                 tp->fringe.n_nodes++;
971         }
972         v->n_tiles = 0;
973         v->rule_mask = (1 << N_VERTEX_RULES) - 1;
974         v->list_ptr = 0;
975         return v;
976 }
977
978 /*-
979  * Add a tile described by vtype to the side of vertex.  This must be
980  * allowed by the rules -- we do not check it here.  New vertices are
981  * allocated as necessary.  The fringe and the forced vertex pool are updated.
982  * The new tile is drawn on the display.
983  *
984  * One thing we do check here is whether the new tile causes an untiled
985  * area to become enclosed by the tiling.  If this would happen, the tile
986  * is not added.  The return value is true iff a tile was added.
987  */
988 static int
989 add_tile(ModeInfo * mi,
990          fringe_node_c * vertex, unsigned side, vertex_type_c vtype)
991 {
992         tiling_c   *tp = &tilings[MI_SCREEN(mi)];
993
994         fringe_node_c
995                 *left = (fringe_node_c *) NULL,
996                 *right = (fringe_node_c *) NULL,
997                 *far = (fringe_node_c *) NULL,
998                 *node;
999         unsigned    fc = fringe_changes(mi, vertex, side, vtype, &right, &far, &left);
1000
1001         vertex_type_c
1002                 ltype = VT_LEFT(vtype),
1003                 rtype = VT_RIGHT(vtype),
1004                 ftype = VT_FAR(vtype);
1005
1006         /* By our conventions vertex->next lies to the left of vertex and
1007            vertex->prev to the right. */
1008
1009         /* This should never occur. */
1010         if (fc & FC_BAG) {
1011                 tp->done = True;
1012                 if (MI_IS_VERBOSE(mi)) {
1013                         (void) fprintf(stderr, "Weirdness in add_tile()\n");
1014                         (void) fprintf(stderr, "fc = %d, FC_BAG = %d\n", fc, FC_BAG);
1015                 }
1016         }
1017         if (side == S_LEFT) {
1018                 if (right == NULL)
1019                         if ((right = alloc_vertex(mi, vertex_dir(mi, vertex, S_LEFT) -
1020                                         vtype_angle(vtype), vertex, tp)) == NULL)
1021                                 return False;
1022                 if (far == NULL)
1023                         if ((far = alloc_vertex(mi, vertex_dir(mi, left, S_RIGHT) +
1024                                         vtype_angle(ltype), left, tp)) == NULL)
1025                                 return False;
1026         } else {
1027                 if (left == NULL)
1028                         if ((left = alloc_vertex(mi, vertex_dir(mi, vertex, S_RIGHT) +
1029                                         vtype_angle(vtype), vertex, tp)) == NULL)
1030                                 return False;
1031                 if (far == NULL)
1032                         if ((far = alloc_vertex(mi, vertex_dir(mi, right, S_LEFT) -
1033                                         vtype_angle(rtype), right, tp)) == NULL)
1034                                 return False;
1035         }
1036
1037         /* Having allocated the new vertices, but before joining them with
1038            the rest of the fringe, check if vertices with same coordinates
1039            already exist.  If any such are found, give up. */
1040         node = tp->fringe.nodes;
1041         do {
1042                 if (((fc & FC_NEW_LEFT) && fived_equal(node->fived, left->fived))
1043                     || ((fc & FC_NEW_RIGHT) && fived_equal(node->fived, right->fived))
1044                     || ((fc & FC_NEW_FAR) && fived_equal(node->fived, far->fived))) {
1045                         /* Better luck next time. */
1046                         if (fc & FC_NEW_LEFT)
1047                                 delete_vertex(mi, left, tp);
1048                         if (fc & FC_NEW_RIGHT)
1049                                 delete_vertex(mi, right, tp);
1050                         if (fc & FC_NEW_FAR)
1051                                 delete_vertex(mi, far, tp);
1052                         return False;
1053                 }
1054                 node = node->next;
1055         } while (node != tp->fringe.nodes);
1056
1057         /* Rechain. */
1058         if (!(fc & FC_CUT_THIS)) {
1059                 if (side == S_LEFT) {
1060                         vertex->next = right;
1061                         right->prev = vertex;
1062                 } else {
1063                         vertex->prev = left;
1064                         left->next = vertex;
1065                 }
1066         }
1067         if (!(fc & FC_CUT_FAR)) {
1068                 if (!(fc & FC_CUT_LEFT)) {
1069                         far->next = left;
1070                         left->prev = far;
1071                 }
1072                 if (!(fc & FC_CUT_RIGHT)) {
1073                         far->prev = right;
1074                         right->next = far;
1075                 }
1076         }
1077         draw_tile(vertex, right, far, left, vtype, mi);
1078
1079         /* Delete vertices that are no longer on the fringe.  Check the others. */
1080         if (fc & FC_CUT_THIS) {
1081                 tp->fringe.nodes = far;
1082                 delete_vertex(mi, vertex, tp);
1083         } else {
1084                 add_vtype(vertex, side, vtype);
1085                 check_vertex(mi, vertex, tp);
1086                 tp->fringe.nodes = vertex;
1087         }
1088         if (fc & FC_CUT_FAR)
1089                 delete_vertex(mi, far, tp);
1090         else {
1091                 add_vtype(far, fc & FC_CUT_RIGHT ? S_LEFT : S_RIGHT, ftype);
1092                 check_vertex(mi, far, tp);
1093         }
1094         if (fc & FC_CUT_LEFT)
1095                 delete_vertex(mi, left, tp);
1096         else {
1097                 add_vtype(left, fc & FC_CUT_FAR ? S_LEFT : S_RIGHT, ltype);
1098                 check_vertex(mi, left, tp);
1099         }
1100         if (fc & FC_CUT_RIGHT)
1101                 delete_vertex(mi, right, tp);
1102         else {
1103                 add_vtype(right, fc & FC_CUT_FAR ? S_RIGHT : S_LEFT, rtype);
1104                 check_vertex(mi, right, tp);
1105         }
1106         return True;
1107 }
1108
1109
1110 /*-
1111  * Add a forced tile to a given forced vertex.  Basically an easy job,
1112  * since we know what to add.  But it might fail if adding the tile
1113  * would cause some untiled area to become enclosed.  There is also another
1114  * more exotic culprit: we might have a dislocation.  Fortunately, they
1115  * are very rare (the PRL article reported that perfect tilings of over
1116  * 2^50 tiles had been generated).  There is a version of the algorithm
1117  * that doesn't produce dislocations, but it's a lot hairier than the
1118  * simpler version I used.
1119  */
1120 static int
1121 add_forced_tile(ModeInfo * mi, forced_node_c * node)
1122 {
1123         tiling_c   *tp = &tilings[MI_SCREEN(mi)];
1124         unsigned    side;
1125         vertex_type_c vtype;
1126         rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES];
1127         int         n;
1128
1129         if (node->forced_sides == (S_LEFT | S_RIGHT))
1130                 side = NRAND(2) ? S_LEFT : S_RIGHT;
1131         else
1132                 side = node->forced_sides;
1133         n = match_rules(node->vertex, hits, True);
1134         n = find_completions(node->vertex, hits, n, side, &vtype /*, True */ );
1135         if (n <= 0) {
1136                 tp->done = True;
1137                 if (MI_IS_VERBOSE(mi)) {
1138                         (void) fprintf(stderr, "Weirdness in add_forced_tile()\n");
1139                         (void) fprintf(stderr, "n = %d\n", n);
1140                 }
1141         }
1142         return add_tile(mi, node->vertex, side, vtype);
1143 }
1144
1145
1146 /*-
1147  * Whether the addition of a tile of vtype on the given side of vertex
1148  * would conform to the rules.  The efficient way to do this would be
1149  * to add the new tile and then use the same type of search as in
1150  * match_rules.  However, this function is not a performance
1151  * bottleneck (only needed for random tile additions, which are
1152  * relatively infrequent), so I will settle for a simpler implementation.
1153  */
1154 static int
1155 legal_move(fringe_node_c * vertex, unsigned side, vertex_type_c vtype)
1156 {
1157         rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES];
1158         vertex_type_c legal_vt[MAX_COMPL];
1159         int         n_hits, n_legal, i;
1160
1161         n_hits = match_rules(vertex, hits, False);
1162         n_legal = find_completions(vertex, hits, n_hits, side, legal_vt /*, False */ );
1163         for (i = 0; i < n_legal; i++)
1164                 if (legal_vt[i] == vtype)
1165                         return True;
1166         return False;
1167 }
1168
1169
1170 /*-
1171  * Add a randomly chosen tile to a given vertex.  This requires more checking
1172  * as we must make sure the new tile conforms to the vertex rules at every
1173  * vertex it touches. */
1174 static void
1175 add_random_tile(fringe_node_c * vertex, ModeInfo * mi)
1176 {
1177         fringe_node_c *right, *left, *far;
1178         int         i, j, n, n_hits, n_good;
1179         unsigned    side, fc, no_good, s;
1180         vertex_type_c vtypes[MAX_COMPL];
1181         rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES];
1182         tiling_c   *tp = &tilings[MI_SCREEN(mi)];
1183
1184         if (MI_NPIXELS(mi) > 2) {
1185                 tp->thick_color = NRAND(MI_NPIXELS(mi));
1186                 /* Insure good contrast */
1187                 tp->thin_color = (NRAND(2 * MI_NPIXELS(mi) / 3) + tp->thick_color +
1188                                   MI_NPIXELS(mi) / 6) % MI_NPIXELS(mi);
1189         } else
1190                 tp->thick_color = tp->thin_color = MI_WHITE_PIXEL(mi);
1191         n_hits = match_rules(vertex, hits, False);
1192         side = NRAND(2) ? S_LEFT : S_RIGHT;
1193         n = find_completions(vertex, hits, n_hits, side, vtypes /*, False */ );
1194         /* One answer would mean a forced tile. */
1195         if (n <= 0) {
1196                 tp->done = True;
1197                 if (MI_IS_VERBOSE(mi)) {
1198                         (void) fprintf(stderr, "Weirdness in add_random_tile()\n");
1199                         (void) fprintf(stderr, "n = %d\n", n);
1200                 }
1201         }
1202         no_good = 0;
1203         n_good = n;
1204         for (i = 0; i < n; i++) {
1205                 fc = fringe_changes(mi, vertex, side, vtypes[i], &right, &far, &left);
1206                 if (fc & FC_BAG) {
1207                         tp->done = True;
1208                         if (MI_IS_VERBOSE(mi)) {
1209                                 (void) fprintf(stderr, "Weirdness in add_random_tile()\n");
1210                                 (void) fprintf(stderr, "fc = %d, FC_BAG = %d\n", fc, FC_BAG);
1211                         }
1212                 }
1213                 if (right) {
1214                         s = (((fc & FC_CUT_FAR) && (fc & FC_CUT_LEFT)) ? S_RIGHT : S_LEFT);
1215                         if (!legal_move(right, s, VT_RIGHT(vtypes[i]))) {
1216                                 no_good |= (1 << i);
1217                                 n_good--;
1218                                 continue;
1219                         }
1220                 }
1221                 if (left) {
1222                         s = (((fc & FC_CUT_FAR) && (fc & FC_CUT_RIGHT)) ? S_LEFT : S_RIGHT);
1223                         if (!legal_move(left, s, VT_LEFT(vtypes[i]))) {
1224                                 no_good |= (1 << i);
1225                                 n_good--;
1226                                 continue;
1227                         }
1228                 }
1229                 if (far) {
1230                         s = ((fc & FC_CUT_LEFT) ? S_RIGHT : S_LEFT);
1231                         if (!legal_move(far, s, VT_FAR(vtypes[i]))) {
1232                                 no_good |= (1 << i);
1233                                 n_good--;
1234                         }
1235                 }
1236         }
1237         if (n_good <= 0) {
1238                 tp->done = True;
1239                 if (MI_IS_VERBOSE(mi)) {
1240                         (void) fprintf(stderr, "Weirdness in add_random_tile()\n");
1241                         (void) fprintf(stderr, "n_good = %d\n", n_good);
1242                 }
1243         }
1244         n = NRAND(n_good);
1245         for (i = j = 0; i <= n; i++, j++)
1246                 while (no_good & (1 << j))
1247                         j++;
1248
1249         if (!add_tile(mi, vertex, side, vtypes[j - 1])) {
1250                 tp->done = True;
1251                 if (MI_IS_VERBOSE(mi)) {
1252                         (void) fprintf(stderr, "Weirdness in add_random_tile()\n");
1253                 }
1254                 free_penrose(tp);
1255         }
1256 }
1257
1258 /* One step of the growth algorithm. */
1259 void
1260 draw_penrose(ModeInfo * mi)
1261 {
1262         int         i = 0, n;
1263         forced_node_c *p;
1264         tiling_c   *tp;
1265
1266         if (tilings == NULL)
1267                 return;
1268         tp = &tilings[MI_SCREEN(mi)];
1269         if (tp->fringe.nodes == NULL)
1270                 return;
1271
1272         MI_IS_DRAWN(mi) = True;
1273         p = tp->forced.first;
1274         if (tp->busyLoop > 0) {
1275                 tp->busyLoop--;
1276                 return;
1277         }
1278         if (tp->done || tp->failures >= 100) {
1279                 init_penrose(mi);
1280                 return;
1281         }
1282         /* Check for the initial "2-gon". */
1283         if (tp->fringe.nodes->prev == tp->fringe.nodes->next) {
1284                 vertex_type_c vtype = (unsigned char) (VT_TOTAL_MASK & LRAND());
1285
1286                 MI_CLEARWINDOW(mi);
1287
1288                 if (!add_tile(mi, tp->fringe.nodes, S_LEFT, vtype))
1289                         free_penrose(tp);
1290                 return;
1291         }
1292         /* No visible nodes left. */
1293         if (tp->fringe.n_nodes == 0) {
1294                 tp->done = True;
1295                 tp->busyLoop = COMPLETION;      /* Just finished drawing */
1296                 return;
1297         }
1298         if (tp->forced.n_visible > 0 && tp->failures < 10) {
1299                 n = NRAND(tp->forced.n_visible);
1300                 for (;;) {
1301                         while (p->vertex->off_screen)
1302                                 p = p->next;
1303                         if (i++ < n)
1304                                 p = p->next;
1305                         else
1306                                 break;
1307                 }
1308         } else if (tp->forced.n_nodes > 0) {
1309                 n = NRAND(tp->forced.n_nodes);
1310                 while (i++ < n)
1311                         p = p->next;
1312         } else {
1313                 fringe_node_c *fringe_p = tp->fringe.nodes;
1314
1315                 n = NRAND(tp->fringe.n_nodes);
1316                 i = 0;
1317                 for (; i <= n; i++)
1318                         do {
1319                                 fringe_p = fringe_p->next;
1320                         } while (fringe_p->off_screen);
1321                 add_random_tile(fringe_p, mi);
1322                 tp->failures = 0;
1323                 return;
1324         }
1325         if (add_forced_tile(mi, p))
1326                 tp->failures = 0;
1327         else
1328                 tp->failures++;
1329 }
1330
1331
1332 /* Total clean-up. */
1333 void
1334 release_penrose(ModeInfo * mi)
1335 {
1336         if (tilings != NULL) {
1337                 int         screen;
1338
1339                 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
1340                         free_penrose(&tilings[screen]);
1341                 (void) free((void *) tilings);
1342                 tilings = (tiling_c *) NULL;
1343         }
1344 }
1345
1346 #endif /* MODE_penrose */