* That hook can talk to the game_ui and set the cheated flag,
* and then make_move can avoid setting the `won' flag after that.
*
- * - timer
- *
* - question marks (arrgh, preferences?)
*
* - sensible parameter constraints
#include "puzzles.h"
enum {
- COL_BACKGROUND,
+ COL_BACKGROUND, COL_BACKGROUND2,
COL_1, COL_2, COL_3, COL_4, COL_5, COL_6, COL_7, COL_8,
COL_MINE, COL_BANG, COL_CROSS, COL_FLAG, COL_FLAGBASE, COL_QUERY,
COL_HIGHLIGHT, COL_LOWLIGHT,
struct game_state {
int w, h, n, dead, won;
struct mine_layout *layout; /* real mine positions */
- char *grid; /* player knowledge */
+ signed char *grid; /* player knowledge */
/*
* Each item in the `grid' array is one of the following values:
*
return "Width must be greater than zero";
if (params->h <= 0)
return "Height must be greater than zero";
+ if (params->n > params->w * params->h - 9)
+ return "Too many mines for grid size";
/*
* FIXME: Need more constraints here. Not sure what the
std->next[i] = -1;
}
-static void known_squares(int w, int h, struct squaretodo *std, char *grid,
+static void known_squares(int w, int h, struct squaretodo *std,
+ signed char *grid,
int (*open)(void *ctx, int x, int y), void *openctx,
int x, int y, int mask, int mine)
{
* steps were required; the exact return value is the number of
* perturb calls.
*/
-static int minesolve(int w, int h, int n, char *grid,
+static int minesolve(int w, int h, int n, signed char *grid,
int (*open)(void *ctx, int x, int y),
- struct perturbations *(*perturb)(void *ctx, char *grid,
+ struct perturbations *(*perturb)(void *ctx,
+ signed char *grid,
int x, int y, int mask),
void *ctx, random_state *rs)
{
*/
struct minectx {
- char *grid;
+ signed char *grid;
int w, h;
int sx, sy;
random_state *rs;
return 0;
}
-static struct perturbations *mineperturb(void *vctx, char *grid,
+static struct perturbations *mineperturb(void *vctx, signed char *grid,
int setx, int sety, int mask)
{
struct minectx *ctx = (struct minectx *)vctx;
* We bypass this bit if we're not after a unique grid.
*/
if (unique) {
- char *solvegrid = snewn(w*h, char);
+ signed char *solvegrid = snewn(w*h, char);
struct minectx actx, *ctx = &actx;
int solveret, prevret = -2;
static char *new_mine_layout(int w, int h, int n, int x, int y, int unique,
random_state *rs, char **game_desc)
{
- char *grid, *ret, *p;
+ signed char *grid, *ret, *p;
unsigned char *bmp;
int i, area;
}
static char *new_game_desc(game_params *params, random_state *rs,
- game_aux_info **aux)
+ game_aux_info **aux, int interactive)
{
-#ifdef PREOPENED
- int x = random_upto(rs, params->w);
- int y = random_upto(rs, params->h);
- char *grid, *desc;
+ if (!interactive) {
+ /*
+ * For batch-generated grids, pre-open one square.
+ */
+ int x = random_upto(rs, params->w);
+ int y = random_upto(rs, params->h);
+ signed char *grid;
+ char *desc;
- grid = new_mine_layout(params->w, params->h, params->n,
- x, y, params->unique, rs);
-#else
- char *rsdesc, *desc;
+ grid = new_mine_layout(params->w, params->h, params->n,
+ x, y, params->unique, rs, &desc);
+ sfree(grid);
+ return desc;
+ } else {
+ char *rsdesc, *desc;
- rsdesc = random_state_encode(rs);
- desc = snewn(strlen(rsdesc) + 100, char);
- sprintf(desc, "r%d,%c,%s", params->n, params->unique ? 'u' : 'a', rsdesc);
- sfree(rsdesc);
- return desc;
-#endif
+ rsdesc = random_state_encode(rs);
+ desc = snewn(strlen(rsdesc) + 100, char);
+ sprintf(desc, "r%d,%c,%s", params->n, params->unique ? 'u' : 'a', rsdesc);
+ sfree(rsdesc);
+ return desc;
+ }
}
static void game_free_aux_info(game_aux_info *aux)
state->layout->me = me;
} else {
+ state->layout->rs = NULL;
+ state->layout->me = NULL;
state->layout->mines = snewn(wh, char);
x = atoi(desc);
static char *game_text_format(game_state *state)
{
- return NULL;
+ char *ret;
+ int x, y;
+
+ ret = snewn((state->w + 1) * state->h + 1, char);
+ for (y = 0; y < state->h; y++) {
+ for (x = 0; x < state->w; x++) {
+ int v = state->grid[y*state->w+x];
+ if (v == 0)
+ v = '-';
+ else if (v >= 1 && v <= 8)
+ v = '0' + v;
+ else if (v == -1)
+ v = '*';
+ else if (v == -2 || v == -3)
+ v = '?';
+ else if (v >= 64)
+ v = '!';
+ ret[y * (state->w+1) + x] = v;
+ }
+ ret[y * (state->w+1) + state->w] = '\n';
+ }
+ ret[(state->w + 1) * state->h] = '\0';
+
+ return ret;
}
struct game_ui {
struct game_drawstate {
int w, h, started;
- char *grid;
+ signed char *grid;
/*
* Items in this `grid' array have all the same values as in
* the game_state grid, and in addition:
frontend_default_colour(fe, &ret[COL_BACKGROUND * 3]);
+ ret[COL_BACKGROUND2 * 3 + 0] = ret[COL_BACKGROUND * 3 + 0] * 19.0 / 20.0;
+ ret[COL_BACKGROUND2 * 3 + 1] = ret[COL_BACKGROUND * 3 + 1] * 19.0 / 20.0;
+ ret[COL_BACKGROUND2 * 3 + 2] = ret[COL_BACKGROUND * 3 + 2] * 19.0 / 20.0;
+
ret[COL_1 * 3 + 0] = 0.0F;
ret[COL_1 * 3 + 1] = 0.0F;
ret[COL_1 * 3 + 2] = 1.0F;
/*
* Omit the highlights in this case.
*/
- draw_rect(fe, x, y, TILE_SIZE, TILE_SIZE, bg);
+ draw_rect(fe, x, y, TILE_SIZE, TILE_SIZE,
+ bg == COL_BACKGROUND ? COL_BACKGROUND2 : bg);
draw_line(fe, x, y, x + TILE_SIZE - 1, y, COL_LOWLIGHT);
draw_line(fe, x, y, x, y + TILE_SIZE - 1, COL_LOWLIGHT);
} else {
* on), we clear the square to COL_BANG.
*/
draw_rect(fe, x, y, TILE_SIZE, TILE_SIZE,
- (v == 65 ? COL_BANG : bg));
+ (v == 65 ? COL_BANG :
+ bg == COL_BACKGROUND ? COL_BACKGROUND2 : bg));
draw_line(fe, x, y, x + TILE_SIZE - 1, y, COL_LOWLIGHT);
draw_line(fe, x, y, x, y + TILE_SIZE - 1, COL_LOWLIGHT);
return TRUE;
}
+static int game_timing_state(game_state *state)
+{
+ if (state->dead || state->won || !state->layout->mines)
+ return FALSE;
+ return TRUE;
+}
+
#ifdef COMBINED
#define thegame mines
#endif
dup_game,
free_game,
FALSE, solve_game,
- FALSE, game_text_format,
+ TRUE, game_text_format,
new_ui,
free_ui,
make_move,
game_anim_length,
game_flash_length,
game_wants_statusbar,
+ TRUE, game_timing_state,
};