static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, int x, int y, int button) { int gx, gy, dx, dy; char buf[80]; button &= ~MOD_MASK; gx = X(state, state->gap_pos); gy = Y(state, state->gap_pos); if (button == CURSOR_RIGHT && gx > 0) dx = gx - 1, dy = gy; else if (button == CURSOR_LEFT && gx < state->w-1) dx = gx + 1, dy = gy; else if (button == CURSOR_DOWN && gy > 0) dy = gy - 1, dx = gx; else if (button == CURSOR_UP && gy < state->h-1) dy = gy + 1, dx = gx; else if (button == LEFT_BUTTON) { dx = FROMCOORD(x); dy = FROMCOORD(y); if (dx < 0 || dx >= state->w || dy < 0 || dy >= state->h) return NULL; /* out of bounds */ /* * Any click location should be equal to the gap location * in _precisely_ one coordinate. */ if ((dx == gx && dy == gy) || (dx != gx && dy != gy)) return NULL; } else return NULL; /* no move */ sprintf(buf, "M%d,%d", dx, dy); return dupstr(buf); }
static char *interpret_move(game_state *state, game_ui *ui, const game_drawstate *ds, int x, int y, int button) { int w = state->par.w; int tx, ty; char buf[80]; button &= ~MOD_MASK; 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 && ui->hshow && ui->hpencil == 0) { ui->hshow = 0; } else { ui->hx = tx; ui->hy = ty; ui->hshow = !state->clues->immutable[ty*w+tx]; ui->hpencil = 0; } ui->hcursor = 0; return ""; /* UI activity occurred */ } if (button == RIGHT_BUTTON) { /* * Pencil-mode highlighting for non filled squares. */ if (state->grid[ty*w+tx] == 0) { if (tx == ui->hx && ty == ui->hy && ui->hshow && ui->hpencil) { ui->hshow = 0; } else { ui->hpencil = 1; ui->hx = tx; ui->hy = ty; ui->hshow = 1; } } else { ui->hshow = 0; } ui->hcursor = 0; return ""; /* UI activity occurred */ } } if (IS_CURSOR_MOVE(button)) { move_cursor(button, &ui->hx, &ui->hy, w, w, 0); ui->hshow = ui->hcursor = 1; return ""; } if (ui->hshow && (button == CURSOR_SELECT)) { ui->hpencil = 1 - ui->hpencil; ui->hcursor = 1; return ""; } if (ui->hshow && ((button >= '0' && button <= '9' && button - '0' <= w) || button == CURSOR_SELECT2 || button == '\b')) { int n = button - '0'; if (button == CURSOR_SELECT2 || button == '\b') n = 0; /* * Can't make pencil marks in a filled square. This can only * become highlighted if we're using cursor keys. */ if (ui->hpencil && state->grid[ui->hy*w+ui->hx]) return NULL; /* * Can't do anything to an immutable square. */ if (state->clues->immutable[ui->hy*w+ui->hx]) return NULL; sprintf(buf, "%c%d,%d,%d", (char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n); if (!ui->hcursor) ui->hshow = 0; return dupstr(buf); } if (button == 'M' || button == 'm') return dupstr("M"); return NULL; }
static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, int x, int y, int button) { int w = state->w, h = state->h, n = state->n /* , wh = w*h */; char buf[80]; int dir; button = button & (~MOD_MASK | MOD_NUM_KEYPAD); if (IS_CURSOR_MOVE(button)) { if (button == CURSOR_LEFT && ui->cur_x > 0) ui->cur_x--; if (button == CURSOR_RIGHT && (ui->cur_x+n) < (w)) ui->cur_x++; if (button == CURSOR_UP && ui->cur_y > 0) ui->cur_y--; if (button == CURSOR_DOWN && (ui->cur_y+n) < (h)) ui->cur_y++; ui->cur_visible = 1; return ""; } if (button == LEFT_BUTTON || button == RIGHT_BUTTON) { /* * Determine the coordinates of the click. We offset by n-1 * half-blocks so that the user must click at the centre of * a rotation region rather than at the corner. */ x -= (n-1) * TILE_SIZE / 2; y -= (n-1) * TILE_SIZE / 2; x = FROMCOORD(x); y = FROMCOORD(y); dir = (button == LEFT_BUTTON ? 1 : -1); if (x < 0 || x > w-n || y < 0 || y > h-n) return NULL; ui->cur_visible = 0; } else if (IS_CURSOR_SELECT(button)) { if (ui->cur_visible) { x = ui->cur_x; y = ui->cur_y; dir = (button == CURSOR_SELECT2) ? -1 : +1; } else { ui->cur_visible = 1; return ""; } } else if (button == 'a' || button == 'A' || button==MOD_NUM_KEYPAD+'7') { x = y = 0; dir = (button == 'A' ? -1 : +1); } else if (button == 'b' || button == 'B' || button==MOD_NUM_KEYPAD+'9') { x = w-n; y = 0; dir = (button == 'B' ? -1 : +1); } else if (button == 'c' || button == 'C' || button==MOD_NUM_KEYPAD+'1') { x = 0; y = h-n; dir = (button == 'C' ? -1 : +1); } else if (button == 'd' || button == 'D' || button==MOD_NUM_KEYPAD+'3') { x = w-n; y = h-n; dir = (button == 'D' ? -1 : +1); } else if (button==MOD_NUM_KEYPAD+'8' && (w-n) % 2 == 0) { x = (w-n) / 2; y = 0; dir = +1; } else if (button==MOD_NUM_KEYPAD+'2' && (w-n) % 2 == 0) { x = (w-n) / 2; y = h-n; dir = +1; } else if (button==MOD_NUM_KEYPAD+'4' && (h-n) % 2 == 0) { x = 0; y = (h-n) / 2; dir = +1; } else if (button==MOD_NUM_KEYPAD+'6' && (h-n) % 2 == 0) { x = w-n; y = (h-n) / 2; dir = +1; } else if (button==MOD_NUM_KEYPAD+'5' && (w-n) % 2 == 0 && (h-n) % 2 == 0){ x = (w-n) / 2; y = (h-n) / 2; dir = +1; } else { return NULL; /* no move to be made */ } /* * If we reach here, we have a valid move. */ sprintf(buf, "M%d,%d,%d", x, y, dir); return dupstr(buf); }
static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, int x, int y, int button) { button &= ~MOD_MASK; x = FROMCOORD(state->w, x); y = FROMCOORD(state->h, y); if (x >= 0 && x < state->w && y >= 0 && y < state->h && (button == LEFT_BUTTON || button == RIGHT_BUTTON || button == MIDDLE_BUTTON)) { #ifdef STYLUS_BASED int currstate = state->grid[y * state->w + x]; #endif ui->dragging = TRUE; if (button == LEFT_BUTTON) { ui->drag = LEFT_DRAG; ui->release = LEFT_RELEASE; #ifdef STYLUS_BASED ui->state = (currstate + 2) % 3; /* FULL -> EMPTY -> UNKNOWN */ #else ui->state = GRID_FULL; #endif } else if (button == RIGHT_BUTTON) { ui->drag = RIGHT_DRAG; ui->release = RIGHT_RELEASE; #ifdef STYLUS_BASED ui->state = (currstate + 1) % 3; /* EMPTY -> FULL -> UNKNOWN */ #else ui->state = GRID_EMPTY; #endif } else /* if (button == MIDDLE_BUTTON) */ { ui->drag = MIDDLE_DRAG; ui->release = MIDDLE_RELEASE; ui->state = GRID_UNKNOWN; } ui->drag_start_x = ui->drag_end_x = x; ui->drag_start_y = ui->drag_end_y = y; ui->cur_visible = 0; return ""; /* UI activity occurred */ } if (ui->dragging && button == ui->drag) { /* * There doesn't seem much point in allowing a rectangle * drag; people will generally only want to drag a single * horizontal or vertical line, so we make that easy by * snapping to it. * * Exception: if we're _middle_-button dragging to tag * things as UNKNOWN, we may well want to trash an entire * area and start over! */ if (ui->state != GRID_UNKNOWN) { if (abs(x - ui->drag_start_x) > abs(y - ui->drag_start_y)) y = ui->drag_start_y; else x = ui->drag_start_x; } if (x < 0) x = 0; if (y < 0) y = 0; if (x >= state->w) x = state->w - 1; if (y >= state->h) y = state->h - 1; ui->drag_end_x = x; ui->drag_end_y = y; return ""; /* UI activity occurred */ } if (ui->dragging && button == ui->release) { int x1, x2, y1, y2, xx, yy; int move_needed = FALSE; x1 = min(ui->drag_start_x, ui->drag_end_x); x2 = max(ui->drag_start_x, ui->drag_end_x); y1 = min(ui->drag_start_y, ui->drag_end_y); y2 = max(ui->drag_start_y, ui->drag_end_y); for (yy = y1; yy <= y2; yy++) for (xx = x1; xx <= x2; xx++) if (state->grid[yy * state->w + xx] != ui->state) move_needed = TRUE; ui->dragging = FALSE; if (move_needed) { char buf[80]; sprintf(buf, "%c%d,%d,%d,%d", (char)(ui->state == GRID_FULL ? 'F' : ui->state == GRID_EMPTY ? 'E' : 'U'), x1, y1, x2-x1+1, y2-y1+1); return dupstr(buf); } else return ""; /* UI activity occurred */ } if (IS_CURSOR_MOVE(button)) { move_cursor(button, &ui->cur_x, &ui->cur_y, state->w, state->h, 0); ui->cur_visible = 1; return ""; } if (IS_CURSOR_SELECT(button)) { int currstate = state->grid[ui->cur_y * state->w + ui->cur_x]; int newstate; char buf[80]; if (!ui->cur_visible) { ui->cur_visible = 1; return ""; } if (button == CURSOR_SELECT2) newstate = currstate == GRID_UNKNOWN ? GRID_EMPTY : currstate == GRID_EMPTY ? GRID_FULL : GRID_UNKNOWN; else newstate = currstate == GRID_UNKNOWN ? GRID_FULL : currstate == GRID_FULL ? GRID_EMPTY : GRID_UNKNOWN; sprintf(buf, "%c%d,%d,%d,%d", (char)(newstate == GRID_FULL ? 'F' : newstate == GRID_EMPTY ? 'E' : 'U'), ui->cur_x, ui->cur_y, 1, 1); return dupstr(buf); } return NULL; }