http://www.jwz.org/xscreensaver/xscreensaver-5.07.tar.gz
[xscreensaver] / hacks / polyominoes.c
1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* polyominoes --- Shows attempts to place polyominoes into a rectangle */
3
4 #if 0
5 static const char sccsid[] = "@(#)polyominoes.c 5.01 2000/12/18 xlockmore";
6 #endif
7
8 /*
9  * Copyright (c) 2000 by Stephen Montgomery-Smith <stephen@math.missouri.edu>
10  *
11  * Permission to use, copy, modify, and distribute this software and its
12  * documentation for any purpose and without fee is hereby granted,
13  * provided that the above copyright notice appear in all copies and that
14  * both that copyright notice and this permission notice appear in
15  * supporting documentation.
16  *
17  * This file is provided AS IS with no warranties of any kind.  The author
18  * shall have no liability with respect to the infringement of copyrights,
19  * trade secrets or any patents by this file or any part thereof.  In no
20  * event will the author be liable for any lost revenue or profits or
21  * other special, indirect and consequential damages.
22  *
23  * Revision History:
24  * 07-Jan-2001: Made improvement to the search algorithm for the puzzles
25  *              involving identical polyominoes (via the variable 
26  *              reason_to_not_attach).  By Stephen Montgomery-Smith.
27  * 20-Dec-2000: Added more puzzles at David Bagley's request.
28  * 27-Nov-2000: Adapted from euler2d.c Copyright (c) 2000 by Stephen
29  *              Montgomery-Smith
30  * 05-Jun-2000: Adapted from flow.c Copyright (c) 1996 by Tim Auckland
31  * 18-Jul-1996: Adapted from swarm.c Copyright (c) 1991 by Patrick J. Naughton.
32  * 31-Aug-1990: Adapted from xswarm by Jeff Butterworth. (butterwo@ncsc.org)
33  */
34
35 #ifdef STANDALONE
36 # define MODE_polyominoes
37 #define DEFAULTS        "*delay: 10000 \n" \
38                                         "*cycles: 2000 \n" \
39                                         "*ncolors: 64 \n" \
40                                         "*fpsSolid: true \n" \
41
42 # define reshape_polyominoes 0
43 # define polyominoes_handle_event 0
44 # define SMOOTH_COLORS
45 # include "xlockmore.h"         /* in xscreensaver distribution */
46 # include "erase.h"
47 #else /* STANDALONE */
48 # include "xlock.h"             /* in xlockmore distribution */
49 #endif /* STANDALONE */
50
51 #ifdef MODE_polyominoes
52 #define DEF_IDENTICAL "False"
53 #define DEF_PLAIN "False"
54
55 static Bool identical;
56 static Bool plain;
57
58 static XrmOptionDescRec opts[] =
59 {
60   {"-identical", ".polyominoes.identical", XrmoptionNoArg, "on"},
61   {"+identical", ".polyominoes.identical", XrmoptionNoArg, "off"},
62   {"-plain", ".polyominoes.plain", XrmoptionNoArg, "on"},
63   {"+plain", ".polyominoes.plain", XrmoptionNoArg, "off"}
64 };
65 static argtype vars[] =
66 {
67   {&identical, "identical", "Identical", DEF_IDENTICAL, t_Bool},
68   {&plain, "plain", "Plain", DEF_PLAIN, t_Bool}
69 };
70 static OptionStruct desc[] =
71 {
72   {"-/+identical", "turn on/off puzzles where the polyomino pieces are identical"},
73   {"-/+plain", "turn on/off plain pieces"}
74 };
75
76 ENTRYPOINT ModeSpecOpt polyominoes_opts =
77 {sizeof opts / sizeof opts[0], opts,
78  sizeof vars / sizeof vars[0], vars, desc};
79
80 #ifdef USE_MODULES
81 ModStruct   polyominoes_description = {
82   "polyominoes", "init_polyominoes", "draw_polyominoes", "release_polyominoes",
83   "refresh_polyominoes", "init_polyominoes", (char *) NULL, &polyominoes_opts,
84   6000, 1, 8192, 1, 64, 1.0, "",
85   "Shows attempts to place polyominoes into a rectangle", 0, NULL
86 };
87
88 #endif
89
90 /* Each polyomino is described by several quantities:
91    len:             the number of squares in the polyomino;
92    point:           the list of points;
93    tranform_len:    the number of items in transform_list;
94    transform_list:  a list of transformations that need to be done in order
95                     to get all rotations and reflections (see the function
96                     transform below);
97    max_white:       the maximum number of white squares covered if polyomino
98                     is placed on a chess board;
99    color:           it's display color;
100    attached:        whether it is currently attached to the rectangle;
101    attach_point:    point on rectangle where attached;
102    point_no:        the number of the point where it is attached;
103    transform_index: which element of transform_list is currently being used.
104 */
105
106 typedef struct {int x,y;} point_type;
107
108 typedef struct {int len; point_type *point;
109                 int transform_len, transform_list[8], max_white;
110                 unsigned long color;
111                 int attached;
112                 point_type attach_point;
113                 int point_no, transform_index;} polyomino_type;
114
115
116 typedef struct _polyominoesstruct{
117   int wait;
118
119   int width, height;
120   unsigned border_color;
121   int mono;
122
123   polyomino_type *polyomino;
124   int nr_polyominoes;
125   Bool identical, use3D;
126   int *attach_list;
127   int nr_attached;
128
129 /* The array that tells where the polyominoes are attached. */
130   int *array, *changed_array;
131
132 /* These specify the dimensions of how things appear on the screen. */
133   int box, x_margin, y_margin;
134
135 /* These booleans decide in which way to try to attach the polyominoes. */
136   int left_right, top_bottom;
137
138 /* Bitmaps for display purposes. */
139   int use_bitmaps;
140   XImage *bitmaps[256];
141
142 /* Structures used for display purposes if there is not enough memory
143    to allocate bitmaps (or if the screen is small). */
144   XSegment *lines;
145   XRectangle *rectangles;
146
147 /* A procedure that may be used to see if certain configurations
148    are permissible. */
149   int (*check_ok)(struct _polyominoesstruct *sp);
150
151 /* Tells program that solutions are invariant under 180 degree
152    rotation. */
153   int rot180;
154
155 /* This is a variable used in the case that all the polyominoes are identical
156    that will further prune the search tree.  Essentially it will be
157    int reason_to_not_attach[nr_polynominoes][nr_polynominoes];
158    Let me first explain the effect it is trying to overcome.  Often
159    in the search process, the computer will first try to fit shapes into
160    a region (call it A), and then into another region (call it B) that is
161    essentially disjoint from A.  But it may be that it just is not possible
162    to fit shapes into region B.  So it fits something into A, and then
163    tries to fit something into B.  Failing it fits something else into A,
164    and then tried again to fit something into B.  Thus the program is trying
165    again and again to fit something into B, when it should have figured out
166    the first time that it was impossible.
167
168    To overcome this, everytime we try to attach a piece, we collect the reasons
169    why it cannot be attached (a boolean for each piece that got in the way).
170    If we see that a piece cannot be attached, we detach the other pieces until
171    we have detached at least one piece for which the boolean reason_to_not_attach
172    is set.
173 */
174   int *reason_to_not_attach;
175
176   int counter;
177
178 #ifdef STANDALONE
179   eraser_state *eraser;
180 #endif
181 } polyominoesstruct;
182
183 #define ARRAY(x,y)         (sp->array[(x)*sp->height+(y)])
184 #define CHANGED_ARRAY(x,y) (sp->changed_array[(x)*sp->height+(y)])
185 #define ARRAY_P(p)         (sp->array[(p).x*sp->height+(p).y])
186 #define CHANGED_ARRAY_P(p) (sp->changed_array[(p).x*sp->height+(p).y])
187 #define ARR(x,y) (((x)<0||(x)>=sp->width||(y)<0||(y)>=sp->height)?-2:ARRAY(x,y))
188
189 #define REASON_TO_NOT_ATTACH(x,y) (sp->reason_to_not_attach[(x)*sp->nr_polyominoes+(y)])
190
191 #define ROUND8(n) ((((n)+7)/8)*8)
192
193 /* Defines to index the bitmaps.  A set bit indicates that an edge or
194    corner is required. */
195 #define LEFT (1<<0)
196 #define RIGHT (1<<1)
197 #define UP (1<<2)
198 #define DOWN (1<<3)
199 #define LEFT_UP (1<<4)
200 #define LEFT_DOWN (1<<5)
201 #define RIGHT_UP (1<<6)
202 #define RIGHT_DOWN (1<<7)
203 #define IS_LEFT(n) ((n) & LEFT)
204 #define IS_RIGHT(n) ((n) & RIGHT)
205 #define IS_UP(n) ((n) & UP)
206 #define IS_DOWN(n) ((n) & DOWN)
207 #define IS_LEFT_UP(n) ((n) & LEFT_UP)
208 #define IS_LEFT_DOWN(n) ((n) & LEFT_DOWN)
209 #define IS_RIGHT_UP(n) ((n) & RIGHT_UP)
210 #define IS_RIGHT_DOWN(n) ((n) & RIGHT_DOWN)
211
212 /* Defines to access the bitmaps. */
213 #define BITNO(x,y) ((x)+(y)*ROUND8(sp->box))
214 #define SETBIT(n,x,y) {data[BITNO(x,y)/8] |= 1<<(BITNO(x,y)%8);}
215 #define RESBIT(n,x,y) {data[BITNO(x,y)/8] &= ~(1<<(BITNO(x,y)%8));}
216 #define TWOTHIRDSBIT(n,x,y) {if ((x+y-1)%3) SETBIT(n,x,y) else RESBIT(n,x,y)}
217 #define HALFBIT(n,x,y) {if ((x-y)%2) SETBIT(n,x,y) else RESBIT(n,x,y)}
218 #define THIRDBIT(n,x,y) {if (!((x-y-1)%3)) SETBIT(n,x,y) else RESBIT(n,x,y)}
219 #define THREEQUARTERSBIT(n,x,y) \
220   {if ((y%2)||((x+2+y/2+1)%2)) SETBIT(n,x,y) else RESBIT(n,x,y)}
221 #define NOTHALFBIT(n,x,y) {if ((x-y)%2) RESBIT(n,x,y) else SETBIT(n,x,y)}
222
223 /* Parameters for bitmaps. */
224 #define G ((sp->box/45)+1)         /* 1/2 of gap between polyominoes. */
225 #define T ((sp->box<=12)?1:(G*2))  /* Thickness of walls of polyominoes. */
226 #define R ((sp->box<=12)?1:(G*6))  /* Amount of rounding. */
227 #define RT ((sp->box<=12)?1:(G*3)) /* Thickness of wall of rounded parts. 
228                                       Here 3 is an approximation to 2 sqrt(2). */
229 #define RR 0   /* Roof ridge thickness */
230
231 #if 0
232 /* A list of those bitmaps we need to create to display any pentomino. */
233 /* (not used right now because it does not seem to work for hexonimoes.) */
234
235 static int bitmaps_needed[] =
236 {
237  LEFT_UP|LEFT_DOWN|RIGHT_UP|RIGHT_DOWN,
238
239  LEFT|RIGHT_UP|RIGHT_DOWN,
240  RIGHT|LEFT_UP|LEFT_DOWN,
241  UP|LEFT_DOWN|RIGHT_DOWN,
242  DOWN|LEFT_UP|RIGHT_UP,
243  LEFT|RIGHT_UP,
244  RIGHT|LEFT_UP,
245  UP|LEFT_DOWN,
246  DOWN|LEFT_UP,
247  LEFT|RIGHT_DOWN,
248  RIGHT|LEFT_DOWN,
249  UP|RIGHT_DOWN,
250  DOWN|RIGHT_UP,
251
252 /* These needed for hexonimoes*/
253  LEFT,
254  RIGHT,
255  UP,
256  DOWN,
257  LEFT_DOWN|RIGHT_UP|RIGHT_DOWN,
258  LEFT_UP|RIGHT_UP|RIGHT_DOWN,
259  LEFT_UP|LEFT_DOWN|RIGHT_DOWN,
260  LEFT_UP|LEFT_DOWN|RIGHT_UP,
261
262  LEFT|UP|RIGHT_DOWN,
263  LEFT|DOWN|RIGHT_UP,
264  RIGHT|UP|LEFT_DOWN,
265  RIGHT|DOWN|LEFT_UP,
266  LEFT|UP,
267  LEFT|DOWN,
268  RIGHT|UP,
269  RIGHT|DOWN,
270
271  LEFT|RIGHT,
272  UP|DOWN,
273
274  RIGHT|UP|DOWN,
275  LEFT|UP|DOWN,
276  LEFT|RIGHT|DOWN,
277  LEFT|RIGHT|UP,
278
279  -1
280 };
281
282 static int bitmap_needed(int n)
283 {
284   int i;
285
286   for (i=0;bitmaps_needed[i]!=-1;i++)
287     if (n == bitmaps_needed[i])
288       return 1;
289   return 0;
290 }
291
292 #endif
293
294 /* Some debugging routines.
295
296 static void print_board(polyominoesstruct *sp)
297 {
298   int x,y;
299   for (y=0;y<sp->height;y++) {
300     for (x=0;x<sp->width;x++)
301       if (ARRAY(x,y) == -1)
302         fprintf(stderr," ");
303       else
304         fprintf(stderr,"%c",'a'+ARRAY(x,y));
305     fprintf(stderr,"\n");
306   }
307   fprintf(stderr,"\n");
308 }
309
310 static void print_points(point_type *point, int len)
311 {
312   int i;
313
314   for (i=0;i<len;i++)
315     fprintf(stderr,"(%d %d) ",point[i].x,point[i].y);
316 }
317
318 static void print_polyomino(polyomino_type poly)
319 {
320   int i;
321
322   print_points(poly.point,poly.len);
323   fprintf(stderr,"\n");
324   for (i=0;i<poly.transform_len;i++)
325     fprintf(stderr,"%d ",poly.transform_list[i]);
326   fprintf(stderr,"\n");
327 }
328 */
329
330 static polyominoesstruct *polyominoeses = (polyominoesstruct *) NULL;
331
332 static
333 void random_permutation(int n, int a[])
334 {
335   int i,j,k,r;
336
337   for (i=0;i<n;i++) a[i] = -1;
338   for (i=0;i<n;i++) {
339     r=NRAND(n-i);
340     k=0;
341     while(a[k]!=-1) k++;
342     for (j=0;j<r;j++) {
343       k++;
344       while(a[k]!=-1) k++;
345     }
346     a[k]=i;
347   }
348 }
349
350
351 /************************************************************
352 These are the routines for manipulating the polyominoes and
353 attaching and detaching them from the rectangle.
354 ************************************************************/
355
356 static void transform(point_type in, point_type offset, int transform_no, 
357                       point_type attach_point, point_type *out) {
358   switch (transform_no) {
359     case 0: out->x=in.x-offset.x+attach_point.x;
360             out->y=in.y-offset.y+attach_point.y;
361             break;
362     case 1: out->x=-(in.y-offset.y)+attach_point.x;
363             out->y=in.x-offset.x+attach_point.y;
364             break;
365     case 2: out->x=-(in.x-offset.x)+attach_point.x;
366             out->y=-(in.y-offset.y)+attach_point.y;
367             break;
368     case 3: out->x=in.y-offset.y+attach_point.x;
369             out->y=-(in.x-offset.x)+attach_point.y;
370             break;
371     case 4: out->x=-(in.x-offset.x)+attach_point.x;
372             out->y=in.y-offset.y+attach_point.y;
373             break;
374     case 5: out->x=in.y-offset.y+attach_point.x;
375             out->y=in.x-offset.x+attach_point.y;
376             break;
377     case 6: out->x=in.x-offset.x+attach_point.x;
378             out->y=-(in.y-offset.y)+attach_point.y;
379             break;
380     case 7: out->x=-(in.y-offset.y)+attach_point.x;
381             out->y=-(in.x-offset.x)+attach_point.y;
382             break;
383   }
384 }
385
386 static int first_poly_no(polyominoesstruct *sp)
387 {
388   int poly_no;
389
390   poly_no = 0;
391   while(poly_no<sp->nr_polyominoes && sp->polyomino[poly_no].attached)
392     poly_no++;
393   return poly_no;
394 }
395
396 static void next_poly_no(polyominoesstruct *sp, int *poly_no)
397 {
398
399   if (sp->identical) {
400     *poly_no = sp->nr_polyominoes;
401   } else {
402     do {
403       (*poly_no)++;
404     } while (*poly_no<sp->nr_polyominoes && sp->polyomino[*poly_no].attached);
405   }
406 }
407
408 /* check_all_regions_multiple_of looks for connected regions of 
409    blank spaces, and returns 0 if it finds a connected region containing
410    a number of blanks that is not a multiple of n.
411 */
412
413 static void count_adjacent_blanks(polyominoesstruct *sp, int *count, int x, int y, int blank_mark)
414 {
415
416   if (ARRAY(x,y) == -1) {
417     (*count)++;
418     ARRAY(x,y) = blank_mark;
419     if (x>=1) count_adjacent_blanks(sp, count,x-1,y,blank_mark);
420     if (x<sp->width-1) count_adjacent_blanks(sp, count,x+1,y,blank_mark);
421     if (y>=1) count_adjacent_blanks(sp, count,x,y-1,blank_mark);
422     if (y<sp->height-1) count_adjacent_blanks(sp, count,x,y+1,blank_mark);
423   }
424 }
425
426 static int check_all_regions_multiple_of(polyominoesstruct *sp, int n)
427 {
428   int x,y,count,good = 1;
429
430   for (x=0;x<sp->width && good;x++) for (y=0;y<sp->height && good;y++) {
431     count = 0;
432     count_adjacent_blanks(sp, &count,x,y,-2);
433     good = count%n == 0;
434   }
435
436   for (x=0;x<sp->width;x++) for (y=0;y<sp->height;y++)
437     if (ARRAY(x,y) == -2)
438       ARRAY(x,y) = -1;
439
440   return good;
441 }
442
443 static int check_all_regions_positive_combination_of(polyominoesstruct *sp, int m, int n)
444 {
445   int x,y,count,good = 1;
446
447   for (x=0;x<sp->width && good;x++) for (y=0;y<sp->height && good;y++) {
448     count = 0;
449     count_adjacent_blanks(sp, &count,x,y,-2);
450     good = 0;
451     for (;count>=0 && !good;count-=m)
452       good = count%n == 0;
453   }
454
455   for (x=0;x<sp->width;x++) for (y=0;y<sp->height;y++)
456     if (ARRAY(x,y) == -2)
457       ARRAY(x,y) = -1;
458
459   return good;
460 }
461
462 static int find_smallest_blank_component(polyominoesstruct *sp)
463 {
464   int x,y,size,smallest_size,blank_mark,smallest_mark;
465
466   smallest_mark = blank_mark = -10;
467   smallest_size = 1000000000;
468   for (x=0;x<sp->width;x++) for (y=0;y<sp->height;y++) if (ARRAY(x,y) == -1) {
469     size = 0;
470     count_adjacent_blanks(sp, &size,x,y,blank_mark);
471     if (size<smallest_size) {
472       smallest_mark = blank_mark;
473       smallest_size = size;
474     }
475     blank_mark--;
476   }
477
478   return smallest_mark;
479 }
480
481 /* "Chess board" check - see init_max_whites_list above for more details.
482 */
483 /* If the rectangle is alternatively covered by white and black
484    squares (chess board style), then this gives the list of
485    the maximal possible whites covered by each polyomino.  It
486    is used by the function whites_ok which makes sure that the
487    array has a valid number of white or black remaining blanks left.
488 */
489
490 static int whites_ok(polyominoesstruct *sp)
491 {
492   int x,y,poly_no,whites=0,blacks=0,max_white=0,min_white=0;
493
494   for (x=0;x<sp->width;x++) for (y=0;y<sp->height;y++) {
495     if (ARRAY(x,y) == -1 && (x+y)%2) whites++;
496     if (ARRAY(x,y) == -1 && (x+y+1)%2) blacks++;
497   }
498   for (poly_no=0;poly_no<sp->nr_polyominoes;poly_no++) if (!sp->polyomino[poly_no].attached) {
499     max_white += sp->polyomino[poly_no].max_white;
500     min_white += sp->polyomino[poly_no].len - sp->polyomino[poly_no].max_white;
501   }
502   return (min_white <= blacks && min_white <= whites
503           && blacks <= max_white && whites <= max_white);
504 }
505
506 /* This routine looks at the point (x,y) and sees how many polyominoes
507    and all their various transforms may be attached there.
508 */
509
510 static int
511 score_point(polyominoesstruct *sp, int x, int y, int min_score_so_far)
512 {
513   int poly_no, point_no, transform_index, i, attachable;
514   point_type attach_point, target_point;
515   int score = 0;
516
517   if (x>=1 && x<sp->width-1 && y>=1 && y<sp->height-1 &&
518       ARRAY(x-1,y-1)<0 && ARRAY(x-1,y)<0 && ARRAY(x-1,y+1)<0 && 
519       ARRAY(x+1,y-1)<0 && ARRAY(x+1,y)<0 && ARRAY(x+1,y+1)<0 && 
520       ARRAY(x,y-1)<0 && ARRAY(x,y+1)<0)
521     return 10000;
522
523   attach_point.x = x;
524   attach_point.y = y;
525   for (poly_no=first_poly_no(sp);poly_no<sp->nr_polyominoes;next_poly_no(sp,&poly_no))
526   if (!sp->polyomino[poly_no].attached) {
527     for (point_no=0;point_no<sp->polyomino[poly_no].len;point_no++)
528     for (transform_index=0;transform_index<sp->polyomino[poly_no].transform_len;transform_index++) {
529       attachable = 1;
530       for (i=0;i<sp->polyomino[poly_no].len;i++) {
531         transform(sp->polyomino[poly_no].point[i],
532                   sp->polyomino[poly_no].point[point_no],
533                   sp->polyomino[poly_no].transform_list[transform_index], 
534                   attach_point, &target_point);
535         if ( ! ((target_point.x>=0) && (target_point.x<sp->width) 
536                   && (target_point.y>=0) && (target_point.y<sp->height)
537                   && (ARRAY_P(target_point)<0))) {
538           attachable = 0;
539           break;
540         }
541       }
542       if (attachable) {
543         score++;
544         if (score>=min_score_so_far)
545           return score;
546       }
547     }
548   }
549
550   return score;
551 }
552
553 static void find_blank(polyominoesstruct *sp, point_type *point)
554 {
555   int score, worst_score;
556   int x, y;
557   int blank_mark;
558
559   blank_mark = find_smallest_blank_component(sp);
560
561   worst_score = 1000000;
562   for (x=0;x<sp->width;x++) for (y=0;y<sp->height;y++) if (ARRAY(x,y)==blank_mark) {
563     score = 100*score_point(sp,x,y,worst_score);
564     if (score>0) {
565       if (sp->left_right) score += 10*x;
566       else                score += 10*(sp->width-1-x);
567       if (sp->top_bottom) score += y;
568       else                score += (sp->height-1-y);
569     }
570     if (score<worst_score) {
571       point->x = x;
572       point->y = y;
573       worst_score = score;
574     }
575   }
576
577   for (x=0;x<sp->width;x++) for (y=0;y<sp->height;y++) 
578     if (ARRAY(x,y)<0) ARRAY(x,y) = -1;
579 }
580
581 /* Detaches the most recently attached polyomino. */
582
583 static
584 void detach(polyominoesstruct *sp, int *poly_no, int *point_no, int *transform_index, point_type *attach_point, int rot180)
585 {
586   int i;
587   point_type target_point;
588
589   if (sp->nr_attached == 0) return;
590   sp->nr_attached--;
591   *poly_no = sp->attach_list[sp->nr_attached];
592   *point_no = sp->polyomino[*poly_no].point_no;
593   *transform_index = sp->polyomino[*poly_no].transform_index;
594   *attach_point = sp->polyomino[*poly_no].attach_point;
595   for (i=0;i<sp->polyomino[*poly_no].len;i++) {
596     transform(sp->polyomino[*poly_no].point[i],
597               sp->polyomino[*poly_no].point[*point_no],
598               sp->polyomino[*poly_no].transform_list[*transform_index]^(rot180<<1), 
599               *attach_point, &target_point);
600     ARRAY_P(target_point) = -1;
601     CHANGED_ARRAY_P(target_point) = 1;
602   }
603
604   sp->polyomino[*poly_no].attached = 0;
605 }
606
607 /* Attempts to attach a polyomino at point (x,y) at the 
608    point_no-th point of that polyomino, using the transform
609    transform_no.  Returns 1 if successful.
610 */
611
612 static
613 int attach(polyominoesstruct *sp, int poly_no, int point_no, int transform_index, point_type attach_point, int rot180,
614            int *reason_to_not_attach) {
615   point_type target_point;
616   int i;
617   int attachable = 1, worst_reason_not_to_attach = 1000000000;
618
619   if (rot180) {
620     attach_point.x = sp->width-1-attach_point.x;
621     attach_point.y = sp->height-1-attach_point.y;
622   }
623
624   if (sp->polyomino[poly_no].attached)
625     return 0;
626
627   for (i=0;i<sp->polyomino[poly_no].len;i++) {
628     transform(sp->polyomino[poly_no].point[i],
629               sp->polyomino[poly_no].point[point_no],
630               sp->polyomino[poly_no].transform_list[transform_index]^(rot180<<1), 
631               attach_point, &target_point);
632     if ( ! ((target_point.x>=0) && (target_point.x<sp->width) 
633               && (target_point.y>=0) && (target_point.y<sp->height)
634               && (ARRAY_P(target_point) == -1))) {
635       if (sp->identical) {
636         attachable = 0;
637         if ((target_point.x>=0) && (target_point.x<sp->width) 
638            && (target_point.y>=0) && (target_point.y<sp->height) 
639            && (ARRAY_P(target_point) >= 0)
640            && (ARRAY_P(target_point)<worst_reason_not_to_attach))
641           worst_reason_not_to_attach = ARRAY_P(target_point);
642       }
643       else
644         return 0;
645     }
646   }
647
648   if (sp->identical && !attachable) {
649     if (worst_reason_not_to_attach < 1000000000)
650       reason_to_not_attach[worst_reason_not_to_attach] = 1;
651     return 0;
652   }
653
654   for (i=0;i<sp->polyomino[poly_no].len;i++) {
655     transform(sp->polyomino[poly_no].point[i],
656               sp->polyomino[poly_no].point[point_no],
657               sp->polyomino[poly_no].transform_list[transform_index]^(rot180<<1),
658               attach_point, &target_point);
659     ARRAY_P(target_point) = poly_no;
660     CHANGED_ARRAY_P(target_point) = 1;
661   }
662
663   sp->attach_list[sp->nr_attached] = poly_no;
664   sp->nr_attached++;
665
666   sp->polyomino[poly_no].attached = 1;
667   sp->polyomino[poly_no].point_no = point_no;
668   sp->polyomino[poly_no].attach_point = attach_point;
669   sp->polyomino[poly_no].transform_index = transform_index;
670
671   if (!sp->check_ok(sp)) {
672     detach(sp,&poly_no,&point_no,&transform_index,&attach_point,rot180);
673     return 0;
674   }
675
676   return 1;
677 }
678
679 static
680 int next_attach_try(polyominoesstruct *sp, int *poly_no, int *point_no, int *transform_index)
681 {
682
683   (*transform_index)++;
684   if (*transform_index>=sp->polyomino[*poly_no].transform_len) {
685     *transform_index = 0;
686     (*point_no)++;
687     if (*point_no>=sp->polyomino[*poly_no].len) {
688       *point_no = 0;
689       next_poly_no(sp,poly_no);
690       if (*poly_no>=sp->nr_polyominoes) {
691         *poly_no = first_poly_no(sp);
692         return 0;
693       }
694     }
695   }
696   return 1;
697 }
698
699
700 /*******************************************************
701 Display routines.
702 *******************************************************/
703
704 static void
705 draw_without_bitmaps(ModeInfo * mi, polyominoesstruct *sp)
706 {
707   Display *display = MI_DISPLAY(mi);
708   Window  window = MI_WINDOW(mi);
709   GC gc = MI_GC(mi);
710   int x,y,poly_no,nr_lines,nr_rectangles;
711
712   XSetLineAttributes(display,gc,sp->box/10+1,LineSolid,CapRound,JoinRound);
713
714   for (poly_no=-1;poly_no<sp->nr_polyominoes;poly_no++) {
715     nr_rectangles = 0;
716     for (x=0;x<sp->width;x++) for (y=0;y<sp->height;y++)
717     if (CHANGED_ARRAY(x,y) && ARRAY(x,y) == poly_no) {
718       sp->rectangles[nr_rectangles].x = sp->x_margin + sp->box*x;
719       sp->rectangles[nr_rectangles].y = sp->y_margin + sp->box*y;
720       sp->rectangles[nr_rectangles].width = sp->box;
721       sp->rectangles[nr_rectangles].height = sp->box;
722       nr_rectangles++;
723     }
724     if (poly_no == -1)
725       XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
726     else
727       XSetForeground(display, gc, sp->polyomino[poly_no].color);
728     XFillRectangles(display, window, gc, sp->rectangles, nr_rectangles);
729   }
730
731   XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
732
733   nr_lines = 0;
734   for (x=0;x<sp->width-1;x++) for (y=0;y<sp->height;y++) {
735     if (ARRAY(x,y) == -1 && ARRAY(x+1,y) == -1
736         && (CHANGED_ARRAY(x,y) || CHANGED_ARRAY(x+1,y))) {
737       sp->lines[nr_lines].x1 = sp->x_margin + sp->box*(x+1);
738       sp->lines[nr_lines].y1 = sp->y_margin + sp->box*y;
739       sp->lines[nr_lines].x2 = sp->x_margin + sp->box*(x+1);
740       sp->lines[nr_lines].y2 = sp->y_margin + sp->box*(y+1);
741       nr_lines++;
742     }
743   }
744   XDrawSegments(display, window, gc, sp->lines, nr_lines);
745
746   nr_lines = 0;
747   for (x=0;x<sp->width;x++) for (y=0;y<sp->height-1;y++) {
748     if (ARRAY(x,y) == -1 && ARRAY(x,y+1) == -1
749         && (CHANGED_ARRAY(x,y) || CHANGED_ARRAY(x,y+1))) {
750       sp->lines[nr_lines].x1 = sp->x_margin + sp->box*x;
751       sp->lines[nr_lines].y1 = sp->y_margin + sp->box*(y+1);
752       sp->lines[nr_lines].x2 = sp->x_margin + sp->box*(x+1);
753       sp->lines[nr_lines].y2 = sp->y_margin + sp->box*(y+1);
754       nr_lines++;
755     }
756   }
757   XDrawSegments(display, window, gc, sp->lines, nr_lines);
758
759   XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
760   XDrawRectangle(display, window, gc, sp->x_margin, sp->y_margin, sp->box*sp->width, sp->box*sp->height);
761
762   XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
763
764   nr_lines = 0;
765   for (x=0;x<sp->width-1;x++) for (y=0;y<sp->height;y++) {
766     if (ARRAY(x+1,y) != ARRAY(x,y)) {
767       sp->lines[nr_lines].x1 = sp->x_margin + sp->box*(x+1);
768       sp->lines[nr_lines].y1 = sp->y_margin + sp->box*y;
769       sp->lines[nr_lines].x2 = sp->x_margin + sp->box*(x+1);
770       sp->lines[nr_lines].y2 = sp->y_margin + sp->box*(y+1);
771       nr_lines++;
772     }
773   }
774   XDrawSegments(display, window, gc, sp->lines, nr_lines);
775
776   nr_lines = 0;
777   for (x=0;x<sp->width;x++) for (y=0;y<sp->height-1;y++) {
778     if (ARRAY(x,y+1) != ARRAY(x,y)) {
779       sp->lines[nr_lines].x1 = sp->x_margin + sp->box*x;
780       sp->lines[nr_lines].y1 = sp->y_margin + sp->box*(y+1);
781       sp->lines[nr_lines].x2 = sp->x_margin + sp->box*(x+1);
782       sp->lines[nr_lines].y2 = sp->y_margin + sp->box*(y+1);
783       nr_lines++;
784     }
785   }
786   XDrawSegments(display, window, gc, sp->lines, nr_lines);
787   XSetLineAttributes(display,gc,1,LineSolid,CapRound,JoinRound);
788 }
789
790 static void create_bitmaps(ModeInfo * mi, polyominoesstruct *sp)
791 {
792   int x,y,n;
793   char *data;
794
795   for (n=0;n<256;n++) {
796
797 /* Avoid duplication of identical bitmaps. */
798     if (IS_LEFT_UP(n) && (IS_LEFT(n) || IS_UP(n)))
799       sp->bitmaps[n] = sp->bitmaps[n & ~LEFT_UP];
800     else if (IS_LEFT_DOWN(n) && (IS_LEFT(n) || IS_DOWN(n)))
801       sp->bitmaps[n] = sp->bitmaps[n & ~LEFT_DOWN];
802     else if (IS_RIGHT_UP(n) && (IS_RIGHT(n) || IS_UP(n)))
803       sp->bitmaps[n] = sp->bitmaps[n & ~RIGHT_UP];
804     else if (IS_RIGHT_DOWN(n) && (IS_RIGHT(n) || IS_DOWN(n)))
805       sp->bitmaps[n] = sp->bitmaps[n & ~RIGHT_DOWN];
806
807     else /* if (bitmap_needed(n)) */ {
808       data = (char *) malloc(sizeof(char)*(sp->box*ROUND8(sp->box)/8));
809       if (data == NULL) {
810         sp->use_bitmaps = 0;
811         return;
812       }
813
814       for (y=0;y<sp->box;y++) for (x=0;x<sp->box;x++) {
815         if (!sp->use3D) {
816 #ifdef SMALL_BELLYBUTTON
817           if (x >= sp->box / 2 && x <= sp->box / 2 + 1 &&
818               y >= sp->box / 2 && y <= sp->box / 2 + 1)
819             NOTHALFBIT(n,x,y)
820           else
821 #endif
822             HALFBIT(n,x,y)
823         } else if ((x>=y && x<=sp->box-y-1 && IS_UP(n))
824             || (x<=y && x<=sp->box-y-1 && y<sp->box/2 && !IS_LEFT(n))
825             || (x>=y && x>=sp->box-y-1 && y<sp->box/2 && !IS_RIGHT(n)))
826           SETBIT(n,x,y)
827         else if ((x<=y && x<=sp->box-y-1 && IS_LEFT(n))
828             || (x>=y && x<=sp->box-y-1 && x<sp->box/2 && !IS_UP(n))
829             || (x<=y && x>=sp->box-y-1 && x<sp->box/2 && !IS_DOWN(n)))
830           TWOTHIRDSBIT(n,x,y)
831         else if ((x>=y && x>=sp->box-y-1 && IS_RIGHT(n))
832             || (x>=y && x<=sp->box-y-1 && x>=sp->box/2 && !IS_UP(n))
833             || (x<=y && x>=sp->box-y-1 && x>=sp->box/2 && !IS_DOWN(n)))
834           HALFBIT(n,x,y)
835         else if ((x<=y && x>=sp->box-y-1 && IS_DOWN(n))
836             || (x<=y && x<=sp->box-y-1 && y>=sp->box/2 && !IS_LEFT(n))
837             || (x>=y && x>=sp->box-y-1 && y>=sp->box/2 && !IS_RIGHT(n)))
838           THIRDBIT(n,x,y)
839       }
840
841       if (IS_LEFT(n)) 
842         for (y=0;y<sp->box;y++) for (x=G;x<G+T;x++)
843           SETBIT(n,x,y)
844       if (IS_RIGHT(n)) 
845         for (y=0;y<sp->box;y++) for (x=G;x<G+T;x++)
846           SETBIT(n,sp->box-1-x,y)
847       if (IS_UP(n))
848         for (x=0;x<sp->box;x++) for (y=G;y<G+T;y++)
849           SETBIT(n,x,y)
850       if (IS_DOWN(n))
851         for (x=0;x<sp->box;x++) for (y=G;y<G+T;y++)
852           SETBIT(n,x,sp->box-1-y)
853       if (IS_LEFT(n)) 
854         for (y=0;y<sp->box;y++) for (x=0;x<G;x++)
855           RESBIT(n,x,y)
856       if (IS_RIGHT(n)) 
857         for (y=0;y<sp->box;y++) for (x=0;x<G;x++)
858           RESBIT(n,sp->box-1-x,y)
859       if (IS_UP(n))
860         for (x=0;x<sp->box;x++) for (y=0;y<G;y++)
861           RESBIT(n,x,y)
862       if (IS_DOWN(n))
863         for (x=0;x<sp->box;x++) for (y=0;y<G;y++)
864           RESBIT(n,x,sp->box-1-y)
865
866       if (IS_LEFT(n) && IS_UP(n))
867         for (x=G;x<=G+R;x++)
868           for (y=G;y<=R+2*G-x;y++) {
869             if (x+y>R+2*G-RT)
870               SETBIT(n,x,y)
871             else
872               RESBIT(n,x,y)
873           }
874       if (IS_LEFT(n) && IS_DOWN(n))
875         for (x=G;x<=G+R;x++)
876           for (y=G;y<=R+2*G-x;y++) {
877             if (x+y>R+2*G-RT)
878               SETBIT(n,x,sp->box-1-y)
879             else
880               RESBIT(n,x,sp->box-1-y)
881           }
882       if (IS_RIGHT(n) && IS_UP(n))
883         for (x=G;x<=G+R;x++)
884           for (y=G;y<=R+2*G-x;y++) {
885             if (x+y>R+2*G-RT)
886               SETBIT(n,sp->box-1-x,y)
887             else
888               RESBIT(n,sp->box-1-x,y)
889           }
890       if (IS_RIGHT(n) && IS_DOWN(n))
891         for (x=G;x<=G+R;x++)
892           for (y=G;y<=R+2*G-x;y++) {
893             if (x+y>R+2*G-RT)
894               SETBIT(n,sp->box-1-x,sp->box-1-y)
895             else
896               RESBIT(n,sp->box-1-x,sp->box-1-y)
897           }
898
899       if (!IS_LEFT(n) && !IS_UP(n) && IS_LEFT_UP(n)) {
900         for (x=0;x<G;x++) for(y=0;y<G;y++)
901           RESBIT(n,x,y)
902         for (x=G;x<G+T;x++) for(y=0;y<G;y++)
903           SETBIT(n,x,y)
904         for (x=0;x<G+T;x++) for(y=G;y<G+T;y++)
905           SETBIT(n,x,y)
906       }
907       if (!IS_LEFT(n) && !IS_DOWN(n) && IS_LEFT_DOWN(n)) {
908         for (x=0;x<G;x++) for(y=0;y<G;y++)
909           RESBIT(n,x,sp->box-1-y)
910         for (x=G;x<G+T;x++) for(y=0;y<G;y++)
911           SETBIT(n,x,sp->box-1-y)
912         for (x=0;x<G+T;x++) for(y=G;y<G+T;y++)
913           SETBIT(n,x,sp->box-1-y)
914       }
915       if (!IS_RIGHT(n) && !IS_UP(n) && IS_RIGHT_UP(n)) {
916         for (x=0;x<G;x++) for(y=0;y<G;y++)
917           RESBIT(n,sp->box-1-x,y)
918         for (x=G;x<G+T;x++) for(y=0;y<G;y++)
919           SETBIT(n,sp->box-1-x,y)
920         for (x=0;x<G+T;x++) for(y=G;y<G+T;y++)
921           SETBIT(n,sp->box-1-x,y)
922       }
923       if (!IS_RIGHT(n) && !IS_DOWN(n) && IS_RIGHT_DOWN(n)) {
924         for (x=0;x<G;x++) for(y=0;y<G;y++)
925           RESBIT(n,sp->box-1-x,sp->box-1-y)
926         for (x=G;x<G+T;x++) for(y=0;y<G;y++)
927           SETBIT(n,sp->box-1-x,sp->box-1-y)
928         for (x=0;x<G+T;x++) for(y=G;y<G+T;y++)
929           SETBIT(n,sp->box-1-x,sp->box-1-y)
930       }
931
932 #ifdef LARGE_BELLYBUTTON
933       if (!sp->use3D) {
934         if (!IS_LEFT(n) && !IS_UP(n) && !IS_LEFT_UP(n))
935           for (x=0;x<G+T;x++) for(y=0;y<G+T;y++)
936             SETBIT(n,x,y)
937         if (!IS_LEFT(n) && !IS_DOWN(n) && !IS_LEFT_DOWN(n))
938           for (x=0;x<G+T;x++) for(y=sp->box-G-T;y<sp->box;y++)
939             SETBIT(n,x,y)
940         if (!IS_RIGHT(n) && !IS_UP(n) && !IS_RIGHT_UP(n))
941           for (x=sp->box-G-T;x<sp->box;x++) for(y=0;y<G+T;y++)
942             SETBIT(n,x,y)
943         if (!IS_RIGHT(n) && !IS_DOWN(n) && !IS_RIGHT_DOWN(n))
944           for (x=sp->box-G-T;x<sp->box;x++) for(y=sp->box-G-T;y<sp->box;y++)
945             SETBIT(n,x,y)
946       } else
947 #else
948       if (sp->use3D)
949 #endif
950       {
951         if (!IS_LEFT(n) && !IS_UP(n) && !IS_LEFT_UP(n))
952           for (x=0;x<sp->box/2-RR;x++) for(y=0;y<sp->box/2-RR;y++)
953             THREEQUARTERSBIT(n,x,y)
954         if (!IS_LEFT(n) && !IS_DOWN(n) && !IS_LEFT_DOWN(n))
955           for (x=0;x<sp->box/2-RR;x++) for(y=sp->box/2+RR;y<sp->box;y++)
956             THREEQUARTERSBIT(n,x,y)
957         if (!IS_RIGHT(n) && !IS_UP(n) && !IS_RIGHT_UP(n))
958           for (x=sp->box/2+RR;x<sp->box;x++) for(y=0;y<sp->box/2-RR;y++)
959             THREEQUARTERSBIT(n,x,y)
960         if (!IS_RIGHT(n) && !IS_DOWN(n) && !IS_RIGHT_DOWN(n))
961           for (x=sp->box/2+RR;x<sp->box;x++) for(y=sp->box/2+RR;y<sp->box;y++)
962             THREEQUARTERSBIT(n,x,y)
963       }
964
965       sp->bitmaps[n] = XCreateImage(MI_DISPLAY(mi), MI_VISUAL(mi), 1, XYBitmap,
966                                     0, data, sp->box, sp->box, 8, 0);
967       if (sp->bitmaps[n] == None) {
968         free(data);
969         sp->use_bitmaps = 0;
970         return;
971       }
972       sp->bitmaps[n]->byte_order = MSBFirst;
973       sp->bitmaps[n]->bitmap_unit = 8;
974       sp->bitmaps[n]->bitmap_bit_order = LSBFirst;
975     }
976   }
977
978   sp->use_bitmaps = 1;
979 }
980
981 static void draw_with_bitmaps(ModeInfo * mi, polyominoesstruct *sp)
982 {
983   Display *display = MI_DISPLAY(mi);
984   Window  window = MI_WINDOW(mi);
985   GC gc = MI_GC(mi);
986   int x,y,t,bitmap_index;
987
988   for (x=0;x<sp->width;x++) for (y=0;y<sp->height;y++) {
989     if (ARRAY(x,y) == -1) {
990       if (CHANGED_ARRAY(x,y)) {
991         XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
992         XFillRectangle(display,window,gc,
993                        sp->x_margin + sp->box*x,
994                        sp->y_margin + sp->box*y,
995                        sp->box,sp->box);
996       }
997     }
998     else {
999       XSetForeground(display, gc, sp->polyomino[ARRAY(x,y)].color);
1000       bitmap_index = 0;
1001       if (ARR(x,y) != ARR(x-1,y))   bitmap_index |= LEFT;
1002       if (ARR(x,y) != ARR(x+1,y))   bitmap_index |= RIGHT;
1003       if (ARR(x,y) != ARR(x,y-1))   bitmap_index |= UP;
1004       if (ARR(x,y) != ARR(x,y+1))   bitmap_index |= DOWN;
1005       if (ARR(x,y) != ARR(x-1,y-1)) bitmap_index |= LEFT_UP;
1006       if (ARR(x,y) != ARR(x-1,y+1)) bitmap_index |= LEFT_DOWN;
1007       if (ARR(x,y) != ARR(x+1,y-1)) bitmap_index |= RIGHT_UP;
1008       if (ARR(x,y) != ARR(x+1,y+1)) bitmap_index |= RIGHT_DOWN;
1009       (void) XPutImage(display,window,gc,
1010                 sp->bitmaps[bitmap_index],
1011                 0,0,
1012                 sp->x_margin + sp->box*x,
1013                 sp->y_margin + sp->box*y,
1014                 sp->box,sp->box);
1015     }
1016   }
1017
1018   XSetForeground(display, gc, sp->border_color);
1019   for (t=G;t<G+T;t++)
1020     XDrawRectangle(display,window,gc,
1021                    sp->x_margin-t-1,sp->y_margin-t-1,
1022                    sp->box*sp->width+1+2*t, sp->box*sp->height+1+2*t);
1023 }
1024
1025
1026 /***************************************************
1027 Routines to initialise and close down polyominoes.
1028 ***************************************************/
1029
1030 static void free_bitmaps(polyominoesstruct *sp)
1031 {
1032   int n;
1033   
1034   for (n=0;n<256;n++)
1035 /* Don't bother to free duplicates */
1036     if (IS_LEFT_UP(n) && (IS_LEFT(n) || IS_UP(n)))
1037       sp->bitmaps[n] = None;
1038     else if (IS_LEFT_DOWN(n) && (IS_LEFT(n) || IS_DOWN(n)))
1039       sp->bitmaps[n] = None;
1040     else if (IS_RIGHT_UP(n) && (IS_RIGHT(n) || IS_UP(n)))
1041       sp->bitmaps[n] = None;
1042     else if (IS_RIGHT_DOWN(n) && (IS_RIGHT(n) || IS_DOWN(n)))
1043       sp->bitmaps[n] = None;
1044
1045     else if (sp->bitmaps[n] != None) {
1046         XDestroyImage(sp->bitmaps[n]);
1047         sp->bitmaps[n] = None;
1048     }
1049 }
1050
1051 #define deallocate(p,t) if ((p)!=NULL) {free(p); p=(t*)NULL;}
1052
1053 static void free_polyominoes(polyominoesstruct *sp)
1054 {
1055   int n;
1056
1057   for (n=0;n<sp->nr_polyominoes;n++) {
1058     deallocate(sp->polyomino[n].point, point_type);
1059   }
1060
1061   deallocate(sp->polyomino, polyomino_type);
1062   deallocate(sp->attach_list, int);
1063   deallocate(sp->rectangles, XRectangle);
1064   deallocate(sp->lines, XSegment);
1065   deallocate(sp->reason_to_not_attach, int);
1066   deallocate(sp->array, int);
1067   deallocate(sp->changed_array, int);
1068
1069   free_bitmaps(sp);
1070 }
1071
1072 #define set_allocate(p,type,size) p = (type *) malloc(size);            \
1073                              if ((p)==NULL) {free_polyominoes(sp);return 0;}
1074
1075 #define copy_polyomino(dst,src,new_rand)                                \
1076   (dst).len=(src).len;                                                  \
1077   (dst).max_white = (src).max_white;                                    \
1078   set_allocate((dst).point,point_type,sizeof(point_type)*(src).len);            \
1079   (dst).len = (src).len;                                                \
1080   if (new_rand)                                                         \
1081     random_permutation((src).len,perm_point);                           \
1082   for (i=0;i<(src).len;i++)                                             \
1083     (dst).point[i] = (src).point[perm_point[i]];                        \
1084   (dst).transform_len = (src).transform_len;                            \
1085   if (new_rand)                                                         \
1086     random_permutation((src).transform_len,perm_transform);             \
1087   for (i=0;i<(src).transform_len;i++)                                   \
1088     (dst).transform_list[i] = (src).transform_list[perm_transform[i]];  \
1089   (dst).attached = 0
1090
1091
1092 /***************************************************
1093 Puzzle specific initialization routines.
1094 ***************************************************/
1095
1096 static
1097 int check_pentomino_puzzle(polyominoesstruct *sp)
1098 {
1099   return check_all_regions_multiple_of(sp, 5) && whites_ok(sp);
1100 }
1101
1102 static
1103 int check_hexomino_puzzle(polyominoesstruct *sp)
1104 {
1105   return check_all_regions_multiple_of(sp, 6) && whites_ok(sp);
1106 }
1107
1108 static
1109 int check_tetr_pentomino_puzzle(polyominoesstruct *sp)
1110 {
1111   return check_all_regions_positive_combination_of(sp, 5, 4) && whites_ok(sp);
1112 }
1113
1114 static
1115 int check_pent_hexomino_puzzle(polyominoesstruct *sp)
1116 {
1117   return check_all_regions_positive_combination_of(sp, 6, 5) && whites_ok(sp);
1118 }
1119
1120 static
1121 int check_heptomino_puzzle(polyominoesstruct *sp)
1122 {
1123   return check_all_regions_multiple_of(sp, 7) && whites_ok(sp);
1124 }
1125
1126 static
1127 int check_octomino_puzzle(polyominoesstruct *sp)
1128 {
1129   return check_all_regions_multiple_of(sp, 8) && whites_ok(sp);
1130 }
1131
1132 static
1133 int check_dekomino_puzzle(polyominoesstruct *sp)
1134 {
1135   return check_all_regions_multiple_of(sp, 10) && whites_ok(sp);
1136 }
1137
1138 static
1139 int check_elevenomino_puzzle(polyominoesstruct *sp)
1140 {
1141   return check_all_regions_multiple_of(sp, 11) && whites_ok(sp);
1142 }
1143
1144 static struct {int len; point_type point[4];
1145                int transform_len, transform_list[8], max_white;} tetromino[5] =
1146 {
1147 /*
1148 xxxx 
1149 */
1150   {4, {{0,0}, {1,0}, {2,0}, {3,0}},
1151    2, {0, 1, -1, -1, -1, -1, -1, -1}, 2},
1152 /*
1153 xxx  
1154   x  
1155 */
1156   {4, {{0,0}, {1,0}, {2,0}, {2,1}},
1157    8, {0, 1, 2, 3, 4, 5, 6, 7}, 2},
1158 /*
1159 xxx  
1160  x   
1161 */
1162   {4, {{0,0}, {1,0}, {1,1}, {2,0}},
1163    4, {0, 1, 2, 3, -1, -1, -1, -1}, 3},
1164 /*
1165 xx   
1166  xx  
1167 */
1168   {4, {{0,0}, {1,0}, {1,1}, {2,1}},
1169    4, {0, 1, 4, 5, -1, -1, -1, -1}, 2},
1170 /*
1171 xx   
1172 xx   
1173 */
1174   {4, {{0,0}, {0,1}, {1,0}, {1,1}},
1175    1, {0, -1, -1, -1, -1, -1, -1, -1}, 2}};
1176
1177
1178 static struct pentomino_struct {int len; point_type point[5];
1179                                 int transform_len, transform_list[8], max_white;}
1180   pentomino[12] =
1181 {
1182 /*
1183 xxxxx 
1184 */
1185   {5, {{0,0}, {1,0}, {2,0}, {3,0}, {4,0}},
1186    2, {0, 1, -1, -1, -1, -1, -1, -1}, 3},
1187 /*
1188 xxxx  
1189    x  
1190 */
1191   {5, {{0,0}, {1,0}, {2,0}, {3,0}, {3,1}},
1192    8, {0, 1, 2, 3, 4, 5, 6, 7}, 3},
1193 /*
1194 xxxx  
1195   x   
1196 */
1197   {5, {{0,0}, {1,0}, {2,0}, {2,1}, {3,0}},
1198    8, {0, 1, 2, 3, 4, 5, 6, 7}, 3},
1199 /*
1200   x   
1201 xxx   
1202   x   
1203 */
1204   {5, {{0,0}, {1,0}, {2,-1}, {2,0}, {2,1}},
1205    4, {0, 1, 2, 3, -1, -1, -1, -1}, 3},
1206 /*
1207 xxx   
1208   xx  
1209 */
1210   {5, {{0,0}, {1,0}, {2,0}, {2,1}, {3,1}},
1211    8, {0, 1, 2, 3, 4, 5, 6, 7}, 3},
1212 /*
1213 xxx   
1214  xx   
1215 */
1216   {5, {{0,0}, {1,0}, {1,1}, {2,0}, {2,1}},
1217    8, {0, 1, 2, 3, 4, 5, 6, 7}, 3},
1218 /*
1219 xxx   
1220   x   
1221   x   
1222 */
1223   {5, {{0,0}, {1,0}, {2,0}, {2,1}, {2,2}},
1224    4, {0, 1, 2, 3, -1, -1, -1, -1}, 3},
1225 /*
1226  x    
1227 xxx   
1228   x   
1229 */
1230   {5, {{0,0}, {1,-1}, {1,0}, {2,0}, {2,1}},
1231    8, {0, 1, 2, 3, 4, 5, 6, 7}, 3},
1232 /*
1233 xxx   
1234 x x   
1235 */
1236   {5, {{0,0}, {0,1}, {1,0}, {2,0}, {2,1}},
1237    4, {0, 1, 2, 3, -1, -1, -1, -1}, 3},
1238 /*
1239   x   
1240 xxx   
1241 x     
1242 */
1243   {5, {{0,0}, {0,1}, {1,0}, {2,-1}, {2,0}},
1244    4, {0, 1, 4, 5, -1, -1, -1, -1}, 3},
1245 /*
1246  x    
1247 xxx   
1248  x    
1249 */
1250   {5, {{0,0}, {1,-1}, {1,0}, {1,1}, {2,0}},
1251    1, {0, -1, -1, -1, -1, -1, -1, -1}, 4},
1252 /*
1253 xx    
1254  xx   
1255   x   
1256 */
1257   {5, {{0,0}, {1,0}, {1,1}, {2,1}, {2,2}},
1258    4, {0, 1, 2, 3, -1, -1, -1, -1}, 3}};
1259
1260
1261 static struct hexomino_struct {int len; point_type point[6];
1262                                int transform_len, transform_list[8], max_white;}
1263   hexomino[35] =
1264 {
1265 /*
1266 xxxxxx 
1267 */
1268   {6, {{0,0}, {1,0}, {2,0}, {3,0}, {4,0}, {5,0}},
1269    2, {0, 1, -1, -1, -1, -1, -1, -1}, 3},
1270 /*
1271 xxxxx  
1272     x  
1273 */
1274   {6, {{0,0}, {1,0}, {2,0}, {3,0}, {4,0}, {4,1}},
1275    8, {0, 1, 2, 3, 4, 5, 6, 7}, 3},
1276 /*
1277 xxxxx  
1278    x   
1279 */
1280   {6, {{0,0}, {1,0}, {2,0}, {3,0}, {3,1}, {4,0}},
1281    8, {0, 1, 2, 3, 4, 5, 6, 7}, 4},
1282 /*
1283 xxxxx  
1284   x    
1285 */
1286   {6, {{0,0}, {1,0}, {2,0}, {2,1}, {3,0}, {4,0}},
1287    4, {0, 1, 2, 3, -1, -1, -1, -1}, 3},
1288 /*
1289    x   
1290 xxxx   
1291    x   
1292 */
1293   {6, {{0,0}, {1,0}, {2,0}, {3,-1}, {3,0}, {3,1}},
1294    4, {0, 1, 2, 3, -1, -1, -1, -1}, 4},
1295 /*
1296 xxxx   
1297    xx  
1298 */
1299   {6, {{0,0}, {1,0}, {2,0}, {3,0}, {3,1}, {4,1}},
1300    8, {0, 1, 2, 3, 4, 5, 6, 7}, 3},
1301 /*
1302 xxxx   
1303   xx   
1304 */
1305   {6, {{0,0}, {1,0}, {2,0}, {2,1}, {3,0}, {3,1}},
1306    8, {0, 1, 2, 3, 4, 5, 6, 7}, 3},
1307 /*
1308 xxxx   
1309    x   
1310    x   
1311 */
1312   {6, {{0,0}, {1,0}, {2,0}, {3,0}, {3,1}, {3,2}},
1313    8, {0, 1, 2, 3, 4, 5, 6, 7}, 3},
1314 /*
1315   x    
1316 xxxx   
1317    x   
1318 */
1319   {6, {{0,0}, {1,0}, {2,-1}, {2,0}, {3,0}, {3,1}},
1320    8, {0, 1, 2, 3, 4, 5, 6, 7}, 3},
1321 /*
1322 xxxx   
1323  x x   
1324 */
1325   {6, {{0,0}, {1,0}, {1,1}, {2,0}, {3,0}, {3,1}},
1326    8, {0, 1, 2, 3, 4, 5, 6, 7}, 4},
1327 /*
1328  x     
1329 xxxx   
1330    x   
1331 */
1332   {6, {{0,0}, {1,-1}, {1,0}, {2,0}, {3,0}, {3,1}},
1333    8, {0, 1, 2, 3, 4, 5, 6, 7}, 4},
1334 /*
1335 xxxx   
1336 x  x   
1337 */
1338   {6, {{0,0}, {0,1}, {1,0}, {2,0}, {3,0}, {3,1}},
1339    4, {0, 1, 2, 3, -1, -1, -1, -1}, 3},
1340 /*
1341    x   
1342 xxxx   
1343 x      
1344 */
1345   {6, {{0,0}, {0,1}, {1,0}, {2,0}, {3,-1}, {3,0}},
1346    4, {0, 1, 4, 5, -1, -1, -1, -1}, 3},
1347 /*
1348   x    
1349 xxxx   
1350   x    
1351 */
1352   {6, {{0,0}, {1,0}, {2,-1}, {2,0}, {2,1}, {3,0}},
1353    4, {0, 1, 2, 3, -1, -1, -1, -1}, 4},
1354 /*
1355 xxxx   
1356  xx    
1357 */
1358   {6, {{0,0}, {1,0}, {1,1}, {2,0}, {2,1}, {3,0}},
1359    4, {0, 1, 2, 3, -1, -1, -1, -1}, 3},
1360 /*
1361 xxxx   
1362   x    
1363   x    
1364 */
1365   {6, {{0,0}, {1,0}, {2,0}, {2,1}, {2,2}, {3,0}},
1366    8, {0, 1, 2, 3, 4, 5, 6, 7}, 3},
1367 /*
1368  x     
1369 xxxx   
1370   x    
1371 */
1372   {6, {{0,0}, {1,-1}, {1,0}, {2,0}, {2,1}, {3,0}},
1373    4, {0, 1, 4, 5, -1, -1, -1, -1}, 3},
1374 /*
1375   xx   
1376 xxx    
1377   x    
1378 */
1379   {6, {{0,0}, {1,0}, {2,-1}, {2,0}, {2,1}, {3,-1}},
1380    8, {0, 1, 2, 3, 4, 5, 6, 7}, 3},
1381 /*
1382  xx    
1383 xxx    
1384   x    
1385 */
1386   {6, {{0,0}, {1,-1}, {1,0}, {2,-1}, {2,0}, {2,1}},
1387    8, {0, 1, 2, 3, 4, 5, 6, 7}, 3},
1388 /*
1389   x    
1390 xxx    
1391 x x    
1392 */
1393   {6, {{0,0}, {0,1}, {1,0}, {2,-1}, {2,0}, {2,1}},
1394    8, {0, 1, 2, 3, 4, 5, 6, 7}, 4},
1395 /*
1396 xxx    
1397   xxx  
1398 */
1399   {6, {{0,0}, {1,0}, {2,0}, {2,1}, {3,1}, {4,1}},
1400    4, {0, 1, 4, 5, -1, -1, -1, -1}, 3},
1401 /*
1402 xxx    
1403   xx   
1404    x   
1405 */
1406   {6, {{0,0}, {1,0}, {2,0}, {2,1}, {3,1}, {3,2}},
1407    8, {0, 1, 2, 3, 4, 5, 6, 7}, 3},
1408 /*
1409 xxx    
1410  xxx   
1411 */
1412   {6, {{0,0}, {1,0}, {1,1}, {2,0}, {2,1}, {3,1}},
1413    4, {0, 1, 4, 5, -1, -1, -1, -1}, 4},
1414 /*
1415 xxx    
1416   xx   
1417   x    
1418 */
1419   {6, {{0,0}, {1,0}, {2,0}, {2,1}, {2,2}, {3,1}},
1420    8, {0, 1, 2, 3, 4, 5, 6, 7}, 4},
1421 /*
1422  x     
1423 xxx    
1424   xx   
1425 */
1426   {6, {{0,0}, {1,-1}, {1,0}, {2,0}, {2,1}, {3,1}},
1427    8, {0, 1, 2, 3, 4, 5, 6, 7}, 4},
1428 /*
1429 xxx    
1430 x xx   
1431 */
1432   {6, {{0,0}, {0,1}, {1,0}, {2,0}, {2,1}, {3,1}},
1433    8, {0, 1, 2, 3, 4, 5, 6, 7}, 3},
1434 /*
1435 xxx    
1436  xx    
1437   x    
1438 */
1439   {6, {{0,0}, {1,0}, {1,1}, {2,0}, {2,1}, {2,2}},
1440    4, {0, 1, 2, 3, -1, -1, -1, -1}, 4},
1441 /*
1442  x     
1443 xxx    
1444  xx    
1445 */
1446   {6, {{0,0}, {1,-1}, {1,0}, {1,1}, {2,0}, {2,1}},
1447    4, {0, 1, 2, 3, -1, -1, -1, -1}, 4},
1448 /*
1449 xxx    
1450 xxx    
1451 */
1452   {6, {{0,0}, {0,1}, {1,0}, {1,1}, {2,0}, {2,1}},
1453    2, {0, 1, -1, -1, -1, -1, -1, -1}, 3},
1454 /*
1455 xxx    
1456   x    
1457   xx   
1458 */
1459   {6, {{0,0}, {1,0}, {2,0}, {2,1}, {2,2}, {3,2}},
1460    8, {0, 1, 2, 3, 4, 5, 6, 7}, 3},
1461 /*
1462 xxx    
1463   x    
1464  xx    
1465 */
1466   {6, {{0,0}, {1,0}, {1,2}, {2,0}, {2,1}, {2,2}},
1467    8, {0, 1, 2, 3, 4, 5, 6, 7}, 3},
1468 /*
1469  x     
1470 xxx    
1471 x x    
1472 */
1473   {6, {{0,0}, {0,1}, {1,-1}, {1,0}, {2,0}, {2,1}},
1474    4, {0, 1, 2, 3, -1, -1, -1, -1}, 3},
1475 /*
1476   xx   
1477 xxx    
1478 x      
1479 */
1480   {6, {{0,0}, {0,1}, {1,0}, {2,-1}, {2,0}, {3,-1}},
1481    8, {0, 1, 2, 3, 4, 5, 6, 7}, 3},
1482 /*
1483  xx    
1484 xxx    
1485 x      
1486 */
1487   {6, {{0,0}, {0,1}, {1,-1}, {1,0}, {2,-1}, {2,0}},
1488    8, {0, 1, 2, 3, 4, 5, 6, 7}, 3},
1489 /*
1490 xx     
1491  xx    
1492   xx   
1493 */
1494   {6, {{0,0}, {1,0}, {1,1}, {2,1}, {2,2}, {3,2}},
1495    4, {0, 1, 4, 5, -1, -1, -1, -1}, 3}};
1496
1497 static struct pentomino_struct one_sided_pentomino[60];
1498
1499 static void make_one_sided_pentomino(void)
1500 {
1501   int i,j,t,u;
1502
1503   j=0;
1504   for (i=0;i<18;i++) {
1505     one_sided_pentomino[j] = pentomino[i];
1506     for (t=0;t<8;t++)
1507       if (one_sided_pentomino[j].transform_list[t]>=4) {
1508         one_sided_pentomino[j].transform_len = t;
1509         j++;
1510         one_sided_pentomino[j] = pentomino[i];
1511         for (u=t;u<8;u++) one_sided_pentomino[j].transform_list[u-t] = one_sided_pentomino[j].transform_list[u];
1512         one_sided_pentomino[j].transform_len -= t;
1513         break;
1514       }
1515     j++;
1516   }
1517 }
1518
1519 static struct hexomino_struct one_sided_hexomino[60];
1520
1521 static void make_one_sided_hexomino(void)
1522 {
1523   int i,j,t,u;
1524
1525   j=0;
1526   for (i=0;i<35;i++) {
1527     one_sided_hexomino[j] = hexomino[i];
1528     for (t=0;t<8;t++)
1529       if (one_sided_hexomino[j].transform_list[t]>=4) {
1530         one_sided_hexomino[j].transform_len = t;
1531         j++;
1532         one_sided_hexomino[j] = hexomino[i];
1533         for (u=t;u<8;u++) one_sided_hexomino[j].transform_list[u-t] = one_sided_hexomino[j].transform_list[u];
1534         one_sided_hexomino[j].transform_len -= t;
1535         break;
1536       }
1537     j++;
1538   }
1539 }
1540
1541 /*
1542 Find all the ways of placing all twelve pentominoes
1543 into a rectangle whose size is 20x3, 15x4, 12x5 or 10x6.
1544 */
1545
1546 static
1547 int set_pentomino_puzzle(polyominoesstruct *sp)
1548 {
1549   int perm_poly[12], perm_point[5], perm_transform[8], i, p;
1550
1551   switch (NRAND(4)) {
1552     case 0:
1553       sp->width = 20;
1554       sp->height = 3;
1555       break;
1556     case 1:
1557       sp->width = 15;
1558       sp->height = 4;
1559       break;
1560     case 2:
1561       sp->width = 12;
1562       sp->height = 5;
1563       break;
1564     case 3:
1565       sp->width = 10;
1566       sp->height = 6;
1567       break;
1568   }
1569
1570   sp->nr_polyominoes = 12;
1571   set_allocate(sp->polyomino,polyomino_type,12*sizeof(polyomino_type));
1572   random_permutation(12,perm_poly);
1573   for (p=0;p<12;p++) {
1574     copy_polyomino(sp->polyomino[p],pentomino[perm_poly[p]],1);
1575   }
1576
1577   sp->check_ok = check_pentomino_puzzle;
1578
1579   return 1;
1580 }
1581
1582 /*
1583 Many of the following puzzles are inspired by
1584 http://www.xs4all.nl/~gp/PolyominoSolver/Polyomino.html
1585 */
1586
1587 /*
1588 Find all the ways of placing all eighteen one-sided pentominoes
1589 into a rectangle.
1590 */
1591
1592 static
1593 int set_one_sided_pentomino_puzzle(polyominoesstruct *sp)
1594 {
1595   int perm_poly[18], perm_point[5], perm_transform[8], i, p;
1596
1597   make_one_sided_pentomino();
1598
1599   switch (NRAND(4)) {
1600     case 0:
1601       sp->width = 30;
1602       sp->height = 3;
1603       break;
1604     case 1:
1605       sp->width = 18;
1606       sp->height = 5;
1607       break;
1608     case 2:
1609       sp->width = 15;
1610       sp->height = 6;
1611       break;
1612     case 3:
1613       sp->width = 10;
1614       sp->height = 9;
1615       break;
1616   }
1617
1618   sp->nr_polyominoes = 18;
1619   set_allocate(sp->polyomino,polyomino_type,18*sizeof(polyomino_type));
1620   random_permutation(18,perm_poly);
1621   for (p=0;p<18;p++) {
1622     copy_polyomino(sp->polyomino[p],one_sided_pentomino[perm_poly[p]],1);
1623   }
1624
1625   sp->check_ok = check_pentomino_puzzle;
1626
1627   return 1;
1628 }
1629
1630 /*
1631 Find all the ways of placing all sixty one-sided hexominoes
1632 into a rectangle.
1633 */
1634
1635 static
1636 int set_one_sided_hexomino_puzzle(polyominoesstruct *sp)
1637 {
1638   int perm_poly[60], perm_point[6], perm_transform[8], i, p;
1639
1640   make_one_sided_hexomino();
1641
1642   switch (NRAND(8)) {
1643     case 0:
1644       sp->width = 20;
1645       sp->height = 18;
1646       break;
1647     case 1:
1648       sp->width = 24;
1649       sp->height = 15;
1650       break;
1651     case 2:
1652       sp->width = 30;
1653       sp->height = 12;
1654       break;
1655     case 3:
1656       sp->width = 36;
1657       sp->height = 10;
1658       break;
1659     case 4:
1660       sp->width = 40;
1661       sp->height = 9;
1662       break;
1663     case 5:
1664       sp->width = 45;
1665       sp->height = 8;
1666       break;
1667     case 6:
1668       sp->width = 60;
1669       sp->height = 6;
1670       break;
1671     case 7:
1672       sp->width = 72;
1673       sp->height = 5;
1674       break;
1675   }
1676
1677   sp->nr_polyominoes = 60;
1678   set_allocate(sp->polyomino,polyomino_type,60*sizeof(polyomino_type));
1679   random_permutation(60,perm_poly);
1680   for (p=0;p<60;p++) {
1681     copy_polyomino(sp->polyomino[p],one_sided_hexomino[perm_poly[p]],1);
1682   }
1683
1684   sp->check_ok = check_hexomino_puzzle;
1685
1686   return 1;
1687 }
1688
1689 /*
1690 Find all the ways of placing all five tetrominoes and all twelve
1691 pentominoes into a rectangle.
1692 */
1693
1694 static
1695 int set_tetr_pentomino_puzzle(polyominoesstruct *sp)
1696 {
1697   int perm_poly[17], perm_point[5], perm_transform[8], i, p;
1698
1699   switch (NRAND(3)) {
1700     case 0:
1701       sp->width = 20;
1702       sp->height = 4;
1703       break;
1704     case 1:
1705       sp->width = 16;
1706       sp->height = 5;
1707       break;
1708     case 2:
1709       sp->width = 10;
1710       sp->height = 8;
1711       break;
1712   }
1713
1714   sp->nr_polyominoes = 17;
1715   set_allocate(sp->polyomino,polyomino_type,17*sizeof(polyomino_type));
1716   random_permutation(17,perm_poly);
1717   for (p=0;p<5;p++) {
1718     copy_polyomino(sp->polyomino[perm_poly[p]],tetromino[p],1);
1719   }
1720   for (p=0;p<12;p++) {
1721     copy_polyomino(sp->polyomino[perm_poly[p+5]],pentomino[p],1);
1722   }
1723
1724   sp->check_ok = check_tetr_pentomino_puzzle;
1725
1726   return 1;
1727 }
1728 /*
1729 Find all the ways of placing all twelve pentominoes and all thirty five
1730 hexominoes into a rectangle whose size is 18x15.
1731 */
1732
1733 static
1734 int set_pent_hexomino_puzzle(polyominoesstruct *sp)
1735 {
1736   int perm_poly[47], perm_point[6], perm_transform[8], i, p;
1737
1738   switch (NRAND(5)) {
1739     case 0:
1740       sp->width = 54;
1741       sp->height = 5;
1742       break;
1743     case 1:
1744       sp->width = 45;
1745       sp->height = 6;
1746       break;
1747     case 2:
1748       sp->width = 30;
1749       sp->height = 9;
1750       break;
1751     case 3:
1752       sp->width = 27;
1753       sp->height = 10;
1754       break;
1755     case 4:
1756       sp->width = 18;
1757       sp->height = 15;
1758       break;
1759   }
1760
1761   sp->nr_polyominoes = 47;
1762   set_allocate(sp->polyomino,polyomino_type,47*sizeof(polyomino_type));
1763   random_permutation(47,perm_poly);
1764   for (p=0;p<12;p++) {
1765     copy_polyomino(sp->polyomino[perm_poly[p]],pentomino[p],1);
1766   }
1767   for (p=0;p<35;p++) {
1768     copy_polyomino(sp->polyomino[perm_poly[p+12]],hexomino[p],1);
1769   }
1770
1771   sp->check_ok = check_pent_hexomino_puzzle;
1772
1773   return 1;
1774 }
1775
1776 /*
1777 Other puzzles:
1778
1779 Science News September 20, 1986 Vol 130, No 12
1780 Science News November 14, 1987 Vol 132, Pg 310
1781 */
1782
1783 /*
1784
1785  *
1786 **** fills a 10x5 rectangle
1787
1788 */
1789
1790 static struct {int len; point_type point[5]; 
1791                int transform_len, transform_list[8], max_white;} pentomino1 =
1792   {5, {{0,0}, {1,0}, {2,0}, {3,0}, {1,1}},
1793    8, {0, 1, 2, 3, 4, 5, 6, 7}, 3};
1794
1795 static
1796 int set_pentomino_puzzle1(polyominoesstruct *sp)
1797 {
1798   int perm_point[5], perm_transform[8], i, p;
1799
1800   sp->width = 10;
1801   sp->height =5;
1802
1803   sp->nr_polyominoes = 10;
1804   set_allocate(sp->polyomino,polyomino_type,10*sizeof(polyomino_type));
1805   for (p=0;p<10;p++) {
1806     copy_polyomino(sp->polyomino[p],pentomino1,1);
1807   }
1808
1809   sp->check_ok = check_pentomino_puzzle;
1810
1811   return 1;
1812 }
1813
1814 /*
1815
1816  *
1817 ***** fills a 24x23 rectangle
1818
1819 */
1820
1821 static struct {int len; point_type point[6]; 
1822                int transform_len, transform_list[8], max_white;} hexomino1 =
1823   {6, {{0,0}, {1,0}, {2,0}, {3,0}, {4,0}, {1,1}},
1824    8, {0, 1, 2, 3, 4, 5, 6, 7}, 4};
1825
1826 static
1827 int set_hexomino_puzzle1(polyominoesstruct *sp)
1828 {
1829   int perm_point[6], perm_transform[8], i, p;
1830
1831   sp->width = 24;
1832   sp->height =23;
1833
1834   sp->nr_polyominoes = 92;
1835   set_allocate(sp->polyomino,polyomino_type,92*sizeof(polyomino_type));
1836   for (p=0;p<92;p++) {
1837     copy_polyomino(sp->polyomino[p],hexomino1,1);
1838   }
1839
1840   sp->check_ok = check_hexomino_puzzle;
1841
1842   return 1;
1843 }
1844
1845 /*
1846
1847  **
1848 ***** fills a 21x26 rectangle
1849
1850 (All solutions have 180 degree rotational symmetry)
1851
1852 */
1853
1854 static struct {int len; point_type point[7]; 
1855                int transform_len, transform_list[8], max_white;} heptomino1 =
1856   {7, {{0,0}, {1,0}, {2,0}, {3,0}, {4,0}, {1,1}, {2,1}},
1857    8, {0, 1, 2, 3, 4, 5, 6, 7}, 4};
1858
1859 static
1860 int set_heptomino_puzzle1(polyominoesstruct *sp)
1861 {
1862   int perm_point[7], perm_transform[8], i, p;
1863
1864   sp->rot180 = 1;
1865
1866   sp->width = 26;
1867   sp->height =21;
1868
1869   sp->nr_polyominoes = 78;
1870   set_allocate(sp->polyomino,polyomino_type,78*sizeof(polyomino_type));
1871   for (p=0;p<78;p+=2) {
1872     copy_polyomino(sp->polyomino[p],heptomino1,1);
1873     copy_polyomino(sp->polyomino[p+1],heptomino1,0);
1874   }
1875
1876   sp->check_ok = check_heptomino_puzzle;
1877
1878   return 1;
1879 }
1880
1881 /* The following puzzles from 
1882 Polyominoes Puzzles, Patterns, Problems, and Packings Revised (2nd) Edition
1883 by Solomon W. Golomb   Princeton University Press 1994
1884 */
1885
1886 /*
1887
1888  **
1889 ***** fills a 28x19 rectangle
1890
1891 */
1892 static
1893 int set_heptomino_puzzle2(polyominoesstruct *sp)
1894 {
1895   int perm_point[7], perm_transform[8], i, p;
1896
1897   sp->width = 28;
1898   sp->height =19;
1899
1900   sp->nr_polyominoes = 76;
1901   set_allocate(sp->polyomino,polyomino_type,76*sizeof(polyomino_type));
1902   for (p=0;p<76;p++) {
1903     copy_polyomino(sp->polyomino[p],heptomino1,1);
1904   }
1905
1906   sp->check_ok = check_heptomino_puzzle;
1907
1908   return 1;
1909 }
1910
1911 /*
1912
1913 ***
1914 **** fills a 25x22 rectangle
1915 ****
1916
1917 */
1918
1919 static struct {int len; point_type point[11]; 
1920                int transform_len, transform_list[8], max_white;} elevenomino1 =
1921   {11, {{0,0}, {1,0}, {2,0}, 
1922         {0,1}, {1,1}, {2,1}, {3,1},
1923         {0,2}, {1,2}, {2,2}, {3,2}},
1924    8, {0, 1, 2, 3, 4, 5, 6, 7}, 6};
1925
1926 static
1927 int set_elevenomino_puzzle1(polyominoesstruct *sp)
1928 {
1929   int perm_point[11], perm_transform[8], i, p;
1930
1931   sp->rot180 = 1;
1932
1933   sp->width = 25;
1934   sp->height =22;
1935
1936   sp->nr_polyominoes = 50;
1937   set_allocate(sp->polyomino,polyomino_type,50*sizeof(polyomino_type));
1938   for (p=0;p<50;p+=2) {
1939     copy_polyomino(sp->polyomino[p],elevenomino1,1);
1940     copy_polyomino(sp->polyomino[p+1],elevenomino1,0);
1941   }
1942
1943   sp->check_ok = check_elevenomino_puzzle;
1944
1945   return 1;
1946 }
1947
1948 /*
1949
1950  *
1951  *
1952 **** fills 32 x 30 rectangle
1953 ****
1954
1955 */
1956
1957 static struct {int len; point_type point[10]; 
1958                int transform_len, transform_list[8], max_white;} dekomino1 =
1959   {10, {       {1,-1},
1960                {1,0}, 
1961         {0,1}, {1,1}, {2,1}, {3,1},
1962         {0,2}, {1,2}, {2,2}, {3,2}},
1963    8, {0, 1, 2, 3, 4, 5, 6, 7}, 5};
1964
1965 static
1966 int set_dekomino_puzzle1(polyominoesstruct *sp)
1967 {
1968   int perm_point[10], perm_transform[8], i, p;
1969
1970   sp->width = 32;
1971   sp->height =30;
1972
1973   sp->nr_polyominoes = 96;
1974   set_allocate(sp->polyomino,polyomino_type,96*sizeof(polyomino_type));
1975   for (p=0;p<96;p++) {
1976     copy_polyomino(sp->polyomino[p],dekomino1,1);
1977   }
1978
1979   sp->check_ok = check_dekomino_puzzle;
1980
1981   return 1;
1982 }
1983
1984 /*
1985
1986  *
1987 ***  fills 96 x 26 rectangle
1988 ****
1989
1990 */
1991
1992 static struct {int len; point_type point[10]; 
1993                int transform_len, transform_list[8], max_white;} octomino1 =
1994   {8, {        {1,0}, 
1995         {0,1}, {1,1}, {2,1},
1996         {0,2}, {1,2}, {2,2}, {3,2}},
1997    8, {0, 1, 2, 3, 4, 5, 6, 7}, 5};
1998
1999 static
2000 int set_octomino_puzzle1(polyominoesstruct *sp)
2001 {
2002   int perm_point[8], perm_transform[8], i, p;
2003
2004   sp->width = 96;
2005   sp->height =26;
2006
2007   sp->nr_polyominoes = 312;
2008   set_allocate(sp->polyomino,polyomino_type,312*sizeof(polyomino_type));
2009   for (p=0;p<312;p++) {
2010     copy_polyomino(sp->polyomino[p],octomino1,1);
2011   }
2012
2013   sp->check_ok = check_octomino_puzzle;
2014
2015   return 1;
2016 }
2017
2018 /*
2019
2020  *   fills 15 x 15 rectangle
2021 ****
2022
2023 */
2024
2025 static
2026 int set_pentomino_puzzle2(polyominoesstruct *sp)
2027 {
2028   int perm_point[5], perm_transform[8], i, p;
2029
2030   sp->width = 15;
2031   sp->height =15;
2032
2033   sp->nr_polyominoes = 45;
2034   set_allocate(sp->polyomino,polyomino_type,45*sizeof(polyomino_type));
2035   for (p=0;p<45;p++) {
2036     copy_polyomino(sp->polyomino[p],pentomino1,1);
2037   }
2038
2039   sp->check_ok = check_pentomino_puzzle;
2040
2041   return 1;
2042 }
2043
2044 /*
2045
2046 ***
2047 **** fills a 47x33 rectangle
2048 ****
2049
2050 */
2051
2052 static
2053 int set_elevenomino_puzzle2(polyominoesstruct *sp)
2054 {
2055   int perm_point[11], perm_transform[8], i, p;
2056
2057   sp->width = 47;
2058   sp->height =33;
2059
2060   sp->nr_polyominoes = 141;
2061   set_allocate(sp->polyomino,polyomino_type,141*sizeof(polyomino_type));
2062   for (p=0;p<141;p++) {
2063     copy_polyomino(sp->polyomino[p],elevenomino1,1);
2064   }
2065
2066   sp->check_ok = check_elevenomino_puzzle;
2067
2068   return 1;
2069 }
2070
2071 /**************************************************
2072 The main functions.
2073 **************************************************/
2074
2075 #define allocate(p,type,size) p = (type *) malloc(size); if ((p)==NULL) {free_polyominoes(sp); return;}
2076
2077 ENTRYPOINT void
2078 init_polyominoes (ModeInfo * mi)
2079 {
2080   polyominoesstruct *sp;
2081   int i,x,y, start;
2082   int box1, box2;
2083   int *perm;
2084
2085   if (polyominoeses == NULL) {
2086     if ((polyominoeses
2087          = (polyominoesstruct *) calloc(MI_NUM_SCREENS(mi),sizeof (polyominoesstruct))) 
2088         == NULL)
2089       return;
2090   }
2091   sp = &polyominoeses[MI_SCREEN(mi)];
2092
2093   free_polyominoes(sp);
2094
2095   sp->rot180 = 0;
2096   sp->counter = 0;
2097
2098   if (MI_IS_FULLRANDOM(mi)) {
2099     sp->identical = (Bool) (LRAND() & 1);
2100     sp->use3D = (Bool) (NRAND(4));
2101   } else {
2102     sp->identical = identical; 
2103     sp->use3D = !plain;
2104   }
2105   if (sp->identical) {
2106     switch (NRAND(9)) {
2107       case 0:
2108         if (!set_pentomino_puzzle1(sp))
2109           return;
2110         break;
2111       case 1:
2112         if (!set_hexomino_puzzle1(sp))
2113           return;
2114         break;
2115       case 2:
2116         if (!set_heptomino_puzzle1(sp))
2117           return;
2118         break;
2119       case 3:
2120         if (!set_heptomino_puzzle2(sp))
2121           return;
2122         break;
2123       case 4:
2124         if (!set_elevenomino_puzzle1(sp))
2125           return;
2126         break;
2127       case 5:
2128         if (!set_dekomino_puzzle1(sp))
2129           return;
2130         break;
2131       case 6:
2132         if (!set_octomino_puzzle1(sp))
2133           return;
2134         break;
2135       case 7:
2136         if (!set_pentomino_puzzle2(sp))
2137           return;
2138         break;
2139       case 8:
2140         if (!set_elevenomino_puzzle2(sp))
2141           return;
2142         break;
2143     }
2144   } else {
2145     switch (NRAND(5)) {
2146       case 0:
2147         if (!set_pentomino_puzzle(sp))
2148           return;
2149         break;
2150       case 1:
2151         if (!set_one_sided_pentomino_puzzle(sp))
2152           return;
2153         break;
2154       case 2:
2155         if (!set_one_sided_hexomino_puzzle(sp))
2156           return;
2157         break;
2158       case 3:
2159         if (!set_pent_hexomino_puzzle(sp))
2160           return;
2161         break;
2162       case 4:
2163         if (!set_tetr_pentomino_puzzle(sp))
2164           return;
2165         break;
2166     }
2167   }
2168
2169   allocate(sp->attach_list,int,sp->nr_polyominoes*sizeof(int));
2170   sp->nr_attached = 0;
2171
2172   if (sp->identical) {
2173     allocate(sp->reason_to_not_attach,int,sp->nr_polyominoes*sp->nr_polyominoes*sizeof(int));
2174   }
2175
2176   allocate(sp->array,int,sp->width*sp->height*sizeof(int));
2177   allocate(sp->changed_array,int,sp->width*sp->height*sizeof(int));
2178   for (x=0;x<sp->width;x++) for (y=0;y<sp->height;y++) ARRAY(x,y) = -1;
2179
2180   sp->left_right = NRAND(2);
2181   sp->top_bottom = NRAND(2);
2182
2183   box1 = MI_WIDTH(mi)/(sp->width+2);
2184   box2 = MI_HEIGHT(mi)/(sp->height+2);
2185   if (box1<box2)
2186     sp->box = box1;
2187   else
2188     sp->box = box2;
2189
2190   if (sp->box >= 12) {
2191     sp->box = (sp->box/12)*12;
2192     create_bitmaps(mi,sp);
2193     if (!sp->use_bitmaps)
2194       free_bitmaps(sp);
2195    }
2196    else
2197      sp->use_bitmaps = 0;
2198
2199   if (!sp->use_bitmaps) {
2200     allocate(sp->rectangles,XRectangle,sp->width*sp->height*sizeof(XRectangle));
2201     allocate(sp->lines,XSegment,sp->width*sp->height*sizeof(XSegment));
2202   }
2203
2204   allocate(perm,int,sp->nr_polyominoes*sizeof(int));
2205   random_permutation(sp->nr_polyominoes, perm);
2206   sp->mono = MI_NPIXELS(mi) < 12;
2207   start = NRAND(MI_NPIXELS(mi));
2208   for (i=0;i<sp->nr_polyominoes;i++)
2209     if (!sp->mono) {
2210       sp->polyomino[i].color = MI_PIXEL(mi,(perm[i]*MI_NPIXELS(mi) / sp->nr_polyominoes + start) % MI_NPIXELS(mi));
2211       if (sp->rot180) {
2212          sp->polyomino[i+1].color = sp->polyomino[i].color;
2213          i++;
2214       }
2215     }
2216     else
2217       if(sp->use_bitmaps)
2218         sp->polyomino[i].color = MI_WHITE_PIXEL(mi);
2219       else
2220         sp->polyomino[i].color = MI_BLACK_PIXEL(mi);
2221   free(perm);
2222
2223   if (sp->use_bitmaps) {
2224     if (sp->mono)
2225       sp->border_color = MI_WHITE_PIXEL(mi);
2226     else
2227       sp->border_color = MI_PIXEL(mi,NRAND(MI_NPIXELS(mi)));
2228   }
2229
2230   sp->x_margin = (MI_WIDTH(mi)-sp->box*sp->width)/2;
2231   sp->y_margin = (MI_HEIGHT(mi)-sp->box*sp->height)/2;
2232
2233   sp->wait = 0;
2234
2235 #ifndef STANDALONE
2236   /* Clear the background. */
2237   MI_CLEARWINDOW(mi);
2238 #endif
2239   
2240 }
2241
2242 ENTRYPOINT void
2243 draw_polyominoes (ModeInfo * mi)
2244 {
2245   polyominoesstruct *sp;
2246   int poly_no,point_no,transform_index,done,another_attachment_try;
2247   point_type attach_point;
2248   int i,detach_until;
2249
2250   if (polyominoeses == NULL)
2251     return;
2252   sp = &polyominoeses[MI_SCREEN(mi)];
2253
2254 #ifdef STANDALONE
2255     if (sp->eraser) {
2256       sp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), sp->eraser);
2257       return;
2258     }
2259 #endif
2260
2261   if (MI_CYCLES(mi) != 0) {
2262     if (++sp->counter > MI_CYCLES(mi)) {
2263 #ifdef STANDALONE
2264       sp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), sp->eraser);
2265 #endif /* STANDALONE */
2266       init_polyominoes(mi);
2267       return;
2268     }
2269   }
2270
2271   if (sp->box == 0) {
2272 #ifdef STANDALONE
2273     sp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), sp->eraser);
2274 #endif /* STANDALONE */
2275     init_polyominoes(mi);
2276     return;
2277   }
2278
2279   MI_IS_DRAWN(mi) = True;
2280   sp->wait--;
2281   if (sp->wait>0) return;
2282
2283   memset(sp->changed_array,0,sp->width*sp->height*sizeof(int));
2284
2285   poly_no = first_poly_no(sp);
2286   point_no = 0;
2287   transform_index = 0;
2288   done = 0;
2289   another_attachment_try = 1;
2290   find_blank(sp,&attach_point);
2291   if (sp->identical && sp->nr_attached < sp->nr_polyominoes)
2292     memset(&REASON_TO_NOT_ATTACH(sp->nr_attached,0),0,sp->nr_polyominoes*sizeof(int));
2293   while(!done) {
2294     if (sp->nr_attached < sp->nr_polyominoes) {
2295       while (!done && another_attachment_try) {
2296         done = attach(sp,poly_no,point_no,transform_index,attach_point,0,&REASON_TO_NOT_ATTACH(sp->nr_attached,0));
2297         if (done && sp->rot180) {
2298           poly_no = first_poly_no(sp);
2299           done = attach(sp,poly_no,point_no,transform_index,attach_point,1,&REASON_TO_NOT_ATTACH(sp->nr_attached-1,0));
2300           if (!done)
2301             detach(sp,&poly_no,&point_no,&transform_index,&attach_point,0);
2302         }
2303         if (!done)
2304           another_attachment_try = next_attach_try(sp,&poly_no,&point_no,&transform_index);
2305       }
2306     }
2307
2308     if (sp->identical) {
2309       if (!done) {
2310         if (sp->nr_attached == 0)
2311           done = 1;
2312         else {
2313           detach_until=sp->nr_attached-1;
2314           if (sp->nr_attached < sp->nr_polyominoes)
2315             while (detach_until>0 && REASON_TO_NOT_ATTACH(sp->nr_attached,detach_until)==0)
2316               detach_until--;
2317           while (sp->nr_attached>detach_until) {
2318             if (sp->rot180)
2319               detach(sp,&poly_no,&point_no,&transform_index,&attach_point,1);
2320             detach(sp,&poly_no,&point_no,&transform_index,&attach_point,0);
2321             if (sp->nr_attached+1+sp->rot180 < sp->nr_polyominoes)
2322               for (i=0;i<sp->nr_polyominoes;i++)
2323                 REASON_TO_NOT_ATTACH(sp->nr_attached,i) |= REASON_TO_NOT_ATTACH(sp->nr_attached+1+sp->rot180,i);
2324           }
2325           another_attachment_try = next_attach_try(sp,&poly_no,&point_no,&transform_index);
2326         }
2327       }
2328     }
2329     else {
2330       if (!done) {
2331         if (sp->nr_attached == 0)
2332           done = 1;
2333         else {
2334           if (sp->rot180)
2335             detach(sp,&poly_no,&point_no,&transform_index,&attach_point,1);
2336           detach(sp,&poly_no,&point_no,&transform_index,&attach_point,0);
2337         }
2338         another_attachment_try = next_attach_try(sp,&poly_no,&point_no,&transform_index);
2339       }
2340     }
2341   }
2342
2343   if (sp->use_bitmaps)
2344     draw_with_bitmaps(mi,sp);
2345   else
2346     draw_without_bitmaps(mi,sp);
2347
2348   if (sp->nr_attached == sp->nr_polyominoes)
2349     sp->wait = 100;
2350   else
2351     sp->wait = 0;
2352 }
2353
2354 ENTRYPOINT void
2355 release_polyominoes(ModeInfo * mi)
2356 {
2357   int screen;
2358   
2359   if (polyominoeses != NULL) {
2360     for (screen=0;screen<MI_NUM_SCREENS(mi); screen++)
2361       free_polyominoes(&polyominoeses[screen]);
2362     (void) free((void *) polyominoeses);
2363     polyominoeses = (polyominoesstruct *) NULL;
2364   }
2365 }
2366
2367 ENTRYPOINT void
2368 refresh_polyominoes (ModeInfo * mi)
2369 {
2370   MI_CLEARWINDOW(mi);
2371 }
2372
2373 XSCREENSAVER_MODULE ("Polyominoes", polyominoes)
2374
2375 #endif /* MODE_polyominoes */