X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=undead.c;h=b1f536e8d0233183a3d0ecf553999038670bf120;hb=db313b3948d27244dd7c34c2609c66d6204d8931;hp=d7d5b095fcaeec6c7bd44b7f8d80d3e92b73e4b3;hpb=c3285318e60cb78d190725aba3675325921afdb3;p=sgt-puzzles.git diff --git a/undead.c b/undead.c index d7d5b09..b1f536e 100644 --- a/undead.c +++ b/undead.c @@ -49,6 +49,7 @@ enum { COL_GHOST, COL_ZOMBIE, COL_VAMPIRE, + COL_DONE, NCOLOURS }; @@ -237,6 +238,7 @@ struct game_state { unsigned char *pencils; unsigned char *cell_errors; unsigned char *hint_errors; + unsigned char *hints_done; unsigned char count_errors[3]; int solved; int cheated; @@ -289,6 +291,9 @@ static game_state *new_state(const game_params *params) { state->hint_errors = snewn(2*state->common->num_paths, unsigned char); for (i=0;i<2*state->common->num_paths;i++) state->hint_errors[i] = FALSE; + state->hints_done = snewn(2 * state->common->num_paths, unsigned char); + memset(state->hints_done, 0, + 2 * state->common->num_paths * sizeof(unsigned char)); for (i=0;i<3;i++) state->count_errors[i] = FALSE; @@ -332,6 +337,13 @@ static game_state *dup_game(const game_state *state) } else ret->hint_errors = NULL; + if (state->hints_done != NULL) { + ret->hints_done = snewn(2 * state->common->num_paths, unsigned char); + memcpy(ret->hints_done, state->hints_done, + 2 * state->common->num_paths * sizeof(unsigned char)); + } + else ret->hints_done = NULL; + ret->count_errors[0] = state->count_errors[0]; ret->count_errors[1] = state->count_errors[1]; ret->count_errors[2] = state->count_errors[2]; @@ -358,6 +370,7 @@ static void free_game(game_state *state) { if (state->common->fixed != NULL) sfree(state->common->fixed); sfree(state->common); } + if (state->hints_done != NULL) sfree(state->hints_done); if (state->hint_errors != NULL) sfree(state->hint_errors); if (state->cell_errors != NULL) sfree(state->cell_errors); if (state->pencils != NULL) sfree(state->pencils); @@ -1662,12 +1675,40 @@ struct game_drawstate { unsigned char count_errors[3]; unsigned char *cell_errors; unsigned char *hint_errors; + unsigned char *hints_done; int hx, hy, hshow, hpencil; /* as for game_ui. */ int hflash; int ascii; }; +static int is_clue(const game_state *state, int x, int y) +{ + int h = state->common->params.h, w = state->common->params.w; + + if (((x == 0 || x == w + 1) && y > 0 && y <= h) || + ((y == 0 || y == h + 1) && x > 0 && x <= w)) + return TRUE; + + return FALSE; +} + +static int clue_index(const game_state *state, int x, int y) +{ + int h = state->common->params.h, w = state->common->params.w; + + if (y == 0) + return x - 1; + else if (x == w + 1) + return w + y - 1; + else if (y == h + 1) + return 2 * w + h - x; + else if (x == 0) + return 2 * (w + h) - y; + + return -1; +} + #define TILESIZE (ds->tilesize) #define BORDER (TILESIZE/4) @@ -1686,6 +1727,10 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->ascii = !ui->ascii; return ""; } + + if (button == 'm' || button == 'M') { + return dupstr("M"); + } if (ui->hshow == 1 && ui->hpencil == 0) { xi = state->common->xinfo[ui->hx + ui->hy*(state->common->params.w+2)]; @@ -1818,6 +1863,11 @@ static char *interpret_move(const game_state *state, game_ui *ui, } } } + } else if (button == LEFT_BUTTON) { + if (is_clue(state, gx, gy)) { + sprintf(buf, "D%d,%d", gx, gy); + return dupstr(buf); + } } return NULL; @@ -1905,7 +1955,9 @@ int check_path_solution(game_state *state, int p) { } } - if (unfilled == 0 && count != state->common->paths[p].sightings_start) { + if (count > state->common->paths[p].sightings_start || + count + unfilled < state->common->paths[p].sightings_start) + { correct = FALSE; state->hint_errors[state->common->paths[p].grid_start] = TRUE; } @@ -1927,7 +1979,9 @@ int check_path_solution(game_state *state, int p) { } } - if (unfilled == 0 && count != state->common->paths[p].sightings_end) { + if (count > state->common->paths[p].sightings_end || + count + unfilled < state->common->paths[p].sightings_end) + { correct = FALSE; state->hint_errors[state->common->paths[p].grid_end] = TRUE; } @@ -1942,7 +1996,7 @@ int check_path_solution(game_state *state, int p) { static game_state *execute_move(const game_state *state, const char *move) { - int x,n,p,i; + int x,y,n,p,i; char c; int correct; int solver; @@ -1969,6 +2023,23 @@ static game_state *execute_move(const game_state *state, const char *move) if (c == 'z') ret->pencils[x] ^= 4; move += n; } + if (c == 'D' && sscanf(move + 1, "%d,%d%n", &x, &y, &n) == 2 && + is_clue(ret, x, y)) { + ret->hints_done[clue_index(ret, x, y)] ^= 1; + move += n + 1; + } + if (c == 'M') { + /* + * Fill in absolutely all pencil marks in unfilled + * squares, for those who like to play by the rigorous + * approach of starting off in that state and eliminating + * things. + */ + for (i = 0; i < ret->common->wh; i++) + if (ret->guess[i] == 7) + ret->pencils[i] = 7; + move++; + } if (*move == ';') move++; } @@ -2058,6 +2129,10 @@ static float *game_colours(frontend *fe, int *ncolours) ret[COL_VAMPIRE * 3 + 1] = ret[COL_BACKGROUND * 3 + 0] * 0.9F; ret[COL_VAMPIRE * 3 + 2] = ret[COL_BACKGROUND * 3 + 0] * 0.9F; + ret[COL_DONE * 3 + 0] = ret[COL_BACKGROUND * 3 + 0] / 1.5F; + ret[COL_DONE * 3 + 1] = ret[COL_BACKGROUND * 3 + 1] / 1.5F; + ret[COL_DONE * 3 + 2] = ret[COL_BACKGROUND * 3 + 2] / 1.5F; + *ncolours = NCOLOURS; return ret; } @@ -2090,6 +2165,9 @@ static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state) ds->hint_errors = snewn(2*state->common->num_paths,unsigned char); for (i=0;i<2*state->common->num_paths;i++) ds->hint_errors[i] = FALSE; + ds->hints_done = snewn(2 * state->common->num_paths, unsigned char); + memset(ds->hints_done, 0, + 2 * state->common->num_paths * sizeof(unsigned char)); ds->hshow = ds->hpencil = ds->hflash = 0; ds->hx = ds->hy = 0; @@ -2097,6 +2175,7 @@ static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state) } static void game_free_drawstate(drawing *dr, game_drawstate *ds) { + sfree(ds->hints_done); sfree(ds->hint_errors); sfree(ds->cell_errors); sfree(ds->pencils); @@ -2325,6 +2404,8 @@ static void draw_path_hint(drawing *dr, game_drawstate *ds, color = COL_ERROR; else if (hflash) color = COL_FLASH; + else if (ds->hints_done[hint_index]) + color = COL_DONE; else color = COL_TEXT; @@ -2445,15 +2526,21 @@ static void draw_pencils(drawing *dr, game_drawstate *ds, static int is_hint_stale(const game_drawstate *ds, int hflash, const game_state *state, int index) { - if (!ds->started) return TRUE; - if (ds->hflash != hflash) return TRUE; + int ret = FALSE; + if (!ds->started) ret = TRUE; + if (ds->hflash != hflash) ret = TRUE; if (ds->hint_errors[index] != state->hint_errors[index]) { ds->hint_errors[index] = state->hint_errors[index]; - return TRUE; + ret = TRUE; } - return FALSE; + if (ds->hints_done[index] != state->hints_done[index]) { + ds->hints_done[index] = state->hints_done[index]; + ret = TRUE; + } + + return ret; } static void game_redraw(drawing *dr, game_drawstate *ds, @@ -2615,7 +2702,7 @@ static void game_print(drawing *dr, const game_state *state, int tilesize) const struct game thegame = { "Undead", "games.undead", "undead", default_params, - game_fetch_preset, + game_fetch_preset, NULL, decode_params, encode_params, free_params,