#define MAX_2SUMS 5
#define MAX_3SUMS 8
#define MAX_4SUMS 12
-unsigned int sum_bits2[18][MAX_2SUMS];
-unsigned int sum_bits3[25][MAX_3SUMS];
-unsigned int sum_bits4[31][MAX_4SUMS];
+unsigned long sum_bits2[18][MAX_2SUMS];
+unsigned long sum_bits3[25][MAX_3SUMS];
+unsigned long sum_bits4[31][MAX_4SUMS];
-static int find_sum_bits(unsigned int *array, int idx, int value_left,
+static int find_sum_bits(unsigned long *array, int idx, int value_left,
int addends_left, int min_addend,
- unsigned int bitmask_so_far)
+ unsigned long bitmask_so_far)
{
int i;
assert(addends_left >= 2);
for (i = min_addend; i < value_left; i++) {
- unsigned int new_bitmask = bitmask_so_far | (1 << i);
+ unsigned long new_bitmask = bitmask_so_far | (1L << i);
assert(bitmask_so_far != new_bitmask);
if (addends_left == 2) {
break;
if (j > 9)
continue;
- array[idx++] = new_bitmask | (1 << j);
+ array[idx++] = new_bitmask | (1L << j);
} else
idx = find_sum_bits(array, idx, value_left - i,
addends_left - 1, i + 1,
int cr = usage->cr;
int i, ret, max_sums;
int nsquares = cages->nr_squares[b];
- unsigned int *sumbits, possible_addends;
+ unsigned long *sumbits, possible_addends;
if (clue == 0) {
assert(nsquares == 0);
possible_addends = 0;
for (i = 0; i < max_sums; i++) {
int j;
- unsigned int bits = sumbits[i];
+ unsigned long bits = sumbits[i];
if (bits == 0)
break;
for (j = 0; j < nsquares; j++) {
int n;
- unsigned int square_bits = bits;
+ unsigned long square_bits = bits;
int x = cages->blocks[b][j];
for (n = 1; n <= cr; n++)
if (!cube2(x, n))
- square_bits &= ~(1 << n);
+ square_bits &= ~(1L << n);
if (square_bits == 0) {
break;
}
/*
* Check whether a grid contains a valid complete puzzle.
*/
-static int check_valid(int cr, struct block_structure *blocks, int xtype,
- digit *grid)
+static int check_valid(int cr, struct block_structure *blocks,
+ struct block_structure *kblocks, int xtype, digit *grid)
{
unsigned char *used;
int x, y, i, j, n;
}
/*
+ * Check that each Killer cage, if any, contains at most one of
+ * everything.
+ */
+ if (kblocks) {
+ for (i = 0; i < kblocks->nr_blocks; i++) {
+ memset(used, FALSE, cr);
+ for (j = 0; j < kblocks->nr_squares[i]; j++)
+ if (grid[kblocks->blocks[i][j]] > 0 &&
+ grid[kblocks->blocks[i][j]] <= cr) {
+ if (used[grid[kblocks->blocks[i][j]]-1]) {
+ sfree(used);
+ return FALSE;
+ }
+ used[grid[kblocks->blocks[i][j]]-1] = TRUE;
+ }
+ }
+ }
+
+ /*
* Check that each diagonal contains precisely one of everything.
*/
if (xtype) {
if (!gridgen(cr, blocks, kblocks, params->xtype, grid, rs, area*area))
continue;
- assert(check_valid(cr, blocks, params->xtype, grid));
+ assert(check_valid(cr, blocks, kblocks, params->xtype, grid));
/*
* Save the solved grid in aux.
unsigned char *pencil;
unsigned char *hl;
/* This is scratch space used within a single call to game_redraw. */
- int *entered_items;
+ int nregions, *entered_items;
};
static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
* We've made a real change to the grid. Check to see
* if the game has been completed.
*/
- if (!ret->completed && check_valid(cr, ret->blocks, ret->xtype,
- ret->grid)) {
+ if (!ret->completed && check_valid(cr, ret->blocks, ret->kblocks,
+ ret->xtype, ret->grid)) {
ret->completed = TRUE;
}
}
memset(ds->pencil, 0, cr*cr*cr);
ds->hl = snewn(cr*cr, unsigned char);
memset(ds->hl, 0, cr*cr);
- ds->entered_items = snewn(cr*cr, int);
+ /*
+ * ds->entered_items needs one row of cr entries per entity in
+ * which digits may not be duplicated. That's one for each row,
+ * each column, each block, each diagonal, and each Killer cage.
+ */
+ ds->nregions = cr*3 + 2;
+ if (state->kblocks)
+ ds->nregions += state->kblocks->nr_blocks;
+ ds->entered_items = snewn(cr * ds->nregions, int);
ds->tilesize = 0; /* not decided yet */
return ds;
}
* This array is used to keep track of rows, columns and boxes
* which contain a number more than once.
*/
- for (x = 0; x < cr * cr; x++)
+ for (x = 0; x < cr * ds->nregions; x++)
ds->entered_items[x] = 0;
for (x = 0; x < cr; x++)
for (y = 0; y < cr; y++) {
digit d = state->grid[y*cr+x];
if (d) {
- int box = state->blocks->whichblock[y*cr+x];
- ds->entered_items[x*cr+d-1] |= ((ds->entered_items[x*cr+d-1] & 1) << 1) | 1;
- ds->entered_items[y*cr+d-1] |= ((ds->entered_items[y*cr+d-1] & 4) << 1) | 4;
- ds->entered_items[box*cr+d-1] |= ((ds->entered_items[box*cr+d-1] & 16) << 1) | 16;
+ int box, kbox;
+
+ /* Rows */
+ ds->entered_items[x*cr+d-1]++;
+
+ /* Columns */
+ ds->entered_items[(y+cr)*cr+d-1]++;
+
+ /* Blocks */
+ box = state->blocks->whichblock[y*cr+x];
+ ds->entered_items[(box+2*cr)*cr+d-1]++;
+
+ /* Diagonals */
if (ds->xtype) {
if (ondiag0(y*cr+x))
- ds->entered_items[d-1] |= ((ds->entered_items[d-1] & 64) << 1) | 64;
+ ds->entered_items[(3*cr)*cr+d-1]++;
if (ondiag1(y*cr+x))
- ds->entered_items[cr+d-1] |= ((ds->entered_items[cr+d-1] & 64) << 1) | 64;
+ ds->entered_items[(3*cr+1)*cr+d-1]++;
+ }
+
+ /* Killer cages */
+ if (state->kblocks) {
+ kbox = state->kblocks->whichblock[y*cr+x];
+ ds->entered_items[(kbox+3*cr+2)*cr+d-1]++;
}
}
}
/* Mark obvious errors (ie, numbers which occur more than once
* in a single row, column, or box). */
- if (d && ((ds->entered_items[x*cr+d-1] & 2) ||
- (ds->entered_items[y*cr+d-1] & 8) ||
- (ds->entered_items[state->blocks->whichblock[y*cr+x]*cr+d-1] & 32) ||
- (ds->xtype && ((ondiag0(y*cr+x) && (ds->entered_items[d-1] & 128)) ||
- (ondiag1(y*cr+x) && (ds->entered_items[cr+d-1] & 128))))))
+ if (d && (ds->entered_items[x*cr+d-1] > 1 ||
+ ds->entered_items[(y+cr)*cr+d-1] > 1 ||
+ ds->entered_items[(state->blocks->whichblock[y*cr+x]
+ +2*cr)*cr+d-1] > 1 ||
+ (ds->xtype && ((ondiag0(y*cr+x) &&
+ ds->entered_items[(3*cr)*cr+d-1] > 1) ||
+ (ondiag1(y*cr+x) &&
+ ds->entered_items[(3*cr+1)*cr+d-1]>1)))||
+ (state->kblocks &&
+ ds->entered_items[(state->kblocks->whichblock[y*cr+x]
+ +3*cr+2)*cr+d-1] > 1)))
highlight |= 16;
if (d && state->kblocks) {