예제 #1
0
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);
}
예제 #2
0
파일: towers.c 프로젝트: xymus/sgtpuzzles
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;
}
예제 #3
0
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);
}
예제 #4
0
파일: pattern.c 프로젝트: azaka/puzzless60
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;
}