game_params *ret = snew(game_params);
ret->w = 10;
+#ifdef PORTRAIT_SCREEN
+ ret->h = 10;
+#else
ret->h = 8;
-
+#endif
return ret;
}
}
static const struct game_params inertia_presets[] = {
+#ifdef PORTRAIT_SCREEN
+ { 10, 10 },
+ { 12, 12 },
+ { 16, 16 },
+#else
{ 10, 8 },
{ 15, 12 },
{ 20, 16 },
+#endif
};
static int game_fetch_preset(int i, char **name, game_params **params)
char *err, *soln, *p;
/*
+ * Before anything else, deal with the special case in which
+ * all the gems are already collected.
+ */
+ for (i = 0; i < wh; i++)
+ if (currstate->grid[i] == GEM)
+ break;
+ if (i == wh) {
+ *error = "Game is already solved";
+ return NULL;
+ }
+
+ /*
* Solving Inertia is a question of first building up the graph
* of where you can get to from where, and secondly finding a
* tour of the graph which takes in every gem.
*/
while (1) {
int oldlen = circuitlen;
+ int dir;
- for (i = 0; i < wh; i++)
- unvisited[i] = 0;
- for (i = 0; i < circuitlen; i++) {
- int xy = nodes[circuit[i]] / DP1;
- if (currstate->grid[xy] == GEM)
- unvisited[xy]++;
- }
+ for (dir = +1; dir >= -1; dir -= 2) {
- /*
- * If there's any gem we didn't end up visiting at all,
- * give up.
- */
- for (i = 0; i < wh; i++) {
- if (currstate->grid[i] == GEM && unvisited[i] == 0) {
- err = "Unable to find a solution from this starting point";
- break;
+ for (i = 0; i < wh; i++)
+ unvisited[i] = 0;
+ for (i = 0; i < circuitlen; i++) {
+ int xy = nodes[circuit[i]] / DP1;
+ if (currstate->grid[xy] == GEM)
+ unvisited[xy]++;
}
- }
- if (i < wh)
- break;
- for (i = j = 0; i < circuitlen; i++) {
- int xy = nodes[circuit[i]] / DP1;
- if (currstate->grid[xy] == GEM && unvisited[xy] > 1) {
- unvisited[xy]--;
- } else if (currstate->grid[xy] == GEM || i == circuitlen-1) {
- /*
- * circuit[i] collects a gem for the only time, or is
- * the last node in the circuit. Therefore it cannot be
- * removed; so we now want to replace the path from
- * circuit[j] to circuit[i] with a bfs-shortest path.
- */
- int k, dest, ni, ti, thisdist;
+ /*
+ * If there's any gem we didn't end up visiting at all,
+ * give up.
+ */
+ for (i = 0; i < wh; i++) {
+ if (currstate->grid[i] == GEM && unvisited[i] == 0) {
+ err = "Unable to find a solution from this starting point";
+ break;
+ }
+ }
+ if (i < wh)
+ break;
+
+ for (i = j = (dir > 0 ? 0 : circuitlen-1);
+ i < circuitlen && i >= 0;
+ i += dir) {
+ int xy = nodes[circuit[i]] / DP1;
+ if (currstate->grid[xy] == GEM && unvisited[xy] > 1) {
+ unvisited[xy]--;
+ } else if (currstate->grid[xy] == GEM || i == circuitlen-1) {
+ /*
+ * circuit[i] collects a gem for the only time,
+ * or is the last node in the circuit.
+ * Therefore it cannot be removed; so we now
+ * want to replace the path from circuit[j] to
+ * circuit[i] with a bfs-shortest path.
+ */
+ int p, q, k, dest, ni, ti, thisdist;
+
+ /*
+ * Set up the upper and lower bounds of the
+ * reduced section.
+ */
+ p = min(i, j);
+ q = max(i, j);
#ifdef TSP_DIAGNOSTICS
- printf("optimising section from %d - %d\n", j, i);
+ printf("optimising section from %d - %d\n", p, q);
#endif
- for (k = 0; k < n; k++)
- dist[k] = -1;
- head = tail = 0;
-
- dist[circuit[j]] = 0;
- list[tail++] = circuit[j];
-
- while (head < tail && dist[circuit[i]] < 0) {
- int ni = list[head++];
- for (k = edgei[ni]; k < edgei[ni+1]; k++) {
- int ti = edges[k];
- if (ti >= 0 && dist[ti] < 0) {
- dist[ti] = dist[ni] + 1;
- list[tail++] = ti;
+ for (k = 0; k < n; k++)
+ dist[k] = -1;
+ head = tail = 0;
+
+ dist[circuit[p]] = 0;
+ list[tail++] = circuit[p];
+
+ while (head < tail && dist[circuit[q]] < 0) {
+ int ni = list[head++];
+ for (k = edgei[ni]; k < edgei[ni+1]; k++) {
+ int ti = edges[k];
+ if (ti >= 0 && dist[ti] < 0) {
+ dist[ti] = dist[ni] + 1;
+ list[tail++] = ti;
+ }
}
}
- }
- thisdist = dist[circuit[i]];
- assert(thisdist >= 0 && thisdist <= i-j);
+ thisdist = dist[circuit[q]];
+ assert(thisdist >= 0 && thisdist <= q-p);
- memmove(circuit+j+thisdist, circuit+i,
- (circuitlen - i) * sizeof(int));
- circuitlen -= i-j;
- i = j + thisdist;
- circuitlen += i-j;
+ memmove(circuit+p+thisdist, circuit+q,
+ (circuitlen - q) * sizeof(int));
+ circuitlen -= q-p;
+ q = p + thisdist;
+ circuitlen += q-p;
+
+ if (dir > 0)
+ i = q; /* resume loop from the right place */
#ifdef TSP_DIAGNOSTICS
- printf("new section runs from %d - %d\n", j, i);
+ printf("new section runs from %d - %d\n", p, q);
#endif
- dest = i;
- assert(dest >= 0);
- ni = circuit[i];
+ dest = q;
+ assert(dest >= 0);
+ ni = circuit[q];
- while (1) {
- /* printf("dest=%d circuitlen=%d ni=%d dist[ni]=%d\n", dest, circuitlen, ni, dist[ni]); */
- circuit[dest] = ni;
- if (dist[ni] == 0)
- break;
- dest--;
- ti = -1;
- for (k = backedgei[ni]; k < backedgei[ni+1]; k++) {
- ti = backedges[k];
- if (ti >= 0 && dist[ti] == dist[ni] - 1)
+ while (1) {
+ /* printf("dest=%d circuitlen=%d ni=%d dist[ni]=%d\n", dest, circuitlen, ni, dist[ni]); */
+ circuit[dest] = ni;
+ if (dist[ni] == 0)
break;
+ dest--;
+ ti = -1;
+ for (k = backedgei[ni]; k < backedgei[ni+1]; k++) {
+ ti = backedges[k];
+ if (ti >= 0 && dist[ti] == dist[ni] - 1)
+ break;
+ }
+ assert(k < backedgei[ni+1] && ti >= 0);
+ ni = ti;
}
- assert(k < backedgei[ni+1] && ti >= 0);
- ni = ti;
- }
- /*
- * Now re-increment the visit counts for the new
- * path.
- */
- while (++j < i) {
- int xy = nodes[circuit[j]] / DP1;
- if (currstate->grid[xy] == GEM)
- unvisited[xy]++;
- }
+ /*
+ * Now re-increment the visit counts for the
+ * new path.
+ */
+ while (++p < q) {
+ int xy = nodes[circuit[p]] / DP1;
+ if (currstate->grid[xy] == GEM)
+ unvisited[xy]++;
+ }
+
+ j = i;
#ifdef TSP_DIAGNOSTICS
- printf("during reduction, circuit is");
- for (k = 0; k < circuitlen; k++) {
- int nc = nodes[circuit[k]];
- printf(" (%d,%d,%d)", nc/DP1%w, nc/(DP1*w), nc%DP1);
- }
- printf("\n");
- printf("moves are ");
- x = nodes[circuit[0]] / DP1 % w;
- y = nodes[circuit[0]] / DP1 / w;
- for (k = 1; k < circuitlen; k++) {
- int x2, y2, dx, dy;
- if (nodes[circuit[k]] % DP1 != DIRECTIONS)
- continue;
- x2 = nodes[circuit[k]] / DP1 % w;
- y2 = nodes[circuit[k]] / DP1 / w;
- dx = (x2 > x ? +1 : x2 < x ? -1 : 0);
- dy = (y2 > y ? +1 : y2 < y ? -1 : 0);
- for (d = 0; d < DIRECTIONS; d++)
- if (DX(d) == dx && DY(d) == dy)
- printf("%c", "89632147"[d]);
- x = x2;
- y = y2;
- }
- printf("\n");
+ printf("during reduction, circuit is");
+ for (k = 0; k < circuitlen; k++) {
+ int nc = nodes[circuit[k]];
+ printf(" (%d,%d,%d)", nc/DP1%w, nc/(DP1*w), nc%DP1);
+ }
+ printf("\n");
+ printf("moves are ");
+ x = nodes[circuit[0]] / DP1 % w;
+ y = nodes[circuit[0]] / DP1 / w;
+ for (k = 1; k < circuitlen; k++) {
+ int x2, y2, dx, dy;
+ if (nodes[circuit[k]] % DP1 != DIRECTIONS)
+ continue;
+ x2 = nodes[circuit[k]] / DP1 % w;
+ y2 = nodes[circuit[k]] / DP1 / w;
+ dx = (x2 > x ? +1 : x2 < x ? -1 : 0);
+ dy = (y2 > y ? +1 : y2 < y ? -1 : 0);
+ for (d = 0; d < DIRECTIONS; d++)
+ if (DX(d) == dx && DY(d) == dy)
+ printf("%c", "89632147"[d]);
+ x = x2;
+ y = y2;
+ }
+ printf("\n");
#endif
+ }
}
- }
#ifdef TSP_DIAGNOSTICS
- printf("after reduction, moves are ");
- x = nodes[circuit[0]] / DP1 % w;
- y = nodes[circuit[0]] / DP1 / w;
- for (i = 1; i < circuitlen; i++) {
- int x2, y2, dx, dy;
- if (nodes[circuit[i]] % DP1 != DIRECTIONS)
- continue;
- x2 = nodes[circuit[i]] / DP1 % w;
- y2 = nodes[circuit[i]] / DP1 / w;
- dx = (x2 > x ? +1 : x2 < x ? -1 : 0);
- dy = (y2 > y ? +1 : y2 < y ? -1 : 0);
- for (d = 0; d < DIRECTIONS; d++)
- if (DX(d) == dx && DY(d) == dy)
- printf("%c", "89632147"[d]);
- x = x2;
- y = y2;
- }
- printf("\n");
+ printf("after reduction, moves are ");
+ x = nodes[circuit[0]] / DP1 % w;
+ y = nodes[circuit[0]] / DP1 / w;
+ for (i = 1; i < circuitlen; i++) {
+ int x2, y2, dx, dy;
+ if (nodes[circuit[i]] % DP1 != DIRECTIONS)
+ continue;
+ x2 = nodes[circuit[i]] / DP1 % w;
+ y2 = nodes[circuit[i]] / DP1 / w;
+ dx = (x2 > x ? +1 : x2 < x ? -1 : 0);
+ dy = (y2 > y ? +1 : y2 < y ? -1 : 0);
+ for (d = 0; d < DIRECTIONS; d++)
+ if (DX(d) == dx && DY(d) == dy)
+ printf("%c", "89632147"[d]);
+ x = x2;
+ y = y2;
+ }
+ printf("\n");
#endif
+ }
/*
- * If we've managed an entire reduction pass and not made
- * the solution any shorter, we're _really_ done.
+ * If we've managed an entire reduction pass in each
+ * direction and not made the solution any shorter, we're
+ * _really_ done.
*/
if (circuitlen == oldlen)
break;
return soln;
}
+static int game_can_format_as_text_now(game_params *params)
+{
+ return TRUE;
+}
+
static char *game_text_format(game_state *state)
{
return NULL;
#define PREFERRED_TILESIZE 32
#define TILESIZE (ds->tilesize)
+#ifdef SMALL_SCREEN
+#define BORDER (TILESIZE / 4)
+#else
#define BORDER (TILESIZE)
+#endif
#define HIGHLIGHT_WIDTH (TILESIZE / 10)
#define COORD(x) ( (x) * TILESIZE + BORDER )
#define FROMCOORD(x) ( ((x) - BORDER + TILESIZE) / TILESIZE - 1 )
dir = 1;
else if (button == (MOD_NUM_KEYPAD | '3'))
dir = 3;
- else if (button == ' ' && state->soln && state->solnpos < state->soln->len)
+ else if (IS_CURSOR_SELECT(button) &&
+ state->soln && state->solnpos < state->soln->len)
dir = state->soln->list[state->solnpos];
if (dir < 0)
sol->list[i] = move[i] - '0';
ret = dup_game(state);
ret->cheated = TRUE;
+ if (ret->soln && --ret->soln->refcount == 0) {
+ sfree(ret->soln->list);
+ sfree(ret->soln);
+ }
ret->soln = sol;
ret->solnpos = 0;
sol->refcount = 1;
ds->player_background = blitter_new(dr, TILESIZE, TILESIZE);
}
-static float *game_colours(frontend *fe, game_state *state, int *ncolours)
+static float *game_colours(frontend *fe, int *ncolours)
{
float *ret = snewn(3 * NCOLOURS, float);
int i;
int coords[8];
coords[0] = tx+TILESIZE/2;
- coords[1] = ty+TILESIZE*1/7;
- coords[2] = tx+TILESIZE*1/7;
+ coords[1] = ty+TILESIZE/2-TILESIZE*5/14;
+ coords[2] = tx+TILESIZE/2-TILESIZE*5/14;
coords[3] = ty+TILESIZE/2;
coords[4] = tx+TILESIZE/2;
- coords[5] = ty+TILESIZE-TILESIZE*1/7;
- coords[6] = tx+TILESIZE-TILESIZE*1/7;
+ coords[5] = ty+TILESIZE/2+TILESIZE*5/14;
+ coords[6] = tx+TILESIZE/2+TILESIZE*5/14;
coords[7] = ty+TILESIZE/2;
draw_polygon(dr, coords, 4, COL_GEM, COL_OUTLINE);
return 0.0F;
}
-static int game_wants_statusbar(void)
-{
- return TRUE;
-}
-
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
#endif
const struct game thegame = {
- "Inertia", "games.inertia",
+ "Inertia", "games.inertia", "inertia",
default_params,
game_fetch_preset,
decode_params,
dup_game,
free_game,
TRUE, solve_game,
- FALSE, game_text_format,
+ FALSE, game_can_format_as_text_now, game_text_format,
new_ui,
free_ui,
encode_ui,
game_anim_length,
game_flash_length,
FALSE, FALSE, game_print_size, game_print,
- game_wants_statusbar,
+ TRUE, /* wants_statusbar */
FALSE, game_timing_state,
- 0, /* mouse_priorities */
+ 0, /* flags */
};