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