static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, int x, int y, int button) { int gx = -1, gy = -1, rangeno = -1, wouldflash = 0; enum { NONE, TOGGLE_BALL, TOGGLE_LOCK, FIRE, REVEAL, TOGGLE_COLUMN_LOCK, TOGGLE_ROW_LOCK} action = NONE; char buf[80], *nullret = NULL; if (IS_CURSOR_MOVE(button)) { int cx = ui->cur_x, cy = ui->cur_y; move_cursor(button, &cx, &cy, state->w+2, state->h+2, 0); if ((cx == 0 && cy == 0 && !CAN_REVEAL(state)) || (cx == 0 && cy == state->h+1) || (cx == state->w+1 && cy == 0) || (cx == state->w+1 && cy == state->h+1)) return NULL; /* disallow moving cursor to corners. */ ui->cur_x = cx; ui->cur_y = cy; ui->cur_visible = 1; return ""; } if (button == LEFT_BUTTON || button == RIGHT_BUTTON) { gx = FROMDRAW(x); gy = FROMDRAW(y); ui->cur_visible = 0; wouldflash = 1; } else if (button == LEFT_RELEASE) { ui->flash_laser = 0; return ""; } else if (IS_CURSOR_SELECT(button)) { if (ui->cur_visible) { gx = ui->cur_x; gy = ui->cur_y; ui->flash_laser = 0; wouldflash = 2; } else { ui->cur_visible = 1; return ""; } /* Fix up 'button' for the below logic. */ if (button == CURSOR_SELECT2) button = RIGHT_BUTTON; else button = LEFT_BUTTON; } if (gx != -1 && gy != -1) { if (gx == 0 && gy == 0 && button == LEFT_BUTTON) action = REVEAL; if (gx >= 1 && gx <= state->w && gy >= 1 && gy <= state->h) { if (button == LEFT_BUTTON) { if (!(GRID(state, gx,gy) & BALL_LOCK)) action = TOGGLE_BALL; } else action = TOGGLE_LOCK; } if (grid2range(state, gx, gy, &rangeno)) { if (button == LEFT_BUTTON) action = FIRE; else if (gy == 0 || gy > state->h) action = TOGGLE_COLUMN_LOCK; /* and use gx */ else action = TOGGLE_ROW_LOCK; /* and use gy */ } } switch (action) { case TOGGLE_BALL: sprintf(buf, "T%d,%d", gx, gy); break; case TOGGLE_LOCK: sprintf(buf, "LB%d,%d", gx, gy); break; case TOGGLE_COLUMN_LOCK: sprintf(buf, "LC%d", gx); break; case TOGGLE_ROW_LOCK: sprintf(buf, "LR%d", gy); break; case FIRE: if (state->reveal && state->exits[rangeno] == LASER_EMPTY) return nullret; ui->flash_laserno = rangeno; ui->flash_laser = wouldflash; nullret = ""; if (state->exits[rangeno] != LASER_EMPTY) return ""; sprintf(buf, "F%d", rangeno); break; case REVEAL: if (!CAN_REVEAL(state)) return nullret; if (ui->cur_visible == 1) ui->cur_x = ui->cur_y = 1; sprintf(buf, "R"); break; default: return nullret; } if (state->reveal) return nullret; ui->newmove = TRUE; return dupstr(buf); }
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; }