mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 16:05:44 -07:00
Slight solver speedup by tracking more carefully which block merges
we've already tried, and not trying them again. [originally from svn r7553]
This commit is contained in:
@ -17,11 +17,31 @@
|
|||||||
* cases.
|
* cases.
|
||||||
*
|
*
|
||||||
* - Improve the generator.
|
* - Improve the generator.
|
||||||
|
* * actually, we seem to be mostly sensible already now. I
|
||||||
|
* want more choice over the type of main block and location
|
||||||
|
* of the exit/target, and I think I probably ought to give
|
||||||
|
* up on compactness and just bite the bullet and have the
|
||||||
|
* target area right outside the main wall, but mostly I
|
||||||
|
* think it's OK.
|
||||||
|
* * but adjust the presets, because 8x6 is _slow_ to
|
||||||
|
* generate.
|
||||||
|
* * also, introduce a difficulty scheme, in the form of
|
||||||
|
* limiting the minimum move count. This is obviously
|
||||||
|
* sensible, because it also speeds up generation since the
|
||||||
|
* solver can bomb out once it hits that ceiling!
|
||||||
|
* + I was going to say I'd need to work out a minimum move
|
||||||
|
* count for each grid size, but actually I think not: if
|
||||||
|
* you ask for too few moves, it just has to remove still
|
||||||
|
* more singletons, until at move count 1 you end up with
|
||||||
|
* nothing in your way at all and it SERVES YOU RIGHT!
|
||||||
*
|
*
|
||||||
* - All the colours are a bit wishy-washy. _Some_ dark colours
|
* - Improve the graphics.
|
||||||
* would surely not be excessive? Probably darken the tiles,
|
* * All the colours are a bit wishy-washy. _Some_ dark
|
||||||
* the walls and the main block, and leave the target marker
|
* colours would surely not be excessive? Probably darken
|
||||||
* pale.
|
* the tiles, the walls and the main block, and leave the
|
||||||
|
* target marker pale.
|
||||||
|
* * The cattle grid effect is still disgusting. Think of
|
||||||
|
* something completely different.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -556,6 +576,8 @@ static void generate_board(int w, int h, int *rtx, int *rty, int *minmoves,
|
|||||||
{
|
{
|
||||||
int wh = w*h;
|
int wh = w*h;
|
||||||
unsigned char *board, *board2, *forcefield;
|
unsigned char *board, *board2, *forcefield;
|
||||||
|
unsigned char *tried_merge;
|
||||||
|
int *dsf;
|
||||||
int *list, nlist, pos;
|
int *list, nlist, pos;
|
||||||
int tx, ty;
|
int tx, ty;
|
||||||
int i, j;
|
int i, j;
|
||||||
@ -575,6 +597,10 @@ static void generate_board(int w, int h, int *rtx, int *rty, int *minmoves,
|
|||||||
for (i = 0; i < h; i++)
|
for (i = 0; i < h; i++)
|
||||||
board[i*w] = board[i*w+(w-1)] = WALL;
|
board[i*w] = board[i*w+(w-1)] = WALL;
|
||||||
|
|
||||||
|
tried_merge = snewn(wh * wh, unsigned char);
|
||||||
|
memset(tried_merge, 0, wh*wh);
|
||||||
|
dsf = snew_dsf(wh);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Invent a main piece at one extreme. (FIXME: vary the
|
* Invent a main piece at one extreme. (FIXME: vary the
|
||||||
* extreme, and the piece.)
|
* extreme, and the piece.)
|
||||||
@ -628,19 +654,11 @@ static void generate_board(int w, int h, int *rtx, int *rty, int *minmoves,
|
|||||||
/*
|
/*
|
||||||
* Now go through that list in random order, trying to merge
|
* Now go through that list in random order, trying to merge
|
||||||
* the blocks on each side of each edge.
|
* the blocks on each side of each edge.
|
||||||
*
|
|
||||||
* FIXME: this seems to produce unpleasantly unbalanced
|
|
||||||
* results. Perhaps we'd do better if we always tried to
|
|
||||||
* combine the _smallest_ block with something?
|
|
||||||
*
|
|
||||||
* FIXME: also one reason it's slow might be because we aren't
|
|
||||||
* tracking which blocks we've already tried to merge, when
|
|
||||||
* another edge ends up linking the same ones.
|
|
||||||
*/
|
*/
|
||||||
shuffle(list, nlist, sizeof(*list), rs);
|
shuffle(list, nlist, sizeof(*list), rs);
|
||||||
while (nlist > 0) {
|
while (nlist > 0) {
|
||||||
int x1, y1, p1;
|
int x1, y1, p1, c1;
|
||||||
int x2, y2, p2;
|
int x2, y2, p2, c2;
|
||||||
|
|
||||||
pos = list[--nlist];
|
pos = list[--nlist];
|
||||||
y1 = y2 = pos / (w*2);
|
y1 = y2 = pos / (w*2);
|
||||||
@ -652,6 +670,18 @@ static void generate_board(int w, int h, int *rtx, int *rty, int *minmoves,
|
|||||||
p1 = y1*w+x1;
|
p1 = y1*w+x1;
|
||||||
p2 = y2*w+x2;
|
p2 = y2*w+x2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Immediately abandon the attempt if we've already tried
|
||||||
|
* to merge the same pair of blocks along a different
|
||||||
|
* edge.
|
||||||
|
*/
|
||||||
|
c1 = dsf_canonify(dsf, p1);
|
||||||
|
c2 = dsf_canonify(dsf, p2);
|
||||||
|
if (tried_merge[c1 * wh + c2])
|
||||||
|
{printf("aha\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In order to be mergeable, these two squares must each
|
* In order to be mergeable, these two squares must each
|
||||||
* either be, or belong to, a non-main anchor, and their
|
* either be, or belong to, a non-main anchor, and their
|
||||||
@ -706,8 +736,20 @@ static void generate_board(int w, int h, int *rtx, int *rty, int *minmoves,
|
|||||||
* Didn't work. Revert the merge.
|
* Didn't work. Revert the merge.
|
||||||
*/
|
*/
|
||||||
memcpy(board, board2, wh);
|
memcpy(board, board2, wh);
|
||||||
|
tried_merge[c1 * wh + c2] = tried_merge[c2 * wh + c1] = TRUE;
|
||||||
} else {
|
} else {
|
||||||
|
int c;
|
||||||
|
|
||||||
moves = j;
|
moves = j;
|
||||||
|
|
||||||
|
dsf_merge(dsf, c1, c2);
|
||||||
|
c = dsf_canonify(dsf, c1);
|
||||||
|
for (i = 0; i < wh; i++)
|
||||||
|
tried_merge[c*wh+i] = (tried_merge[c1*wh+i] |
|
||||||
|
tried_merge[c2*wh+i]);
|
||||||
|
for (i = 0; i < wh; i++)
|
||||||
|
tried_merge[i*wh+c] = (tried_merge[i*wh+c1] |
|
||||||
|
tried_merge[i*wh+c2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1835,7 +1877,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
|
|||||||
sprintf(statusbuf, "%sMoves: %d",
|
sprintf(statusbuf, "%sMoves: %d",
|
||||||
(state->completed >= 0 ? "COMPLETED! " : ""),
|
(state->completed >= 0 ? "COMPLETED! " : ""),
|
||||||
(state->completed >= 0 ? state->completed : state->movecount));
|
(state->completed >= 0 ? state->completed : state->movecount));
|
||||||
if (state->minmoves)
|
if (state->minmoves >= 0)
|
||||||
sprintf(statusbuf+strlen(statusbuf), " (min %d)",
|
sprintf(statusbuf+strlen(statusbuf), " (min %d)",
|
||||||
state->minmoves);
|
state->minmoves);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user