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