mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 08:01:30 -07:00
Patch from James H to add keyboard control in Sixteen and Netslide
(and also belatedly document the keyboard support in Unequal). [originally from svn r8432]
This commit is contained in:
29
misc.c
29
misc.c
@ -280,6 +280,35 @@ int c2pos(int w, int h, int cx, int cy)
|
|||||||
return -1; /* not reached */
|
return -1; /* not reached */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int c2diff(int w, int h, int cx, int cy, int button)
|
||||||
|
{
|
||||||
|
int diff = 0;
|
||||||
|
|
||||||
|
assert(IS_CURSOR_MOVE(button));
|
||||||
|
|
||||||
|
/* Obvious moves around edge. */
|
||||||
|
if (cy == -1)
|
||||||
|
diff = (button == CURSOR_RIGHT) ? +1 : (button == CURSOR_LEFT) ? -1 : diff;
|
||||||
|
if (cy == h)
|
||||||
|
diff = (button == CURSOR_RIGHT) ? -1 : (button == CURSOR_LEFT) ? +1 : diff;
|
||||||
|
if (cx == -1)
|
||||||
|
diff = (button == CURSOR_UP) ? +1 : (button == CURSOR_DOWN) ? -1 : diff;
|
||||||
|
if (cx == w)
|
||||||
|
diff = (button == CURSOR_UP) ? -1 : (button == CURSOR_DOWN) ? +1 : diff;
|
||||||
|
|
||||||
|
if (button == CURSOR_LEFT && cx == w && (cy == 0 || cy == h-1))
|
||||||
|
diff = (cy == 0) ? -1 : +1;
|
||||||
|
if (button == CURSOR_RIGHT && cx == -1 && (cy == 0 || cy == h-1))
|
||||||
|
diff = (cy == 0) ? +1 : -1;
|
||||||
|
if (button == CURSOR_DOWN && cy == -1 && (cx == 0 || cx == w-1))
|
||||||
|
diff = (cx == 0) ? -1 : +1;
|
||||||
|
if (button == CURSOR_UP && cy == h && (cx == 0 || cx == w-1))
|
||||||
|
diff = (cx == 0) ? +1 : -1;
|
||||||
|
|
||||||
|
debug(("cx,cy = %d,%d; w%d h%d, diff = %d", cx, cy, w, h, diff));
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
|
|
||||||
void pos2c(int w, int h, int pos, int *cx, int *cy)
|
void pos2c(int w, int h, int pos, int *cx, int *cy)
|
||||||
{
|
{
|
||||||
int max = w+h+w+h;
|
int max = w+h+w+h;
|
||||||
|
118
netslide.c
118
netslide.c
@ -159,15 +159,15 @@ static game_params *default_params(void)
|
|||||||
|
|
||||||
static const struct { int x, y, wrap, bprob; const char* desc; }
|
static const struct { int x, y, wrap, bprob; const char* desc; }
|
||||||
netslide_presets[] = {
|
netslide_presets[] = {
|
||||||
{3, 3, FALSE, 1.0, " easy"},
|
{3, 3, FALSE, 1, " easy"},
|
||||||
{3, 3, FALSE, 0.0, " medium"},
|
{3, 3, FALSE, 0, " medium"},
|
||||||
{3, 3, TRUE, 0.0, " hard"},
|
{3, 3, TRUE, 0, " hard"},
|
||||||
{4, 4, FALSE, 1.0, " easy"},
|
{4, 4, FALSE, 1, " easy"},
|
||||||
{4, 4, FALSE, 0.0, " medium"},
|
{4, 4, FALSE, 0, " medium"},
|
||||||
{4, 4, TRUE, 0.0, " hard"},
|
{4, 4, TRUE, 0, " hard"},
|
||||||
{5, 5, FALSE, 1.0, " easy"},
|
{5, 5, FALSE, 1, " easy"},
|
||||||
{5, 5, FALSE, 0.0, " medium"},
|
{5, 5, FALSE, 0, " medium"},
|
||||||
{5, 5, TRUE, 0.0, " hard"},
|
{5, 5, TRUE, 0, " hard"},
|
||||||
};
|
};
|
||||||
|
|
||||||
static int game_fetch_preset(int i, char **name, game_params **params)
|
static int game_fetch_preset(int i, char **name, game_params **params)
|
||||||
@ -182,7 +182,7 @@ static int game_fetch_preset(int i, char **name, game_params **params)
|
|||||||
ret->width = netslide_presets[i].x;
|
ret->width = netslide_presets[i].x;
|
||||||
ret->height = netslide_presets[i].y;
|
ret->height = netslide_presets[i].y;
|
||||||
ret->wrapping = netslide_presets[i].wrap;
|
ret->wrapping = netslide_presets[i].wrap;
|
||||||
ret->barrier_probability = netslide_presets[i].bprob;
|
ret->barrier_probability = (float)netslide_presets[i].bprob;
|
||||||
ret->movetarget = 0;
|
ret->movetarget = 0;
|
||||||
|
|
||||||
sprintf(str, "%dx%d%s", ret->width, ret->height, netslide_presets[i].desc);
|
sprintf(str, "%dx%d%s", ret->width, ret->height, netslide_presets[i].desc);
|
||||||
@ -221,7 +221,7 @@ static void decode_params(game_params *ret, char const *string)
|
|||||||
if ( (ret->wrapping = (*p == 'w')) != 0 )
|
if ( (ret->wrapping = (*p == 'w')) != 0 )
|
||||||
p++;
|
p++;
|
||||||
if (*p == 'b') {
|
if (*p == 'b') {
|
||||||
ret->barrier_probability = atof(++p);
|
ret->barrier_probability = (float)atof(++p);
|
||||||
while (*p && (isdigit((unsigned char)*p) || *p == '.')) p++;
|
while (*p && (isdigit((unsigned char)*p) || *p == '.')) p++;
|
||||||
}
|
}
|
||||||
if (*p == 'm') {
|
if (*p == 'm') {
|
||||||
@ -979,8 +979,8 @@ struct game_ui {
|
|||||||
static game_ui *new_ui(game_state *state)
|
static game_ui *new_ui(game_state *state)
|
||||||
{
|
{
|
||||||
game_ui *ui = snew(game_ui);
|
game_ui *ui = snew(game_ui);
|
||||||
ui->cur_x = state->width / 2;
|
ui->cur_x = 0;
|
||||||
ui->cur_y = state->height / 2;
|
ui->cur_y = -1;
|
||||||
ui->cur_visible = FALSE;
|
ui->cur_visible = FALSE;
|
||||||
|
|
||||||
return ui;
|
return ui;
|
||||||
@ -1052,6 +1052,7 @@ struct game_drawstate {
|
|||||||
int width, height;
|
int width, height;
|
||||||
int tilesize;
|
int tilesize;
|
||||||
unsigned char *visible;
|
unsigned char *visible;
|
||||||
|
int cur_x, cur_y;
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *interpret_move(game_state *state, game_ui *ui,
|
static char *interpret_move(game_state *state, game_ui *ui,
|
||||||
@ -1063,11 +1064,37 @@ static char *interpret_move(game_state *state, game_ui *ui,
|
|||||||
|
|
||||||
button &= ~MOD_MASK;
|
button &= ~MOD_MASK;
|
||||||
|
|
||||||
if (button != LEFT_BUTTON && button != RIGHT_BUTTON)
|
if (IS_CURSOR_MOVE(button)) {
|
||||||
return NULL;
|
int cpos, diff = 0;
|
||||||
|
cpos = c2pos(state->width, state->height, ui->cur_x, ui->cur_y);
|
||||||
|
diff = c2diff(state->width, state->height, ui->cur_x, ui->cur_y, button);
|
||||||
|
|
||||||
|
if (diff != 0) {
|
||||||
|
do { /* we might have to do this more than once to skip missing arrows */
|
||||||
|
cpos += diff;
|
||||||
|
pos2c(state->width, state->height, cpos, &ui->cur_x, &ui->cur_y);
|
||||||
|
} while (ui->cur_x == state->cx || ui->cur_y == state->cy);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->cur_visible = 1;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (button == LEFT_BUTTON || button == RIGHT_BUTTON) {
|
||||||
cx = (x - (BORDER + WINDOW_OFFSET + TILE_BORDER) + 2*TILE_SIZE) / TILE_SIZE - 2;
|
cx = (x - (BORDER + WINDOW_OFFSET + TILE_BORDER) + 2*TILE_SIZE) / TILE_SIZE - 2;
|
||||||
cy = (y - (BORDER + WINDOW_OFFSET + TILE_BORDER) + 2*TILE_SIZE) / TILE_SIZE - 2;
|
cy = (y - (BORDER + WINDOW_OFFSET + TILE_BORDER) + 2*TILE_SIZE) / TILE_SIZE - 2;
|
||||||
|
ui->cur_visible = 0;
|
||||||
|
} else if (IS_CURSOR_SELECT(button)) {
|
||||||
|
if (ui->cur_visible) {
|
||||||
|
cx = ui->cur_x;
|
||||||
|
cy = ui->cur_y;
|
||||||
|
} else {
|
||||||
|
/* 'click' when cursor is invisible just makes cursor visible. */
|
||||||
|
ui->cur_visible = 1;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (cy >= 0 && cy < state->height && cy != state->cy)
|
if (cy >= 0 && cy < state->height && cy != state->cy)
|
||||||
{
|
{
|
||||||
@ -1187,6 +1214,7 @@ static game_drawstate *game_new_drawstate(drawing *dr, game_state *state)
|
|||||||
ds->visible = snewn(state->width * state->height, unsigned char);
|
ds->visible = snewn(state->width * state->height, unsigned char);
|
||||||
ds->tilesize = 0; /* not decided yet */
|
ds->tilesize = 0; /* not decided yet */
|
||||||
memset(ds->visible, 0xFF, state->width * state->height);
|
memset(ds->visible, 0xFF, state->width * state->height);
|
||||||
|
ds->cur_x = ds->cur_y = -1;
|
||||||
|
|
||||||
return ds;
|
return ds;
|
||||||
}
|
}
|
||||||
@ -1351,8 +1379,8 @@ static void draw_barrier(drawing *dr, game_drawstate *ds,
|
|||||||
static void draw_tile(drawing *dr, game_drawstate *ds, game_state *state,
|
static void draw_tile(drawing *dr, game_drawstate *ds, game_state *state,
|
||||||
int x, int y, int tile, float xshift, float yshift)
|
int x, int y, int tile, float xshift, float yshift)
|
||||||
{
|
{
|
||||||
int bx = BORDER + WINDOW_OFFSET + TILE_SIZE * x + (xshift * TILE_SIZE);
|
int bx = BORDER + WINDOW_OFFSET + TILE_SIZE * x + (int)(xshift * TILE_SIZE);
|
||||||
int by = BORDER + WINDOW_OFFSET + TILE_SIZE * y + (yshift * TILE_SIZE);
|
int by = BORDER + WINDOW_OFFSET + TILE_SIZE * y + (int)(yshift * TILE_SIZE);
|
||||||
float cx, cy, ex, ey;
|
float cx, cy, ex, ey;
|
||||||
int dir, col;
|
int dir, col;
|
||||||
|
|
||||||
@ -1509,7 +1537,7 @@ static void draw_tile_barriers(drawing *dr, game_drawstate *ds,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void draw_arrow(drawing *dr, game_drawstate *ds,
|
static void draw_arrow(drawing *dr, game_drawstate *ds,
|
||||||
int x, int y, int xdx, int xdy)
|
int x, int y, int xdx, int xdy, int cur)
|
||||||
{
|
{
|
||||||
int coords[14];
|
int coords[14];
|
||||||
int ydy = -xdx, ydx = xdy;
|
int ydy = -xdx, ydx = xdy;
|
||||||
@ -1529,7 +1557,29 @@ static void draw_arrow(drawing *dr, game_drawstate *ds,
|
|||||||
POINT(5, 3 * TILE_SIZE / 8, TILE_SIZE / 2); /* left concave */
|
POINT(5, 3 * TILE_SIZE / 8, TILE_SIZE / 2); /* left concave */
|
||||||
POINT(6, TILE_SIZE / 4, TILE_SIZE / 2); /* left corner */
|
POINT(6, TILE_SIZE / 4, TILE_SIZE / 2); /* left corner */
|
||||||
|
|
||||||
draw_polygon(dr, coords, 7, COL_LOWLIGHT, COL_TEXT);
|
draw_polygon(dr, coords, 7, cur ? COL_POWERED : COL_LOWLIGHT, COL_TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_arrow_for_cursor(drawing *dr, game_drawstate *ds,
|
||||||
|
int cur_x, int cur_y, int cur)
|
||||||
|
{
|
||||||
|
if (cur_x == -1 && cur_y == -1)
|
||||||
|
return; /* 'no cursur here */
|
||||||
|
else if (cur_x == -1) /* LH column. */
|
||||||
|
draw_arrow(dr, ds, 0, cur_y+1, 0, -1, cur);
|
||||||
|
else if (cur_x == ds->width) /* RH column */
|
||||||
|
draw_arrow(dr, ds, ds->width, cur_y, 0, +1, cur);
|
||||||
|
else if (cur_y == -1) /* Top row */
|
||||||
|
draw_arrow(dr, ds, cur_x, 0, +1, 0, cur);
|
||||||
|
else if (cur_y == ds->height) /* Bottom row */
|
||||||
|
draw_arrow(dr, ds, cur_x+1, ds->height, -1, 0, cur);
|
||||||
|
else
|
||||||
|
assert(!"Invalid cursor position");
|
||||||
|
|
||||||
|
draw_update(dr,
|
||||||
|
cur_x * TILE_SIZE + BORDER + WINDOW_OFFSET,
|
||||||
|
cur_y * TILE_SIZE + BORDER + WINDOW_OFFSET,
|
||||||
|
TILE_SIZE, TILE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
|
static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
|
||||||
@ -1539,6 +1589,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
|
|||||||
unsigned char *active;
|
unsigned char *active;
|
||||||
float xshift = 0.0;
|
float xshift = 0.0;
|
||||||
float yshift = 0.0;
|
float yshift = 0.0;
|
||||||
|
int cur_x = -1, cur_y = -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clear the screen and draw the exterior barrier lines if this
|
* Clear the screen and draw the exterior barrier lines if this
|
||||||
@ -1595,15 +1646,26 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
|
|||||||
*/
|
*/
|
||||||
for (x = 0; x < ds->width; x++) {
|
for (x = 0; x < ds->width; x++) {
|
||||||
if (x == state->cx) continue;
|
if (x == state->cx) continue;
|
||||||
draw_arrow(dr, ds, x, 0, +1, 0);
|
draw_arrow(dr, ds, x, 0, +1, 0, 0);
|
||||||
draw_arrow(dr, ds, x+1, ds->height, -1, 0);
|
draw_arrow(dr, ds, x+1, ds->height, -1, 0, 0);
|
||||||
}
|
}
|
||||||
for (y = 0; y < ds->height; y++) {
|
for (y = 0; y < ds->height; y++) {
|
||||||
if (y == state->cy) continue;
|
if (y == state->cy) continue;
|
||||||
draw_arrow(dr, ds, ds->width, y, 0, +1);
|
draw_arrow(dr, ds, ds->width, y, 0, +1, 0);
|
||||||
draw_arrow(dr, ds, 0, y+1, 0, -1);
|
draw_arrow(dr, ds, 0, y+1, 0, -1, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ui->cur_visible) {
|
||||||
|
cur_x = ui->cur_x; cur_y = ui->cur_y;
|
||||||
|
}
|
||||||
|
if (cur_x != ds->cur_x || cur_y != ds->cur_y) {
|
||||||
|
/* Cursor has changed; redraw two (prev and curr) arrows. */
|
||||||
|
assert(cur_x != state->cx && cur_y != state->cy);
|
||||||
|
|
||||||
|
draw_arrow_for_cursor(dr, ds, cur_x, cur_y, 1);
|
||||||
|
draw_arrow_for_cursor(dr, ds, ds->cur_x, ds->cur_y, 0);
|
||||||
|
ds->cur_x = cur_x; ds->cur_y = cur_y;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if this is an undo. If so, we will need to run any animation
|
/* Check if this is an undo. If so, we will need to run any animation
|
||||||
* backwards.
|
* backwards.
|
||||||
@ -1622,9 +1684,9 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
|
|||||||
* state->last_move_pos, in direction
|
* state->last_move_pos, in direction
|
||||||
* state->last_move_dir
|
* state->last_move_dir
|
||||||
*/
|
*/
|
||||||
xshift = state->last_move_row == -1 ? 0.0 :
|
xshift = state->last_move_row == -1 ? 0.0F :
|
||||||
(1 - t / ANIM_TIME) * state->last_move_dir;
|
(1 - t / ANIM_TIME) * state->last_move_dir;
|
||||||
yshift = state->last_move_col == -1 ? 0.0 :
|
yshift = state->last_move_col == -1 ? 0.0F :
|
||||||
(1 - t / ANIM_TIME) * state->last_move_dir;
|
(1 - t / ANIM_TIME) * state->last_move_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1678,8 +1740,8 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
|
|||||||
index(state, ds->visible, x, y) == 0xFF ||
|
index(state, ds->visible, x, y) == 0xFF ||
|
||||||
(x == state->last_move_col || y == state->last_move_row))
|
(x == state->last_move_col || y == state->last_move_row))
|
||||||
{
|
{
|
||||||
float xs = (y == state->last_move_row ? xshift : 0.0);
|
float xs = (y == state->last_move_row ? xshift : (float)0.0);
|
||||||
float ys = (x == state->last_move_col ? yshift : 0.0);
|
float ys = (x == state->last_move_col ? yshift : (float)0.0);
|
||||||
|
|
||||||
draw_tile(dr, ds, state, x, y, c, xs, ys);
|
draw_tile(dr, ds, state, x, y, c, xs, ys);
|
||||||
if (xs < 0 && x == 0)
|
if (xs < 0 && x == 0)
|
||||||
@ -1820,3 +1882,5 @@ const struct game thegame = {
|
|||||||
FALSE, game_timing_state,
|
FALSE, game_timing_state,
|
||||||
0, /* flags */
|
0, /* flags */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* vim: set shiftwidth=4 tabstop=8: */
|
||||||
|
26
puzzles.but
26
puzzles.but
@ -646,9 +646,13 @@ rather than just engineering.
|
|||||||
|
|
||||||
\H{sixteen-controls} \I{controls, for Sixteen}Sixteen controls
|
\H{sixteen-controls} \I{controls, for Sixteen}Sixteen controls
|
||||||
|
|
||||||
This game is played with the mouse. Left-clicking on an arrow will
|
Left-clicking on an arrow will move the appropriate row or column in
|
||||||
move the appropriate row or column in the direction indicated.
|
the direction indicated. Right-clicking will move it in the opposite
|
||||||
Right-clicking will move it in the opposite direction.
|
direction.
|
||||||
|
|
||||||
|
Alternatively, use the cursor keys to move the position indicator
|
||||||
|
around the edge of the grid, and use the return key to move the
|
||||||
|
row/column in the direction indicated.
|
||||||
|
|
||||||
(All the actions described in \k{common-actions} are also available.)
|
(All the actions described in \k{common-actions} are also available.)
|
||||||
|
|
||||||
@ -833,8 +837,8 @@ movement of Sixteen (see \k{sixteen}): you have a Net grid, but
|
|||||||
instead of rotating tiles back into place you have to slide them
|
instead of rotating tiles back into place you have to slide them
|
||||||
into place by moving a whole row at a time.
|
into place by moving a whole row at a time.
|
||||||
|
|
||||||
As in Sixteen, \I{controls, for Netslide}control is with the mouse.
|
As in Sixteen, \I{controls, for Netslide}control is with the mouse or
|
||||||
See \k{sixteen-controls}.
|
cursor keys. See \k{sixteen-controls}.
|
||||||
|
|
||||||
\I{parameters, for Netslide}The available game parameters have similar
|
\I{parameters, for Netslide}The available game parameters have similar
|
||||||
meanings to those in Net (see \k{net-params}) and Sixteen (see
|
meanings to those in Net (see \k{net-params}) and Sixteen (see
|
||||||
@ -2210,7 +2214,8 @@ Space to clear it again (or use the Undo feature).
|
|||||||
|
|
||||||
If you \e{right}-click in a square and then type a number, that
|
If you \e{right}-click in a square and then type a number, that
|
||||||
number will be entered in the square as a \q{pencil mark}. You can
|
number will be entered in the square as a \q{pencil mark}. You can
|
||||||
have pencil marks for multiple numbers in the same square.
|
have pencil marks for multiple numbers in the same square. Squares
|
||||||
|
containing filled-in numbers cannot also contain pencil marks.
|
||||||
|
|
||||||
The game pays no attention to pencil marks, so exactly what you use
|
The game pays no attention to pencil marks, so exactly what you use
|
||||||
them for is up to you: you can use them as reminders that a
|
them for is up to you: you can use them as reminders that a
|
||||||
@ -2227,7 +2232,14 @@ pressing space will also erase pencil marks.
|
|||||||
|
|
||||||
As for Solo, the cursor keys can be used in conjunction with the digit
|
As for Solo, the cursor keys can be used in conjunction with the digit
|
||||||
keys to set numbers or pencil marks. You can also use the 'M' key to
|
keys to set numbers or pencil marks. You can also use the 'M' key to
|
||||||
auto-fill every numeric hint, ready for removal as required.
|
auto-fill every numeric hint, ready for removal as required, or the 'H'
|
||||||
|
key to do the same but also to remove all obvious hints.
|
||||||
|
|
||||||
|
Alternatively, use the cursor keys to move the mark around the grid.
|
||||||
|
Pressing the return key toggles the mark (from a normal mark to a
|
||||||
|
pencil mark), and typing a number in is entered in the square in the
|
||||||
|
appropriate way; typing in a 0 or using the space bar will clear a
|
||||||
|
filled square.
|
||||||
|
|
||||||
(All the actions described in \k{common-actions} are also available.)
|
(All the actions described in \k{common-actions} are also available.)
|
||||||
|
|
||||||
|
@ -306,6 +306,7 @@ void move_cursor(int button, int *x, int *y, int maxw, int maxh, int wrap);
|
|||||||
|
|
||||||
/* Used in netslide.c and sixteen.c for cursor movement around edge. */
|
/* Used in netslide.c and sixteen.c for cursor movement around edge. */
|
||||||
int c2pos(int w, int h, int cx, int cy);
|
int c2pos(int w, int h, int cx, int cy);
|
||||||
|
int c2diff(int w, int h, int cx, int cy, int button);
|
||||||
void pos2c(int w, int h, int pos, int *cx, int *cy);
|
void pos2c(int w, int h, int pos, int *cx, int *cy);
|
||||||
|
|
||||||
/* Draws text with an 'outline' formed by offsetting the text
|
/* Draws text with an 'outline' formed by offsetting the text
|
||||||
|
98
sixteen.c
98
sixteen.c
@ -553,13 +553,24 @@ static char *game_text_format(game_state *state)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct game_ui {
|
||||||
|
int cur_x, cur_y;
|
||||||
|
int cur_visible;
|
||||||
|
};
|
||||||
|
|
||||||
static game_ui *new_ui(game_state *state)
|
static game_ui *new_ui(game_state *state)
|
||||||
{
|
{
|
||||||
return NULL;
|
game_ui *ui = snew(game_ui);
|
||||||
|
ui->cur_x = 0;
|
||||||
|
ui->cur_y = -1;
|
||||||
|
ui->cur_visible = FALSE;
|
||||||
|
|
||||||
|
return ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_ui(game_ui *ui)
|
static void free_ui(game_ui *ui)
|
||||||
{
|
{
|
||||||
|
sfree(ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *encode_ui(game_ui *ui)
|
static char *encode_ui(game_ui *ui)
|
||||||
@ -581,20 +592,47 @@ struct game_drawstate {
|
|||||||
int w, h, bgcolour;
|
int w, h, bgcolour;
|
||||||
int *tiles;
|
int *tiles;
|
||||||
int tilesize;
|
int tilesize;
|
||||||
|
int cur_x, cur_y;
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
|
static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
|
||||||
int x, int y, int button)
|
int x, int y, int button)
|
||||||
{
|
{
|
||||||
int cx, cy, dx, dy;
|
int cx = -1, cy = -1, dx, dy;
|
||||||
char buf[80];
|
char buf[80];
|
||||||
|
|
||||||
button &= ~MOD_MASK;
|
button &= ~MOD_MASK;
|
||||||
if (button != LEFT_BUTTON && button != RIGHT_BUTTON)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
|
if (IS_CURSOR_MOVE(button)) {
|
||||||
|
/* right/down rotates cursor clockwise,
|
||||||
|
* left/up rotates anticlockwise. */
|
||||||
|
int cpos, diff;
|
||||||
|
cpos = c2pos(state->w, state->h, ui->cur_x, ui->cur_y);
|
||||||
|
diff = c2diff(state->w, state->h, ui->cur_x, ui->cur_y, button);
|
||||||
|
|
||||||
|
cpos += diff;
|
||||||
|
pos2c(state->w, state->h, cpos, &ui->cur_x, &ui->cur_y);
|
||||||
|
|
||||||
|
ui->cur_visible = 1;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (button == LEFT_BUTTON || button == RIGHT_BUTTON) {
|
||||||
cx = FROMCOORD(x);
|
cx = FROMCOORD(x);
|
||||||
cy = FROMCOORD(y);
|
cy = FROMCOORD(y);
|
||||||
|
ui->cur_visible = 0;
|
||||||
|
} else if (IS_CURSOR_SELECT(button)) {
|
||||||
|
if (ui->cur_visible) {
|
||||||
|
cx = ui->cur_x;
|
||||||
|
cy = ui->cur_y;
|
||||||
|
} else {
|
||||||
|
ui->cur_visible = 1;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (cx == -1 && cy >= 0 && cy < state->h)
|
if (cx == -1 && cy >= 0 && cy < state->h)
|
||||||
dx = -1, dy = 0;
|
dx = -1, dy = 0;
|
||||||
else if (cx == state->w && cy >= 0 && cy < state->h)
|
else if (cx == state->w && cy >= 0 && cy < state->h)
|
||||||
@ -604,10 +642,10 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
|
|||||||
else if (cy == state->h && cx >= 0 && cx < state->w)
|
else if (cy == state->h && cx >= 0 && cx < state->w)
|
||||||
dy = +1, dx = 0;
|
dy = +1, dx = 0;
|
||||||
else
|
else
|
||||||
return NULL; /* invalid click location */
|
return ""; /* invalid click location */
|
||||||
|
|
||||||
/* reverse direction if right hand button is pressed */
|
/* reverse direction if right hand button is pressed */
|
||||||
if (button == RIGHT_BUTTON) {
|
if (button == RIGHT_BUTTON || button == CURSOR_SELECT2) {
|
||||||
dx = -dx;
|
dx = -dx;
|
||||||
dy = -dy;
|
dy = -dy;
|
||||||
}
|
}
|
||||||
@ -731,6 +769,7 @@ static game_drawstate *game_new_drawstate(drawing *dr, game_state *state)
|
|||||||
ds->tilesize = 0; /* haven't decided yet */
|
ds->tilesize = 0; /* haven't decided yet */
|
||||||
for (i = 0; i < ds->w*ds->h; i++)
|
for (i = 0; i < ds->w*ds->h; i++)
|
||||||
ds->tiles[i] = -1;
|
ds->tiles[i] = -1;
|
||||||
|
ds->cur_x = ds->cur_y = -1;
|
||||||
|
|
||||||
return ds;
|
return ds;
|
||||||
}
|
}
|
||||||
@ -777,7 +816,7 @@ static void draw_tile(drawing *dr, game_drawstate *ds,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void draw_arrow(drawing *dr, game_drawstate *ds,
|
static void draw_arrow(drawing *dr, game_drawstate *ds,
|
||||||
int x, int y, int xdx, int xdy)
|
int x, int y, int xdx, int xdy, int cur)
|
||||||
{
|
{
|
||||||
int coords[14];
|
int coords[14];
|
||||||
int ydy = -xdx, ydx = xdy;
|
int ydy = -xdx, ydx = xdy;
|
||||||
@ -794,7 +833,27 @@ static void draw_arrow(drawing *dr, game_drawstate *ds,
|
|||||||
POINT(5, 3 * TILE_SIZE / 8, TILE_SIZE / 2); /* left concave */
|
POINT(5, 3 * TILE_SIZE / 8, TILE_SIZE / 2); /* left concave */
|
||||||
POINT(6, TILE_SIZE / 4, TILE_SIZE / 2); /* left corner */
|
POINT(6, TILE_SIZE / 4, TILE_SIZE / 2); /* left corner */
|
||||||
|
|
||||||
draw_polygon(dr, coords, 7, COL_LOWLIGHT, COL_TEXT);
|
draw_polygon(dr, coords, 7, cur ? COL_HIGHLIGHT : COL_LOWLIGHT, COL_TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_arrow_for_cursor(drawing *dr, game_drawstate *ds,
|
||||||
|
int cur_x, int cur_y, int cur)
|
||||||
|
{
|
||||||
|
if (cur_x == -1 && cur_y == -1)
|
||||||
|
return; /* 'no cursur here */
|
||||||
|
else if (cur_x == -1) /* LH column. */
|
||||||
|
draw_arrow(dr, ds, COORD(0), COORD(cur_y+1), 0, -1, cur);
|
||||||
|
else if (cur_x == ds->w) /* RH column */
|
||||||
|
draw_arrow(dr, ds, COORD(ds->w), COORD(cur_y), 0, +1, cur);
|
||||||
|
else if (cur_y == -1) /* Top row */
|
||||||
|
draw_arrow(dr, ds, COORD(cur_x), COORD(0), +1, 0, cur);
|
||||||
|
else if (cur_y == ds->h) /* Bottom row */
|
||||||
|
draw_arrow(dr, ds, COORD(cur_x+1), COORD(ds->h), -1, 0, cur);
|
||||||
|
else
|
||||||
|
assert(!"Invalid cursor position");
|
||||||
|
|
||||||
|
draw_update(dr, COORD(cur_x), COORD(cur_y),
|
||||||
|
TILE_SIZE, TILE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
|
static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
|
||||||
@ -802,6 +861,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
|
|||||||
float animtime, float flashtime)
|
float animtime, float flashtime)
|
||||||
{
|
{
|
||||||
int i, bgcolour;
|
int i, bgcolour;
|
||||||
|
int cur_x = -1, cur_y = -1;
|
||||||
|
|
||||||
if (flashtime > 0) {
|
if (flashtime > 0) {
|
||||||
int frame = (int)(flashtime / FLASH_FRAME);
|
int frame = (int)(flashtime / FLASH_FRAME);
|
||||||
@ -842,16 +902,28 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
|
|||||||
* Arrows for making moves.
|
* Arrows for making moves.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < state->w; i++) {
|
for (i = 0; i < state->w; i++) {
|
||||||
draw_arrow(dr, ds, COORD(i), COORD(0), +1, 0);
|
draw_arrow(dr, ds, COORD(i), COORD(0), +1, 0, 0);
|
||||||
draw_arrow(dr, ds, COORD(i+1), COORD(state->h), -1, 0);
|
draw_arrow(dr, ds, COORD(i+1), COORD(state->h), -1, 0, 0);
|
||||||
}
|
}
|
||||||
for (i = 0; i < state->h; i++) {
|
for (i = 0; i < state->h; i++) {
|
||||||
draw_arrow(dr, ds, COORD(state->w), COORD(i), 0, +1);
|
draw_arrow(dr, ds, COORD(state->w), COORD(i), 0, +1, 0);
|
||||||
draw_arrow(dr, ds, COORD(0), COORD(i+1), 0, -1);
|
draw_arrow(dr, ds, COORD(0), COORD(i+1), 0, -1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ds->started = TRUE;
|
ds->started = TRUE;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Cursor (highlighted arrow around edge)
|
||||||
|
*/
|
||||||
|
if (ui->cur_visible) {
|
||||||
|
cur_x = ui->cur_x; cur_y = ui->cur_y;
|
||||||
|
}
|
||||||
|
if (cur_x != ds->cur_x || cur_y != ds->cur_y) {
|
||||||
|
/* Cursor has changed; redraw two (prev and curr) arrows. */
|
||||||
|
draw_arrow_for_cursor(dr, ds, cur_x, cur_y, 1);
|
||||||
|
draw_arrow_for_cursor(dr, ds, ds->cur_x, ds->cur_y, 0);
|
||||||
|
ds->cur_x = cur_x; ds->cur_y = cur_y;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now draw each tile.
|
* Now draw each tile.
|
||||||
@ -1054,3 +1126,5 @@ const struct game thegame = {
|
|||||||
FALSE, game_timing_state,
|
FALSE, game_timing_state,
|
||||||
0, /* flags */
|
0, /* flags */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* vim: set shiftwidth=4 tabstop=8: */
|
||||||
|
Reference in New Issue
Block a user