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