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