~ubuntu-branches/ubuntu/dapper/xscreensaver/dapper-updates

« back to all changes in this revision

Viewing changes to hacks/polyominoes.c

  • Committer: Bazaar Package Importer
  • Author(s): Ralf Hildebrandt
  • Date: 2005-04-09 00:06:43 UTC
  • mfrom: (1.1.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20050409000643-z0abtifbt9s20pcc
Tags: 4.21-3
Patch by Joachim Breitner to check more frequently if DPMS kicked in (closes: #303374, #286664).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
  {"-identical", ".polyominoes.identical", XrmoptionNoArg, "on"},
 
62
  {"+identical", ".polyominoes.identical", XrmoptionNoArg, "off"},
 
63
  {"-plain", ".polyominoes.plain", XrmoptionNoArg, "on"},
 
64
  {"+plain", ".polyominoes.plain", XrmoptionNoArg, "off"}
 
65
};
 
66
static argtype vars[] =
 
67
{
 
68
  {&identical, "identical", "Identical", DEF_IDENTICAL, t_Bool},
 
69
  {&plain, "plain", "Plain", DEF_PLAIN, t_Bool}
 
70
};
 
71
static OptionStruct desc[] =
 
72
{
 
73
  {"-/+identical", "turn on/off puzzles where the polyomino pieces are identical"},
 
74
  {"-/+plain", "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 */