1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* penrose --- quasiperiodic tilings */
4 /* As reported in News of the Weird:
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."
17 NOTW #491, 4-jul-1997, by Chuck Shepherd.
18 http://www.nine.org/notw/notw.html
21 #if !defined( lint ) && !defined( SABER )
22 static const char sccsid[] = "@(#)penrose.c 5.00 2000/11/01 xlockmore";
27 * Copyright (c) 1996 by Timo Korvola <tkorvola@dopey.hut.fi>
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.
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.
42 * 01-Nov-2000: Allocation checks
43 * 10-May-1997: Jamie Zawinski <jwz@jwz.org> compatible with xscreensaver
44 * 09-Sep-1996: Written.
48 Be careful, this probably still has a few bugs (many of which may only
49 appear with a very low probability). These are seen with -verbose .
50 If one of these are hit penrose will reinitialize.
54 * See Onoda, Steinhardt, DiVincenzo and Socolar in
55 * Phys. Rev. Lett. 60, #25, 1988 or
56 * Strandburg in Computers in Physics, Sep/Oct 1991.
58 * This implementation uses the simpler version of the growth
59 * algorithm, i.e., if there are no forced vertices, a randomly chosen
60 * tile is added to a randomly chosen vertex (no preference for those
63 * There are two essential differences to the algorithm presented in
64 * the literature: First, we do not allow the tiling to enclose an
65 * untiled area. Whenever this is in danger of happening, we just
66 * do not add the tile, hoping for a better random choice the next
67 * time. Second, when choosing a vertex randomly, we will take
68 * one that lies within the viewport if available. If this seems to
69 * cause enclosures in the forced rule case, we will allow invisible
70 * vertices to be chosen.
72 * Tiling is restarted whenever one of the following happens: there
73 * are no incomplete vertices within the viewport or the tiling has
74 * extended a window's length beyond the edge of the window
75 * horizontally or vertically or forced rule choice has failed 100
76 * times due to areas about to become enclosed.
79 * Science News March 23 1985 Vol 127, No. 12
80 * Science News July 16 1988 Vol 134, No. 3
81 * The Economist Sept 17 1988 pg. 100
87 #define PROGCLASS "Penrose"
88 #define HACK_INIT init_penrose
89 #define HACK_DRAW draw_penrose
90 #define penrose_opts xlockmore_opts
91 #define DEFAULTS "*delay: 10000 \n" \
94 #include "xlockmore.h" /* from the xscreensaver distribution */
95 #else /* !STANDALONE */
96 #include "xlock.h" /* from the xlockmore distribution */
97 #endif /* !STANDALONE */
101 #define DEF_AMMANN "False"
105 static XrmOptionDescRec opts[] =
107 {(char *) "-ammann", (char *) ".penrose.ammann", XrmoptionNoArg, (caddr_t) "on"},
108 {(char *) "+ammann", (char *) ".penrose.ammann", XrmoptionNoArg, (caddr_t) "off"}
110 static argtype vars[] =
112 {(caddr_t *) & ammann, (char *) "ammann", (char *) "Ammann", (char *) DEF_AMMANN, t_Bool}
114 static OptionStruct desc[] =
116 {(char *) "-/+ammann", (char *) "turn on/off Ammann lines"}
119 ModeSpecOpt penrose_opts =
120 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
123 ModStruct penrose_description =
124 {"penrose", "init_penrose", "draw_penrose", "release_penrose",
125 "init_penrose", "init_penrose", (char *) NULL, &penrose_opts,
126 10000, 1, 1, -40, 64, 1.0, "",
127 "Shows Penrose's quasiperiodic tilings", 0, NULL};
132 * Annoyingly the ANSI C library people have reserved all identifiers
133 * ending with _t for future use. Hence we use _c as a suffix for
134 * typedefs (c for class, although this is not C++).
140 * In theory one could fit 10 tiles to a single vertex. However, the
141 * vertex rules only allow at most seven tiles to meet at a vertex.
144 #define CELEBRATE 31415 /* This causes a pause, an error occurred. */
145 #define COMPLETION 3141 /* This causes a pause, tiles filled up screen. */
147 #define MAX_TILES_PER_VERTEX 7
148 #define N_VERTEX_RULES 8
149 #define ALLOC_NODE(type) (type *)malloc(sizeof (type))
152 * These are used to specify directions. They can also be used in bit
153 * masks to specify a combination of directions.
160 * We do not actually maintain objects corresponding to the tiles since
161 * we do not really need them and they would only consume memory and
162 * cause additional bookkeeping. Instead we only have vertices, and
163 * each vertex lists the type of each adjacent tile as well as the
164 * position of the vertex on the tile (hereafter refered to as
165 * "corner"). These positions are numbered in counterclockwise order
166 * so that 0 is where two double arrows meet (see one of the
167 * articles). The tile type and vertex number are stored in a single
168 * integer (we use char, and even most of it remains unused).
170 * The primary use of tile objects would be draw traversal, but we do
171 * not currently do redraws at all (we just start over).
173 #define VT_CORNER_MASK 0x3
174 #define VT_TYPE_MASK 0x4
178 #define VT_TOTAL_MASK 0x7
180 typedef unsigned char vertex_type_c;
183 * These allow one to compute the types of the other corners of the tile. If
184 * you are standing at a vertex of type vt looking towards the middle of the
185 * tile, VT_LEFT( vt) is the vertex on your left etc.
187 #define VT_LEFT( vt) ((((vt) - 1) & VT_CORNER_MASK) | (((vt) & VT_TYPE_MASK)))
188 #define VT_RIGHT( vt) ((((vt) + 1) & VT_CORNER_MASK) | (((vt) & VT_TYPE_MASK)))
189 #define VT_FAR( vt) ((vt) ^ 2)
193 * Since we do not do redraws, we only store the vertices we need. These are
194 * the ones with still some empty space around them for the growth algorithm
197 * Here we use a doubly chained ring-like structure as vertices often need
198 * to be removed or inserted (they are kept in geometrical order
199 * circling the tiled area counterclockwise). The ring is refered to by
200 * a pointer to one more or less random node. When deleting nodes one
201 * must make sure that this pointer continues to refer to a valid
202 * node. A vertex count is maintained to make it easier to pick
205 typedef struct forced_node forced_node_c;
207 typedef struct fringe_node {
208 struct fringe_node *prev;
209 struct fringe_node *next;
210 /* These are numbered counterclockwise. The gap, if any, lies
211 between the last and first tiles. */
212 vertex_type_c tiles[MAX_TILES_PER_VERTEX];
214 /* A bit mask used to indicate vertex rules that are still applicable for
215 completing this vertex. Initialize this to (1 << N_VERTEX_RULES) - 1,
216 i.e., all ones, and the rule matching functions will automatically mask
217 out rules that no longer match. */
218 unsigned char rule_mask;
219 /* If the vertex is on the forced vertex list, this points to the
220 pointer to the appropriate node in the list. To remove the
221 vertex from the list just set *list_ptr to the next node,
222 deallocate and decrement node count. */
223 struct forced_node **list_ptr;
224 /* Screen coordinates. */
226 /* We also keep track of 5D coordinates to avoid rounding errors.
227 These are in units of edge length. */
229 /* This is used to quickly check if a vertex is visible. */
230 unsigned char off_screen;
234 fringe_node_c *nodes;
235 /* This does not count off-screen nodes. */
241 * The forced vertex pool contains vertices where at least one
242 * side of the tiled region can only be extended in one way. Note
243 * that this does not necessarily mean that there would only be one
244 * applicable rule. forced_sides are specified using S_LEFT and
245 * S_RIGHT as if looking at the untiled region from the vertex.
248 fringe_node_c *vertex;
249 unsigned forced_sides;
250 struct forced_node *next;
254 forced_node_c *first;
255 int n_nodes, n_visible;
259 /* This is the data related to the tiling of one screen. */
265 forced_pool_c forced;
267 unsigned long thick_color, thin_color;
272 static tiling_c *tilings = (tiling_c *) NULL;
274 /* The tiles are listed in counterclockwise order. */
276 vertex_type_c tiles[MAX_TILES_PER_VERTEX];
280 static vertex_rule_c vertex_rules[N_VERTEX_RULES] =
283 {VT_THICK | 2, VT_THICK | 2, VT_THICK | 2, VT_THICK | 2, VT_THICK | 2}, 5},
285 {VT_THICK | 0, VT_THICK | 0, VT_THICK | 0, VT_THICK | 0, VT_THICK | 0}, 5},
287 {VT_THICK | 0, VT_THICK | 0, VT_THICK | 0, VT_THIN | 0}, 4},
289 {VT_THICK | 2, VT_THICK | 2, VT_THIN | 1, VT_THIN | 3, VT_THICK | 2,
290 VT_THIN | 1, VT_THIN | 3}, 7},
292 {VT_THICK | 2, VT_THICK | 2, VT_THICK | 2, VT_THICK | 2,
293 VT_THIN | 1, VT_THIN | 3}, 6},
295 {VT_THICK | 1, VT_THICK | 3, VT_THIN | 2}, 3},
297 {VT_THICK | 0, VT_THIN | 0, VT_THIN | 0}, 3},
299 {VT_THICK | 2, VT_THIN | 1, VT_THICK | 3, VT_THICK | 1, VT_THIN | 3}, 5}
303 /* Match information returned by match_rules. */
310 /* Occasionally floating point coordinates are needed. */
316 /* All angles are measured in multiples of 36 degrees. */
319 static angle_c vtype_angles[] =
320 {4, 1, 4, 1, 2, 3, 2, 3};
322 #define vtype_angle( v) (vtype_angles[ v])
325 /* Direction angle of an edge. */
327 vertex_dir(ModeInfo * mi, fringe_node_c * vertex, unsigned side)
329 tiling_c *tp = &tilings[MI_SCREEN(mi)];
331 (side == S_LEFT ? vertex->next : vertex->prev);
334 for (i = 0; i < 5; i++)
335 switch (v2->fived[i] - vertex->fived[i]) {
339 return (2 * i + 5) % 10;
342 if (MI_IS_VERBOSE(mi)) {
343 (void) fprintf(stderr,
344 "Weirdness in vertex_dir (this has been reported)\n");
345 for (i = 0; i < 5; i++)
346 (void) fprintf(stderr, "v2->fived[%d]=%d, vertex->fived[%d]=%d\n",
347 i, v2->fived[i], i, vertex->fived[i]);
349 tp->busyLoop = CELEBRATE;
354 /* Move one step to a given direction. */
356 add_unit_vec(angle_c dir, int *fived)
363 fived[dir2i[dir % 5]] += (dir % 2 ? -1 : 1);
367 /* For comparing coordinates. */
368 #define fived_equal( f1, f2) (!memcmp( (f1), (f2), 5 * sizeof( int)))
372 * This computes screen coordinates from 5D representation. Note that X
373 * uses left-handed coordinates (y increases downwards).
376 fived_to_loc(int fived[], tiling_c * tp, XPoint *pt)
378 static fcoord_c fived_table[5] =
381 float fifth = 8 * atan(1.) / 5;
384 register fcoord_c offset;
389 if (fived_table[0].x == .0)
390 for (i = 0; i < 5; i++) {
391 fived_table[i].x = cos(fifth * i);
392 fived_table[i].y = sin(fifth * i);
394 for (i = 0; i < 5; i++) {
395 r = fived[i] * tp->edge_length;
396 offset.x += r * fived_table[i].x;
397 offset.y -= r * fived_table[i].y;
399 (*pt).x += (int) (offset.x + .5);
400 (*pt).y += (int) (offset.y + .5);
404 /* Mop up dynamic data for one screen. */
406 free_penrose(tiling_c * tp)
408 register fringe_node_c *fp1, *fp2;
409 register forced_node_c *lp1, *lp2;
411 if (tp->fringe.nodes == NULL)
413 fp1 = tp->fringe.nodes;
417 (void) free((void *) fp2);
418 } while (fp1 != tp->fringe.nodes);
419 tp->fringe.nodes = (fringe_node_c *) NULL;
420 for (lp1 = tp->forced.first; lp1 != 0;) {
423 (void) free((void *) lp2);
425 tp->forced.first = 0;
429 /* Called to init the mode. */
431 init_penrose(ModeInfo * mi)
437 if (tilings == NULL) {
438 if ((tilings = (tiling_c *) calloc(MI_NUM_SCREENS(mi),
439 sizeof (tiling_c))) == NULL)
442 tp = &tilings[MI_SCREEN(mi)];
444 if (MI_IS_FULLRANDOM(mi))
445 tp->ammann = (Bool) (LRAND() & 1);
451 tp->width = MI_WIDTH(mi);
452 tp->height = MI_HEIGHT(mi);
453 if (MI_NPIXELS(mi) > 2) {
454 tp->thick_color = NRAND(MI_NPIXELS(mi));
455 /* Insure good contrast */
456 tp->thin_color = (NRAND(2 * MI_NPIXELS(mi) / 3) + tp->thick_color +
457 MI_NPIXELS(mi) / 6) % MI_NPIXELS(mi);
461 tp->edge_length = NRAND(MIN(-size, MAX(MINSIZE,
462 MIN(tp->width, tp->height) / 2)) - MINSIZE + 1) + MINSIZE;
463 else if (size < MINSIZE) {
465 tp->edge_length = MAX(MINSIZE, MIN(tp->width, tp->height) / 2);
467 tp->edge_length = MINSIZE;
469 tp->edge_length = MIN(size, MAX(MINSIZE,
470 MIN(tp->width, tp->height) / 2));
471 tp->origin.x = (tp->width / 2 + NRAND(tp->width)) / 2;
472 tp->origin.y = (tp->height / 2 + NRAND(tp->height)) / 2;
473 tp->fringe.n_nodes = 2;
474 if (tp->fringe.nodes != NULL)
476 if (tp->fringe.nodes != NULL || tp->forced.first != 0) {
477 if (MI_IS_VERBOSE(mi)) {
478 (void) fprintf(stderr, "Weirdness in init_penrose()\n");
479 (void) fprintf(stderr, "tp->fringe.nodes = NULL && tp->forced.first = 0\n");
481 free_penrose(tp); /* Try again */
484 tp->forced.n_nodes = tp->forced.n_visible = 0;
485 if ((fp = tp->fringe.nodes = ALLOC_NODE(fringe_node_c)) == NULL) {
490 if (MI_IS_VERBOSE(mi)) {
491 (void) fprintf(stderr, "Weirdness in init_penrose()\n");
492 (void) fprintf(stderr, "fp = 0\n");
494 if ((fp = tp->fringe.nodes = ALLOC_NODE(fringe_node_c)) == NULL) {
501 fp->rule_mask = (1 << N_VERTEX_RULES) - 1;
503 if ((fp->prev = fp->next = ALLOC_NODE(fringe_node_c)) == NULL) {
508 if (MI_IS_VERBOSE(mi)) {
509 (void) fprintf(stderr, "Weirdness in init_penrose()\n");
510 (void) fprintf(stderr, "fp->next = 0\n");
512 if ((fp->prev = fp->next = ALLOC_NODE(fringe_node_c)) == NULL) {
519 fp->loc = tp->origin;
520 fp->off_screen = False;
521 for (i = 0; i < 5; i++)
526 fp->next->prev = fp->next->next = fp;
529 fp->fived[i] = 2 * NRAND(2) - 1;
530 fived_to_loc(fp->fived, tp, &(fp->loc));
531 /* That's it! We have created our first edge. */
535 * This attempts to match the configuration of vertex with the vertex
536 * rules. The return value is a total match count. If matches is
537 * non-null, it will be used to store information about the matches
538 * and must be large enough to contain it. To play it absolutely
539 * safe, allocate room for MAX_TILES_PER_VERTEX * N_VERTEX_RULES
540 * entries when searching all matches. The rule mask of vertex will
541 * be applied and rules masked out will not be searched. Only strict
542 * subsequences match. If first_only is true, the search stops when
543 * the first match is found. Otherwise all matches will be found and
544 * the rule_mask of vertex will be updated, which also happens in
545 * single-match mode if no match is found.
548 match_rules(fringe_node_c * vertex, rule_match_c * matches, int first_only)
550 /* I will assume that I can fit all the relevant bits in vertex->tiles
551 into one unsigned long. With 3 bits per element and at most 7
552 elements this means 21 bits, which should leave plenty of room.
553 After packing the bits the rest is just integer comparisons and
554 some bit shuffling. This is essentially Rabin-Karp without
555 congruence arithmetic. */
557 int hits = 0, good_rules[N_VERTEX_RULES], n_good = 0;
559 vertex_hash = 0, lower_bits_mask = ~(VT_TOTAL_MASK << VT_BITS * (vertex->n_tiles - 1));
560 unsigned new_rule_mask = 0;
562 for (i = 0; i < N_VERTEX_RULES; i++)
563 if (vertex->n_tiles >= vertex_rules[i].n_tiles)
564 vertex->rule_mask &= ~(1 << i);
565 else if (vertex->rule_mask & 1 << i)
566 good_rules[n_good++] = i;
567 for (i = 0; i < vertex->n_tiles; i++)
568 vertex_hash |= (unsigned long) vertex->tiles[i] << (VT_BITS * i);
570 for (j = 0; j < n_good; j++) {
571 unsigned long rule_hash = 0;
572 vertex_rule_c *vr = vertex_rules + good_rules[j];
574 for (i = 0; i < vertex->n_tiles; i++)
575 rule_hash |= (unsigned long) vr->tiles[i] << (VT_BITS * i);
576 if (rule_hash == vertex_hash) {
578 matches[hits].rule = good_rules[j];
579 matches[hits].pos = 0;
585 new_rule_mask |= 1 << good_rules[j];
587 for (i = vr->n_tiles - 1; i > 0; i--) {
588 rule_hash = vr->tiles[i] | (rule_hash & lower_bits_mask) << VT_BITS;
589 if (vertex_hash == rule_hash) {
591 matches[hits].rule = good_rules[j];
592 matches[hits].pos = i;
598 new_rule_mask |= 1 << good_rules[j];
602 vertex->rule_mask = new_rule_mask;
608 * find_completions finds the possible ways to add a tile to a vertex.
609 * The return values is the number of such possibilities. You must
610 * first call match_rules to produce matches and n_matches. sides
611 * specifies which side of the vertex to extend and can be S_LEFT or
612 * S_RIGHT. If results is non-null, it should point to an array large
613 * enough to contain the results, which will be stored there.
614 * MAX_COMPL elements will always suffice. If first_only is true we
615 * stop as soon as we find one possibility (NOT USED).
620 find_completions(fringe_node_c * vertex, rule_match_c * matches, int n_matches,
621 unsigned side, vertex_type_c * results /*, int first_only */ )
625 vertex_type_c buf[MAX_COMPL];
631 for (i = 0; i < n_matches; i++) {
632 vertex_rule_c *rule = vertex_rules + matches[i].rule;
633 int pos = (matches[i].pos
634 + (side == S_RIGHT ? vertex->n_tiles : rule->n_tiles - 1))
636 vertex_type_c vtype = rule->tiles[pos];
639 for (j = 0; j < n_res; j++)
640 if (vtype == results[j]) {
645 results[n_res++] = vtype;
652 * Draw a tile on the display. Vertices must be given in a
653 * counterclockwise order. vtype is the vertex type of v1 (and thus
654 * also gives the tile type).
657 draw_tile(fringe_node_c * v1, fringe_node_c * v2,
658 fringe_node_c * v3, fringe_node_c * v4,
659 vertex_type_c vtype, ModeInfo * mi)
661 Display *display = MI_DISPLAY(mi);
662 Window window = MI_WINDOW(mi);
664 tiling_c *tp = &tilings[MI_SCREEN(mi)];
666 vertex_type_c corner = vtype & VT_CORNER_MASK;
668 if (v1->off_screen && v2->off_screen && v3->off_screen && v4->off_screen)
670 pts[corner] = v1->loc;
671 pts[VT_RIGHT(corner)] = v2->loc;
672 pts[VT_FAR(corner)] = v3->loc;
673 pts[VT_LEFT(corner)] = v4->loc;
675 if (MI_NPIXELS(mi) > 2) {
676 if ((vtype & VT_TYPE_MASK) == VT_THICK)
677 XSetForeground(display, gc, MI_PIXEL(mi, tp->thick_color));
679 XSetForeground(display, gc, MI_PIXEL(mi, tp->thin_color));
681 XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
682 XFillPolygon(display, window, gc, pts, 4, Convex, CoordModeOrigin);
683 XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
684 XDrawLines(display, window, gc, pts, 5, CoordModeOrigin);
687 /* Draw some Ammann lines for debugging purposes. This will probably
688 fail miserably on a b&w display. */
690 if ((vtype & VT_TYPE_MASK) == VT_THICK) {
694 float pi10 = 2 * atan(1.) / 5;
696 r = 1 - sin(pi10) / (2 * sin(3 * pi10));
698 if (MI_NPIXELS(mi) > 2)
699 XSetForeground(display, gc, MI_PIXEL(mi, tp->thin_color));
701 XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
702 XSetLineAttributes(display, gc, 1, LineOnOffDash, CapNotLast, JoinMiter);
704 XDrawLine(display, window, gc,
705 (int) (r * pts[3].x + (1 - r) * pts[0].x + .5),
706 (int) (r * pts[3].y + (1 - r) * pts[0].y + .5),
707 (int) (r * pts[1].x + (1 - r) * pts[0].x + .5),
708 (int) (r * pts[1].y + (1 - r) * pts[0].y + .5));
709 if (MI_NPIXELS(mi) <= 2)
710 XSetLineAttributes(display, gc, 1, LineSolid, CapNotLast, JoinMiter);
712 if (MI_NPIXELS(mi) > 2)
713 XSetForeground(display, gc, MI_PIXEL(mi, tp->thick_color));
715 XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
716 XSetLineAttributes(display, gc, 1, LineOnOffDash, CapNotLast, JoinMiter);
718 XDrawLine(display, window, gc,
719 (int) ((pts[3].x + pts[2].x) / 2 + .5),
720 (int) ((pts[3].y + pts[2].y) / 2 + .5),
721 (int) ((pts[1].x + pts[2].x) / 2 + .5),
722 (int) ((pts[1].y + pts[2].y) / 2 + .5));
723 if (MI_NPIXELS(mi) <= 2)
724 XSetLineAttributes(display, gc, 1, LineSolid, CapNotLast, JoinMiter);
730 * Update the status of this vertex on the forced vertex queue. If
731 * the vertex has become untileable set tp->done. This is supposed
732 * to detect dislocations -- never call this routine with a completely
735 * Check for untileable vertices in check_vertex and stop tiling as
736 * soon as one finds one. I don't know if it is possible to run out
737 * of forced vertices while untileable vertices exist (or will
738 * cavities inevitably appear). If this can happen, add_random_tile
739 * might get called with an untileable vertex, causing ( n <= 1).
740 * (This is what the tp->done checks for).
742 * A delayLoop celebrates the dislocation.
745 check_vertex(ModeInfo * mi, fringe_node_c * vertex, tiling_c * tp)
747 rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES];
748 int n_hits = match_rules(vertex, hits, False);
749 unsigned forced_sides = 0;
751 if (vertex->rule_mask == 0) {
753 if (MI_IS_VERBOSE(mi)) {
754 (void) fprintf(stderr, "Dislocation occurred!\n");
756 tp->busyLoop = CELEBRATE; /* Should be able to recover */
758 if (1 == find_completions(vertex, hits, n_hits, S_LEFT, 0 /*, False */ ))
759 forced_sides |= S_LEFT;
760 if (1 == find_completions(vertex, hits, n_hits, S_RIGHT, 0 /*, False */ ))
761 forced_sides |= S_RIGHT;
762 if (forced_sides == 0) {
763 if (vertex->list_ptr != 0) {
764 forced_node_c *node = *vertex->list_ptr;
766 *vertex->list_ptr = node->next;
768 node->next->vertex->list_ptr = vertex->list_ptr;
769 (void) free((void *) node);
770 tp->forced.n_nodes--;
771 if (!vertex->off_screen)
772 tp->forced.n_visible--;
773 vertex->list_ptr = 0;
778 if (vertex->list_ptr == 0) {
779 if ((node = ALLOC_NODE(forced_node_c)) == NULL)
781 node->vertex = vertex;
782 node->next = tp->forced.first;
783 if (tp->forced.first != 0)
784 tp->forced.first->vertex->list_ptr = &(node->next);
785 tp->forced.first = node;
786 vertex->list_ptr = &(tp->forced.first);
787 tp->forced.n_nodes++;
788 if (!vertex->off_screen)
789 tp->forced.n_visible++;
791 node = *vertex->list_ptr;
792 node->forced_sides = forced_sides;
798 * Delete this vertex. If the vertex is a member of the forced vertex queue,
799 * also remove that entry. We assume that the vertex is no longer
800 * connected to the fringe. Note that tp->fringe.nodes must not point to
801 * the vertex being deleted.
804 delete_vertex(ModeInfo * mi, fringe_node_c * vertex, tiling_c * tp)
806 if (tp->fringe.nodes == vertex) {
808 if (MI_IS_VERBOSE(mi)) {
809 (void) fprintf(stderr, "Weirdness in delete_penrose()\n");
810 (void) fprintf(stderr, "tp->fringe.nodes == vertex\n");
812 tp->busyLoop = CELEBRATE;
814 if (vertex->list_ptr != 0) {
815 forced_node_c *node = *vertex->list_ptr;
817 *vertex->list_ptr = node->next;
819 node->next->vertex->list_ptr = vertex->list_ptr;
820 (void) free((void *) node);
821 tp->forced.n_nodes--;
822 if (!vertex->off_screen)
823 tp->forced.n_visible--;
825 if (!vertex->off_screen)
826 tp->fringe.n_nodes--;
827 (void) free((void *) vertex);
832 * Check whether the addition of a tile of type vtype would completely fill
833 * the space available at vertex.
836 fills_vertex(ModeInfo * mi, vertex_type_c vtype, fringe_node_c * vertex)
839 (vertex_dir(mi, vertex, S_LEFT) - vertex_dir(mi, vertex, S_RIGHT)
840 - vtype_angle(vtype)) % 10 == 0;
845 * If you were to add a tile of type vtype to a specified side of
846 * vertex, fringe_changes tells you which other vertices it would
847 * attach to. The addresses of these vertices will be stored in the
848 * last three arguments. Null is stored if the corresponding vertex
849 * would need to be allocated.
851 * The function also analyzes which vertices would be swallowed by the tiling
852 * and thus cut off from the fringe. The result is returned as a bit pattern.
854 #define FC_BAG 1 /* Total enclosure. Should never occur. */
855 #define FC_NEW_RIGHT 2
857 #define FC_NEW_LEFT 8
858 #define FC_NEW_MASK 0xe
859 #define FC_CUT_THIS 0x10
860 #define FC_CUT_RIGHT 0x20
861 #define FC_CUT_FAR 0x40
862 #define FC_CUT_LEFT 0x80
863 #define FC_CUT_MASK 0xf0
864 #define FC_TOTAL_MASK 0xff
867 fringe_changes(ModeInfo * mi, fringe_node_c * vertex,
868 unsigned side, vertex_type_c vtype,
869 fringe_node_c ** right, fringe_node_c ** far,
870 fringe_node_c ** left)
872 fringe_node_c *v, *f = (fringe_node_c *) NULL;
873 unsigned result = FC_NEW_FAR; /* We clear this later if necessary. */
877 if (fills_vertex(mi, vtype, vertex)) {
878 result |= FC_CUT_THIS;
879 } else if (side == S_LEFT) {
880 result |= FC_NEW_RIGHT;
884 result |= FC_NEW_LEFT;
889 if (!(result & FC_NEW_LEFT)) {
893 if (fills_vertex(mi, VT_LEFT(vtype), v)) {
894 result = (result & ~FC_NEW_FAR) | FC_CUT_LEFT;
900 if (!(result & FC_NEW_RIGHT)) {
904 if (fills_vertex(mi, VT_RIGHT(vtype), v)) {
905 result = (result & ~FC_NEW_FAR) | FC_CUT_RIGHT;
911 if (!(result & FC_NEW_FAR)
912 && fills_vertex(mi, VT_FAR(vtype), f)) {
913 result |= FC_CUT_FAR;
914 result &= (~FC_NEW_LEFT & ~FC_NEW_RIGHT);
915 if (right && (result & FC_CUT_LEFT))
917 if (left && (result & FC_CUT_RIGHT))
920 if (((result & FC_CUT_LEFT) && (result & FC_CUT_RIGHT))
921 || ((result & FC_CUT_THIS) && (result & FC_CUT_FAR)))
927 /* A couple of lesser helper functions for add_tile. */
929 add_vtype(fringe_node_c * vertex, unsigned side, vertex_type_c vtype)
932 vertex->tiles[vertex->n_tiles++] = vtype;
936 for (i = vertex->n_tiles; i > 0; i--)
937 vertex->tiles[i] = vertex->tiles[i - 1];
938 vertex->tiles[0] = vtype;
943 static fringe_node_c *
944 alloc_vertex(ModeInfo * mi, angle_c dir, fringe_node_c * from, tiling_c * tp)
948 if ((v = ALLOC_NODE(fringe_node_c)) == NULL) {
950 if (MI_IS_VERBOSE(mi)) {
951 (void) fprintf(stderr, "No memory in alloc_vertex()\n");
953 tp->busyLoop = CELEBRATE;
957 add_unit_vec(dir, v->fived);
958 fived_to_loc(v->fived, tp, &(v->loc));
959 if (v->loc.x < 0 || v->loc.y < 0
960 || v->loc.x >= tp->width || v->loc.y >= tp->height) {
961 v->off_screen = True;
962 if (v->loc.x < -tp->width || v->loc.y < -tp->height
963 || v->loc.x >= 2 * tp->width || v->loc.y >= 2 * tp->height)
966 v->off_screen = False;
967 tp->fringe.n_nodes++;
970 v->rule_mask = (1 << N_VERTEX_RULES) - 1;
976 * Add a tile described by vtype to the side of vertex. This must be
977 * allowed by the rules -- we do not check it here. New vertices are
978 * allocated as necessary. The fringe and the forced vertex pool are updated.
979 * The new tile is drawn on the display.
981 * One thing we do check here is whether the new tile causes an untiled
982 * area to become enclosed by the tiling. If this would happen, the tile
983 * is not added. The return value is true iff a tile was added.
986 add_tile(ModeInfo * mi,
987 fringe_node_c * vertex, unsigned side, vertex_type_c vtype)
989 tiling_c *tp = &tilings[MI_SCREEN(mi)];
992 *left = (fringe_node_c *) NULL,
993 *right = (fringe_node_c *) NULL,
994 *far = (fringe_node_c *) NULL,
996 unsigned fc = fringe_changes(mi, vertex, side, vtype, &right, &far, &left);
999 ltype = VT_LEFT(vtype),
1000 rtype = VT_RIGHT(vtype),
1001 ftype = VT_FAR(vtype);
1003 /* By our conventions vertex->next lies to the left of vertex and
1004 vertex->prev to the right. */
1006 /* This should never occur. */
1009 if (MI_IS_VERBOSE(mi)) {
1010 (void) fprintf(stderr, "Weirdness in add_tile()\n");
1011 (void) fprintf(stderr, "fc = %d, FC_BAG = %d\n", fc, FC_BAG);
1014 if (side == S_LEFT) {
1016 if ((right = alloc_vertex(mi, vertex_dir(mi, vertex, S_LEFT) -
1017 vtype_angle(vtype), vertex, tp)) == NULL)
1020 if ((far = alloc_vertex(mi, vertex_dir(mi, left, S_RIGHT) +
1021 vtype_angle(ltype), left, tp)) == NULL)
1025 if ((left = alloc_vertex(mi, vertex_dir(mi, vertex, S_RIGHT) +
1026 vtype_angle(vtype), vertex, tp)) == NULL)
1029 if ((far = alloc_vertex(mi, vertex_dir(mi, right, S_LEFT) -
1030 vtype_angle(rtype), right, tp)) == NULL)
1034 /* Having allocated the new vertices, but before joining them with
1035 the rest of the fringe, check if vertices with same coordinates
1036 already exist. If any such are found, give up. */
1037 node = tp->fringe.nodes;
1039 if (((fc & FC_NEW_LEFT) && fived_equal(node->fived, left->fived))
1040 || ((fc & FC_NEW_RIGHT) && fived_equal(node->fived, right->fived))
1041 || ((fc & FC_NEW_FAR) && fived_equal(node->fived, far->fived))) {
1042 /* Better luck next time. */
1043 if (fc & FC_NEW_LEFT)
1044 delete_vertex(mi, left, tp);
1045 if (fc & FC_NEW_RIGHT)
1046 delete_vertex(mi, right, tp);
1047 if (fc & FC_NEW_FAR)
1048 delete_vertex(mi, far, tp);
1052 } while (node != tp->fringe.nodes);
1055 if (!(fc & FC_CUT_THIS)) {
1056 if (side == S_LEFT) {
1057 vertex->next = right;
1058 right->prev = vertex;
1060 vertex->prev = left;
1061 left->next = vertex;
1064 if (!(fc & FC_CUT_FAR)) {
1065 if (!(fc & FC_CUT_LEFT)) {
1069 if (!(fc & FC_CUT_RIGHT)) {
1074 draw_tile(vertex, right, far, left, vtype, mi);
1076 /* Delete vertices that are no longer on the fringe. Check the others. */
1077 if (fc & FC_CUT_THIS) {
1078 tp->fringe.nodes = far;
1079 delete_vertex(mi, vertex, tp);
1081 add_vtype(vertex, side, vtype);
1082 check_vertex(mi, vertex, tp);
1083 tp->fringe.nodes = vertex;
1085 if (fc & FC_CUT_FAR)
1086 delete_vertex(mi, far, tp);
1088 add_vtype(far, fc & FC_CUT_RIGHT ? S_LEFT : S_RIGHT, ftype);
1089 check_vertex(mi, far, tp);
1091 if (fc & FC_CUT_LEFT)
1092 delete_vertex(mi, left, tp);
1094 add_vtype(left, fc & FC_CUT_FAR ? S_LEFT : S_RIGHT, ltype);
1095 check_vertex(mi, left, tp);
1097 if (fc & FC_CUT_RIGHT)
1098 delete_vertex(mi, right, tp);
1100 add_vtype(right, fc & FC_CUT_FAR ? S_RIGHT : S_LEFT, rtype);
1101 check_vertex(mi, right, tp);
1108 * Add a forced tile to a given forced vertex. Basically an easy job,
1109 * since we know what to add. But it might fail if adding the tile
1110 * would cause some untiled area to become enclosed. There is also another
1111 * more exotic culprit: we might have a dislocation. Fortunately, they
1112 * are very rare (the PRL article reported that perfect tilings of over
1113 * 2^50 tiles had been generated). There is a version of the algorithm
1114 * that doesn't produce dislocations, but it's a lot hairier than the
1115 * simpler version I used.
1118 add_forced_tile(ModeInfo * mi, forced_node_c * node)
1120 tiling_c *tp = &tilings[MI_SCREEN(mi)];
1122 vertex_type_c vtype;
1123 rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES];
1126 if (node->forced_sides == (S_LEFT | S_RIGHT))
1127 side = NRAND(2) ? S_LEFT : S_RIGHT;
1129 side = node->forced_sides;
1130 n = match_rules(node->vertex, hits, True);
1131 n = find_completions(node->vertex, hits, n, side, &vtype /*, True */ );
1134 if (MI_IS_VERBOSE(mi)) {
1135 (void) fprintf(stderr, "Weirdness in add_forced_tile()\n");
1136 (void) fprintf(stderr, "n = %d\n", n);
1139 return add_tile(mi, node->vertex, side, vtype);
1144 * Whether the addition of a tile of vtype on the given side of vertex
1145 * would conform to the rules. The efficient way to do this would be
1146 * to add the new tile and then use the same type of search as in
1147 * match_rules. However, this function is not a performance
1148 * bottleneck (only needed for random tile additions, which are
1149 * relatively infrequent), so I will settle for a simpler implementation.
1152 legal_move(fringe_node_c * vertex, unsigned side, vertex_type_c vtype)
1154 rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES];
1155 vertex_type_c legal_vt[MAX_COMPL];
1156 int n_hits, n_legal, i;
1158 n_hits = match_rules(vertex, hits, False);
1159 n_legal = find_completions(vertex, hits, n_hits, side, legal_vt /*, False */ );
1160 for (i = 0; i < n_legal; i++)
1161 if (legal_vt[i] == vtype)
1168 * Add a randomly chosen tile to a given vertex. This requires more checking
1169 * as we must make sure the new tile conforms to the vertex rules at every
1170 * vertex it touches. */
1172 add_random_tile(fringe_node_c * vertex, ModeInfo * mi)
1174 fringe_node_c *right, *left, *far;
1175 int i, j, n, n_hits, n_good;
1176 unsigned side, fc, no_good, s;
1177 vertex_type_c vtypes[MAX_COMPL];
1178 rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES];
1179 tiling_c *tp = &tilings[MI_SCREEN(mi)];
1181 if (MI_NPIXELS(mi) > 2) {
1182 tp->thick_color = NRAND(MI_NPIXELS(mi));
1183 /* Insure good contrast */
1184 tp->thin_color = (NRAND(2 * MI_NPIXELS(mi) / 3) + tp->thick_color +
1185 MI_NPIXELS(mi) / 6) % MI_NPIXELS(mi);
1187 tp->thick_color = tp->thin_color = MI_WHITE_PIXEL(mi);
1188 n_hits = match_rules(vertex, hits, False);
1189 side = NRAND(2) ? S_LEFT : S_RIGHT;
1190 n = find_completions(vertex, hits, n_hits, side, vtypes /*, False */ );
1191 /* One answer would mean a forced tile. */
1194 if (MI_IS_VERBOSE(mi)) {
1195 (void) fprintf(stderr, "Weirdness in add_random_tile()\n");
1196 (void) fprintf(stderr, "n = %d\n", n);
1201 for (i = 0; i < n; i++) {
1202 fc = fringe_changes(mi, vertex, side, vtypes[i], &right, &far, &left);
1205 if (MI_IS_VERBOSE(mi)) {
1206 (void) fprintf(stderr, "Weirdness in add_random_tile()\n");
1207 (void) fprintf(stderr, "fc = %d, FC_BAG = %d\n", fc, FC_BAG);
1211 s = (((fc & FC_CUT_FAR) && (fc & FC_CUT_LEFT)) ? S_RIGHT : S_LEFT);
1212 if (!legal_move(right, s, VT_RIGHT(vtypes[i]))) {
1213 no_good |= (1 << i);
1219 s = (((fc & FC_CUT_FAR) && (fc & FC_CUT_RIGHT)) ? S_LEFT : S_RIGHT);
1220 if (!legal_move(left, s, VT_LEFT(vtypes[i]))) {
1221 no_good |= (1 << i);
1227 s = ((fc & FC_CUT_LEFT) ? S_RIGHT : S_LEFT);
1228 if (!legal_move(far, s, VT_FAR(vtypes[i]))) {
1229 no_good |= (1 << i);
1236 if (MI_IS_VERBOSE(mi)) {
1237 (void) fprintf(stderr, "Weirdness in add_random_tile()\n");
1238 (void) fprintf(stderr, "n_good = %d\n", n_good);
1242 for (i = j = 0; i <= n; i++, j++)
1243 while (no_good & (1 << j))
1246 if (!add_tile(mi, vertex, side, vtypes[j - 1])) {
1248 if (MI_IS_VERBOSE(mi)) {
1249 (void) fprintf(stderr, "Weirdness in add_random_tile()\n");
1255 /* One step of the growth algorithm. */
1257 draw_penrose(ModeInfo * mi)
1263 if (tilings == NULL)
1265 tp = &tilings[MI_SCREEN(mi)];
1266 if (tp->fringe.nodes == NULL)
1269 MI_IS_DRAWN(mi) = True;
1270 p = tp->forced.first;
1271 if (tp->busyLoop > 0) {
1275 if (tp->done || tp->failures >= 100) {
1279 /* Check for the initial "2-gon". */
1280 if (tp->fringe.nodes->prev == tp->fringe.nodes->next) {
1281 vertex_type_c vtype = (unsigned char) (VT_TOTAL_MASK & LRAND());
1285 if (!add_tile(mi, tp->fringe.nodes, S_LEFT, vtype))
1289 /* No visible nodes left. */
1290 if (tp->fringe.n_nodes == 0) {
1292 tp->busyLoop = COMPLETION; /* Just finished drawing */
1295 if (tp->forced.n_visible > 0 && tp->failures < 10) {
1296 n = NRAND(tp->forced.n_visible);
1298 while (p->vertex->off_screen)
1305 } else if (tp->forced.n_nodes > 0) {
1306 n = NRAND(tp->forced.n_nodes);
1310 fringe_node_c *fringe_p = tp->fringe.nodes;
1312 n = NRAND(tp->fringe.n_nodes);
1316 fringe_p = fringe_p->next;
1317 } while (fringe_p->off_screen);
1318 add_random_tile(fringe_p, mi);
1322 if (add_forced_tile(mi, p))
1329 /* Total clean-up. */
1331 release_penrose(ModeInfo * mi)
1333 if (tilings != NULL) {
1336 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
1337 free_penrose(&tilings[screen]);
1338 (void) free((void *) tilings);
1339 tilings = (tiling_c *) NULL;
1343 #endif /* MODE_penrose */