X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/blobdiff_plain/a9af91d0a74a53c3a4d1f2da740193ac4a374983..43a45950e9335d1b19245f2d302ec86fd4643bc5:/towers.c diff --git a/towers.c b/towers.c index 468fe84..be0a730 100644 --- a/towers.c +++ b/towers.c @@ -1148,6 +1148,10 @@ static void game_changed_state(game_ui *ui, game_state *oldstate, #define COORD(x) ((x)*TILESIZE + BORDER) #define FROMCOORD(x) (((x)+(TILESIZE-BORDER)) / TILESIZE - 1) +/* These always return positive values, though y offsets are actually -ve */ +#define X_3D_DISP(height, w) ((height) * TILESIZE / (8 * (w))) +#define Y_3D_DISP(height, w) ((height) * TILESIZE / (4 * (w))) + #define FLASH_TIME 0.4F #define DF_PENCIL_SHIFT 16 @@ -1221,14 +1225,13 @@ static int check_errors(game_state *state, int *errors) } for (i = 0; i < 4*w; i++) { - int start, step, j, k, n, best; + int start, step, j, n, best; STARTSTEP(start, step, i, w); if (!clues[i]) continue; best = n = 0; - k = 0; for (j = 0; j < w; j++) { int number = grid[start+j*step]; if (!number) @@ -1264,6 +1267,41 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, tx = FROMCOORD(x); ty = FROMCOORD(y); + if (ds->three_d) { + /* + * In 3D mode, just locating the mouse click in the natural + * square grid may not be sufficient to tell which tower the + * user clicked on. Investigate the _tops_ of the nearby + * towers to see if a click on one grid square was actually + * a click on a tower protruding into that region from + * another. + */ + int dx, dy; + for (dy = 0; dy <= 1; dy++) + for (dx = 0; dx >= -1; dx--) { + int cx = tx + dx, cy = ty + dy; + if (cx >= 0 && cx < w && cy >= 0 && cy < w) { + int height = state->grid[cy*w+cx]; + int bx = COORD(cx), by = COORD(cy); + int ox = bx + X_3D_DISP(height, w); + int oy = by - Y_3D_DISP(height, w); + if (/* on top face? */ + (x - ox >= 0 && x - ox < TILESIZE && + y - oy >= 0 && y - oy < TILESIZE) || + /* in triangle between top-left corners? */ + (ox > bx && x >= bx && x <= ox && y <= by && + (by-y) * (ox-bx) <= (by-oy) * (x-bx)) || + /* in triangle between bottom-right corners? */ + (ox > bx && x >= bx+TILESIZE && x <= ox+TILESIZE && + y >= oy+TILESIZE && + (by-y+TILESIZE)*(ox-bx) >= (by-oy)*(x-bx-TILESIZE))) { + tx = cx; + ty = cy; + } + } + } + } + if (tx >= 0 && tx < w && ty >= 0 && ty < w) { if (button == LEFT_BUTTON) { if (tx == ui->hx && ty == ui->hy && @@ -1486,17 +1524,19 @@ static void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues, int x, int y, long tile) { int w = clues->w /* , a = w*w */; - int tx, ty; + int tx, ty, bg; char str[64]; tx = COORD(x); ty = COORD(y); + bg = (tile & DF_HIGHLIGHT) ? COL_HIGHLIGHT : COL_BACKGROUND; + /* draw tower */ if (ds->three_d && (tile & DF_PLAYAREA) && (tile & DF_DIGIT_MASK)) { int coords[8]; - int xoff = (tile & DF_DIGIT_MASK) * TILESIZE / (8 * w); - int yoff = (tile & DF_DIGIT_MASK) * TILESIZE / (4 * w); + int xoff = X_3D_DISP(tile & DF_DIGIT_MASK, w); + int yoff = Y_3D_DISP(tile & DF_DIGIT_MASK, w); /* left face of tower */ coords[0] = tx; @@ -1507,7 +1547,7 @@ static void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues, coords[5] = coords[3] - yoff; coords[6] = coords[0] + xoff; coords[7] = coords[1] - yoff; - draw_polygon(dr, coords, 4, COL_BACKGROUND, COL_GRID); + draw_polygon(dr, coords, 4, bg, COL_GRID); /* bottom face of tower */ coords[0] = tx + TILESIZE; @@ -1518,7 +1558,7 @@ static void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues, coords[5] = coords[3] - yoff; coords[6] = coords[0] + xoff; coords[7] = coords[1] - yoff; - draw_polygon(dr, coords, 4, COL_BACKGROUND, COL_GRID); + draw_polygon(dr, coords, 4, bg, COL_GRID); /* now offset all subsequent drawing to the top of the tower */ tx += xoff; @@ -1526,8 +1566,7 @@ static void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues, } /* erase background */ - draw_rect(dr, tx, ty, TILESIZE, TILESIZE, - (tile & DF_HIGHLIGHT) ? COL_HIGHLIGHT : COL_BACKGROUND); + draw_rect(dr, tx, ty, TILESIZE, TILESIZE, bg); /* pencil-mode highlight */ if (tile & DF_HIGHLIGHT_PENCIL) { @@ -1584,10 +1623,10 @@ static void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues, * to put the pencil marks. */ /* Start with the whole square, minus space for impinging towers */ - pl = tx + TILESIZE/8; + pl = tx + (ds->three_d ? X_3D_DISP(w,w) : 0); pr = tx + TILESIZE; pt = ty; - pb = ty + TILESIZE - TILESIZE/4; + pb = ty + TILESIZE - (ds->three_d ? Y_3D_DISP(w,w) : 0); /* * We arrange our pencil marks in a grid layout, with @@ -1769,6 +1808,11 @@ static float game_flash_length(game_state *oldstate, game_state *newstate, return 0.0F; } +static int game_status(game_state *state) +{ + return state->completed ? +1 : 0; +} + static int game_timing_state(game_state *state, game_ui *ui) { if (state->completed) @@ -1888,6 +1932,7 @@ const struct game thegame = { game_redraw, game_anim_length, game_flash_length, + game_status, TRUE, FALSE, game_print_size, game_print, FALSE, /* wants_statusbar */ FALSE, game_timing_state,