X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/blobdiff_plain/4efb3868c8a828892638f5490ef0402de22f1830..d3a026ed4258c207b6309802cc2c92eb0a812aac:/fifteen.c diff --git a/fifteen.c b/fifteen.c index 9357d65..04a8f75 100644 --- a/fifteen.c +++ b/fifteen.c @@ -11,6 +11,7 @@ #include "puzzles.h" const char *const game_name = "Fifteen"; +const int game_can_configure = TRUE; #define TILE_SIZE 48 #define BORDER (TILE_SIZE / 2) @@ -42,6 +43,7 @@ struct game_state { int *tiles; int gap_pos; int completed; + int movecount; }; game_params *default_params(void) @@ -70,6 +72,51 @@ game_params *dup_params(game_params *params) return ret; } +config_item *game_configure(game_params *params) +{ + config_item *ret; + char buf[80]; + + ret = snewn(3, config_item); + + ret[0].name = "Width"; + ret[0].type = C_STRING; + sprintf(buf, "%d", params->w); + ret[0].sval = dupstr(buf); + ret[0].ival = 0; + + ret[1].name = "Height"; + ret[1].type = C_STRING; + sprintf(buf, "%d", params->h); + ret[1].sval = dupstr(buf); + ret[1].ival = 0; + + ret[2].name = NULL; + ret[2].type = C_END; + ret[2].sval = NULL; + ret[2].ival = 0; + + return ret; +} + +game_params *custom_params(config_item *cfg) +{ + game_params *ret = snew(game_params); + + ret->w = atoi(cfg[0].sval); + ret->h = atoi(cfg[1].sval); + + return ret; +} + +char *validate_params(game_params *params) +{ + if (params->w < 2 && params->h < 2) + return "Width and height must both be at least two"; + + return NULL; +} + int perm_parity(int *perm, int n) { int i, j, ret; @@ -152,15 +199,16 @@ char *new_game_seed(game_params *params) * 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, and therefore also the top left, count as - * even. + * - 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 = (X(params, gap) ^ Y(params, gap) ^ (n+1)) & 1; + parity = ((X(params, gap) - (params->w-1)) ^ + (Y(params, gap) - (params->h-1)) ^ + (n+1)) & 1; /* * Try the last two tiles one way round. If that fails, swap @@ -224,7 +272,7 @@ game_state *new_game(game_params *params, char *seed) assert(!*p); assert(state->tiles[state->gap_pos] == 0); - state->completed = FALSE; + state->completed = state->movecount = 0; return state; } @@ -240,6 +288,7 @@ game_state *dup_game(game_state *state) memcpy(ret->tiles, state->tiles, state->w * state->h * sizeof(int)); ret->gap_pos = state->gap_pos; ret->completed = state->completed; + ret->movecount = state->movecount; return ret; } @@ -297,16 +346,17 @@ game_state *make_move(game_state *from, int x, int y, int button) for (p = from->gap_pos; p != ret->gap_pos; p += up) { assert(p >= 0 && p < from->n); ret->tiles[p] = from->tiles[p + up]; + ret->movecount++; } /* * See if the game has been completed. */ if (!ret->completed) { - ret->completed = TRUE; + ret->completed = ret->movecount; for (p = 0; p < ret->n; p++) if (ret->tiles[p] != (p < ret->n-1 ? p+1 : 0)) - ret->completed = FALSE; + ret->completed = 0; } return ret; @@ -544,6 +594,26 @@ void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate, } } ds->bgcolour = bgcolour; + + /* + * Update the status bar. + */ + { + char statusbuf[256]; + + /* + * Don't show the new status until we're also showing the + * new _state_ - after the game animation is complete. + */ + if (oldstate) + state = oldstate; + + sprintf(statusbuf, "%sMoves: %d", + (state->completed ? "COMPLETED! " : ""), + (state->completed ? state->completed : state->movecount)); + + status_bar(fe, statusbuf); + } } float game_anim_length(game_state *oldstate, game_state *newstate) @@ -558,3 +628,8 @@ float game_flash_length(game_state *oldstate, game_state *newstate) else return 0.0F; } + +int game_wants_statusbar(void) +{ + return TRUE; +}