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