mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-20 15:41:30 -07:00
Prevent starting in a solved state in Fifteen & Flood
(cherry picked from Android port, commit cb38abdc71780bd9b393b90514396c338306fa69)
This commit is contained in:
141
fifteen.c
141
fifteen.c
@ -156,6 +156,14 @@ static int perm_parity(int *perm, int n)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int is_completed(int *tiles, int n) {
|
||||
int p;
|
||||
for (p = 0; p < n; p++)
|
||||
if (tiles[p] != (p < n-1 ? p+1 : 0))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char *new_game_desc(const game_params *params, random_state *rs,
|
||||
char **aux, bool interactive)
|
||||
{
|
||||
@ -171,81 +179,83 @@ static char *new_game_desc(const game_params *params, random_state *rs,
|
||||
tiles = snewn(n, int);
|
||||
used = snewn(n, bool);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
tiles[i] = -1;
|
||||
used[i] = false;
|
||||
}
|
||||
do {
|
||||
for (i = 0; i < n; i++) {
|
||||
tiles[i] = -1;
|
||||
used[i] = false;
|
||||
}
|
||||
|
||||
gap = random_upto(rs, n);
|
||||
tiles[gap] = 0;
|
||||
used[0] = true;
|
||||
gap = random_upto(rs, n);
|
||||
tiles[gap] = 0;
|
||||
used[0] = true;
|
||||
|
||||
/*
|
||||
* Place everything else except the last two tiles.
|
||||
*/
|
||||
for (x = 0, i = n-1; i > 2; i--) {
|
||||
int k = random_upto(rs, i);
|
||||
int j;
|
||||
/*
|
||||
* Place everything else except the last two tiles.
|
||||
*/
|
||||
for (x = 0, i = n - 1; i > 2; i--) {
|
||||
int k = random_upto(rs, i);
|
||||
int j;
|
||||
|
||||
for (j = 0; j < n; j++)
|
||||
if (!used[j] && (k-- == 0))
|
||||
break;
|
||||
for (j = 0; j < n; j++)
|
||||
if (!used[j] && (k-- == 0))
|
||||
break;
|
||||
|
||||
assert(j < n && !used[j]);
|
||||
used[j] = true;
|
||||
assert(j < n && !used[j]);
|
||||
used[j] = true;
|
||||
|
||||
while (tiles[x] >= 0)
|
||||
x++;
|
||||
assert(x < n);
|
||||
tiles[x] = j;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the last two locations, and the last two pieces.
|
||||
*/
|
||||
while (tiles[x] >= 0)
|
||||
x++;
|
||||
assert(x < n);
|
||||
tiles[x] = j;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the last two locations, and the last two pieces.
|
||||
*/
|
||||
while (tiles[x] >= 0)
|
||||
x1 = x;
|
||||
x++;
|
||||
assert(x < n);
|
||||
x1 = x;
|
||||
x++;
|
||||
while (tiles[x] >= 0)
|
||||
x++;
|
||||
assert(x < n);
|
||||
x2 = x;
|
||||
while (tiles[x] >= 0)
|
||||
x++;
|
||||
assert(x < n);
|
||||
x2 = x;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
if (!used[i])
|
||||
break;
|
||||
p1 = i;
|
||||
for (i = p1+1; i < n; i++)
|
||||
if (!used[i])
|
||||
break;
|
||||
p2 = i;
|
||||
for (i = 0; i < n; i++)
|
||||
if (!used[i])
|
||||
break;
|
||||
p1 = i;
|
||||
for (i = p1 + 1; i < n; i++)
|
||||
if (!used[i])
|
||||
break;
|
||||
p2 = i;
|
||||
|
||||
/*
|
||||
* Determine the required parity of the overall permutation.
|
||||
* This is the XOR of:
|
||||
*
|
||||
* - The chessboard parity ((x^y)&1) of the gap square. The
|
||||
* bottom right counts as even.
|
||||
*
|
||||
* - The parity of n. (The target permutation is 1,...,n-1,0
|
||||
* rather than 0,...,n-1; this is a cyclic permutation of
|
||||
* the starting point and hence is odd iff n is even.)
|
||||
*/
|
||||
parity = PARITY_P(params, gap);
|
||||
/*
|
||||
* Determine the required parity of the overall permutation.
|
||||
* This is the XOR of:
|
||||
*
|
||||
* - The chessboard parity ((x^y)&1) of the gap square. The
|
||||
* bottom right counts as even.
|
||||
*
|
||||
* - The parity of n. (The target permutation is 1,...,n-1,0
|
||||
* rather than 0,...,n-1; this is a cyclic permutation of
|
||||
* the starting point and hence is odd iff n is even.)
|
||||
*/
|
||||
parity = PARITY_P(params, gap);
|
||||
|
||||
/*
|
||||
* Try the last two tiles one way round. If that fails, swap
|
||||
* them.
|
||||
*/
|
||||
tiles[x1] = p1;
|
||||
tiles[x2] = p2;
|
||||
if (perm_parity(tiles, n) != parity) {
|
||||
tiles[x1] = p2;
|
||||
tiles[x2] = p1;
|
||||
assert(perm_parity(tiles, n) == parity);
|
||||
}
|
||||
/*
|
||||
* Try the last two tiles one way round. If that fails, swap
|
||||
* them.
|
||||
*/
|
||||
tiles[x1] = p1;
|
||||
tiles[x2] = p2;
|
||||
if (perm_parity(tiles, n) != parity) {
|
||||
tiles[x1] = p2;
|
||||
tiles[x2] = p1;
|
||||
assert(perm_parity(tiles, n) == parity);
|
||||
}
|
||||
} while (is_completed(tiles, n));
|
||||
|
||||
/*
|
||||
* Now construct the game description, by describing the tile
|
||||
@ -786,11 +796,8 @@ static game_state *execute_move(const game_state *from, const char *move)
|
||||
/*
|
||||
* See if the game has been completed.
|
||||
*/
|
||||
if (!ret->completed) {
|
||||
if (!ret->completed && is_completed(ret->tiles, ret->n)) {
|
||||
ret->completed = ret->movecount;
|
||||
for (p = 0; p < ret->n; p++)
|
||||
if (ret->tiles[p] != (p < ret->n-1 ? p+1 : 0))
|
||||
ret->completed = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
6
flood.c
6
flood.c
@ -552,8 +552,10 @@ static char *new_game_desc(const game_params *params, random_state *rs,
|
||||
/*
|
||||
* Invent a random grid.
|
||||
*/
|
||||
for (i = 0; i < wh; i++)
|
||||
scratch->grid[i] = random_upto(rs, params->colours);
|
||||
do {
|
||||
for (i = 0; i < wh; i++)
|
||||
scratch->grid[i] = random_upto(rs, params->colours);
|
||||
} while (completed(w, h, scratch->grid));
|
||||
|
||||
/*
|
||||
* Run the solver, and count how many moves it uses.
|
||||
|
Reference in New Issue
Block a user