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