X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/blobdiff_plain/4efb3868c8a828892638f5490ef0402de22f1830..077f3cbef8366f3cd57f07cb3eb5118457ea4f6d:/sixteen.c diff --git a/sixteen.c b/sixteen.c index bc21964..7217d10 100644 --- a/sixteen.c +++ b/sixteen.c @@ -13,6 +13,7 @@ #include "puzzles.h" const char *const game_name = "Sixteen"; +const int game_can_configure = TRUE; #define TILE_SIZE 48 #define BORDER TILE_SIZE /* big border to fill with arrows */ @@ -43,6 +44,8 @@ struct game_state { int w, h, n; int *tiles; int completed; + int movecount; + int last_movement_sense; }; game_params *default_params(void) @@ -89,6 +92,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; @@ -231,7 +279,8 @@ game_state *new_game(game_params *params, char *seed) } assert(!*p); - state->completed = FALSE; + state->completed = state->movecount = 0; + state->last_movement_sense = 0; return state; } @@ -246,6 +295,8 @@ game_state *dup_game(game_state *state) ret->tiles = snewn(state->w * state->h, int); memcpy(ret->tiles, state->tiles, state->w * state->h * sizeof(int)); ret->completed = state->completed; + ret->movecount = state->movecount; + ret->last_movement_sense = state->last_movement_sense; return ret; } @@ -287,11 +338,15 @@ game_state *make_move(game_state *from, int x, int y, int button) ret->tiles[C(ret, cx, cy)] = from->tiles[C(from, tx, ty)]; } while (--n > 0); + ret->movecount++; + + ret->last_movement_sense = -(dx+dy); + /* * See if the game has been completed. */ if (!ret->completed) { - ret->completed = TRUE; + ret->completed = ret->movecount; for (n = 0; n < ret->n; n++) if (ret->tiles[n] != n+1) ret->completed = FALSE; @@ -547,13 +602,15 @@ void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate, y0 = COORD(Y(state, j)); dx = (x1 - x0); - if (abs(dx) > TILE_SIZE) { + if (dx != 0 && + dx != TILE_SIZE * state->last_movement_sense) { dx = (dx < 0 ? dx + TILE_SIZE * state->w : dx - TILE_SIZE * state->w); assert(abs(dx) == TILE_SIZE); } dy = (y1 - y0); - if (abs(dy) > TILE_SIZE) { + if (dy != 0 && + dy != TILE_SIZE * state->last_movement_sense) { dy = (dy < 0 ? dy + TILE_SIZE * state->h : dy - TILE_SIZE * state->h); assert(abs(dy) == TILE_SIZE); @@ -588,6 +645,26 @@ void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate, unclip(fe); 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) @@ -602,3 +679,8 @@ float game_flash_length(game_state *oldstate, game_state *newstate) else return 0.0F; } + +int game_wants_statusbar(void) +{ + return TRUE; +}