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