mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 16:05:44 -07:00
Keyboard control for Dominosa (patch largely due to James H, though
with considerable meddling from me). [originally from svn r8788]
This commit is contained in:
88
dominosa.c
88
dominosa.c
@ -951,13 +951,21 @@ static char *game_text_format(game_state *state)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct game_ui {
|
||||||
|
int cur_x, cur_y, 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 = ui->cur_y = 0;
|
||||||
|
ui->cur_visible = 0;
|
||||||
|
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)
|
||||||
@ -972,6 +980,8 @@ static void decode_ui(game_ui *ui, char *encoding)
|
|||||||
static void game_changed_state(game_ui *ui, game_state *oldstate,
|
static void game_changed_state(game_ui *ui, game_state *oldstate,
|
||||||
game_state *newstate)
|
game_state *newstate)
|
||||||
{
|
{
|
||||||
|
if (!oldstate->completed && newstate->completed)
|
||||||
|
ui->cur_visible = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PREFERRED_TILESIZE 32
|
#define PREFERRED_TILESIZE 32
|
||||||
@ -980,6 +990,7 @@ static void game_changed_state(game_ui *ui, game_state *oldstate,
|
|||||||
#define DOMINO_GUTTER (TILESIZE / 16)
|
#define DOMINO_GUTTER (TILESIZE / 16)
|
||||||
#define DOMINO_RADIUS (TILESIZE / 8)
|
#define DOMINO_RADIUS (TILESIZE / 8)
|
||||||
#define DOMINO_COFFSET (DOMINO_GUTTER + DOMINO_RADIUS)
|
#define DOMINO_COFFSET (DOMINO_GUTTER + DOMINO_RADIUS)
|
||||||
|
#define CURSOR_RADIUS (TILESIZE / 4)
|
||||||
|
|
||||||
#define COORD(x) ( (x) * TILESIZE + BORDER )
|
#define COORD(x) ( (x) * TILESIZE + BORDER )
|
||||||
#define FROMCOORD(x) ( ((x) - BORDER + TILESIZE) / TILESIZE - 1 )
|
#define FROMCOORD(x) ( ((x) - BORDER + TILESIZE) / TILESIZE - 1 )
|
||||||
@ -1033,8 +1044,32 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
|
|||||||
(state->grid[d1] != d1 || state->grid[d2] != d2))
|
(state->grid[d1] != d1 || state->grid[d2] != d2))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
ui->cur_visible = 0;
|
||||||
sprintf(buf, "%c%d,%d", (int)(button == RIGHT_BUTTON ? 'E' : 'D'), d1, d2);
|
sprintf(buf, "%c%d,%d", (int)(button == RIGHT_BUTTON ? 'E' : 'D'), d1, d2);
|
||||||
return dupstr(buf);
|
return dupstr(buf);
|
||||||
|
} else if (IS_CURSOR_MOVE(button)) {
|
||||||
|
ui->cur_visible = 1;
|
||||||
|
|
||||||
|
move_cursor(button, &ui->cur_x, &ui->cur_y, 2*w-1, 2*h-1, 0);
|
||||||
|
|
||||||
|
return "";
|
||||||
|
} else if (IS_CURSOR_SELECT(button)) {
|
||||||
|
int d1, d2;
|
||||||
|
|
||||||
|
if (!((ui->cur_x ^ ui->cur_y) & 1))
|
||||||
|
return NULL; /* must have exactly one dimension odd */
|
||||||
|
d1 = (ui->cur_y / 2) * w + (ui->cur_x / 2);
|
||||||
|
d2 = ((ui->cur_y+1) / 2) * w + ((ui->cur_x+1) / 2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We can't mark an edge next to any domino.
|
||||||
|
*/
|
||||||
|
if (button == CURSOR_SELECT2 &&
|
||||||
|
(state->grid[d1] != d1 || state->grid[d2] != d2))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
sprintf(buf, "%c%d,%d", (int)(button == CURSOR_SELECT2 ? 'E' : 'D'), d1, d2);
|
||||||
|
return dupstr(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1275,6 +1310,24 @@ enum {
|
|||||||
TYPE_MASK = 0x0F
|
TYPE_MASK = 0x0F
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* These flags must be disjoint with:
|
||||||
|
* the above enum (TYPE_*) [0x000 -- 0x00F]
|
||||||
|
* EDGE_* [0x100 -- 0xF00]
|
||||||
|
* and must fit into an unsigned long (32 bits).
|
||||||
|
*/
|
||||||
|
#define DF_FLASH 0x40
|
||||||
|
#define DF_CLASH 0x80
|
||||||
|
|
||||||
|
#define DF_CURSOR 0x01000
|
||||||
|
#define DF_CURSOR_USEFUL 0x02000
|
||||||
|
#define DF_CURSOR_XBASE 0x10000
|
||||||
|
#define DF_CURSOR_XMASK 0x30000
|
||||||
|
#define DF_CURSOR_YBASE 0x40000
|
||||||
|
#define DF_CURSOR_YMASK 0xC0000
|
||||||
|
|
||||||
|
#define CEDGE_OFF (TILESIZE / 8)
|
||||||
|
#define IS_EMPTY(s,x,y) ((s)->grid[(y)*(s)->w+(x)] == ((y)*(s)->w+(x)))
|
||||||
|
|
||||||
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 type)
|
int x, int y, int type)
|
||||||
{
|
{
|
||||||
@ -1284,6 +1337,7 @@ static void draw_tile(drawing *dr, game_drawstate *ds, game_state *state,
|
|||||||
char str[80];
|
char str[80];
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
|
clip(dr, cx, cy, TILESIZE, TILESIZE);
|
||||||
draw_rect(dr, cx, cy, TILESIZE, TILESIZE, COL_BACKGROUND);
|
draw_rect(dr, cx, cy, TILESIZE, TILESIZE, COL_BACKGROUND);
|
||||||
|
|
||||||
flags = type &~ TYPE_MASK;
|
flags = type &~ TYPE_MASK;
|
||||||
@ -1300,13 +1354,13 @@ static void draw_tile(drawing *dr, game_drawstate *ds, game_state *state,
|
|||||||
* - a slight shift in the number
|
* - a slight shift in the number
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (flags & 0x80)
|
if (flags & DF_CLASH)
|
||||||
bg = COL_DOMINOCLASH;
|
bg = COL_DOMINOCLASH;
|
||||||
else
|
else
|
||||||
bg = COL_DOMINO;
|
bg = COL_DOMINO;
|
||||||
nc = COL_DOMINOTEXT;
|
nc = COL_DOMINOTEXT;
|
||||||
|
|
||||||
if (flags & 0x40) {
|
if (flags & DF_FLASH) {
|
||||||
int tmp = nc;
|
int tmp = nc;
|
||||||
nc = bg;
|
nc = bg;
|
||||||
bg = tmp;
|
bg = tmp;
|
||||||
@ -1360,11 +1414,23 @@ static void draw_tile(drawing *dr, game_drawstate *ds, game_state *state,
|
|||||||
nc = COL_TEXT;
|
nc = COL_TEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & DF_CURSOR) {
|
||||||
|
int curx = ((flags & DF_CURSOR_XMASK) / DF_CURSOR_XBASE) & 3;
|
||||||
|
int cury = ((flags & DF_CURSOR_YMASK) / DF_CURSOR_YBASE) & 3;
|
||||||
|
int ox = cx + curx*TILESIZE/2;
|
||||||
|
int oy = cy + cury*TILESIZE/2;
|
||||||
|
|
||||||
|
draw_rect_corners(dr, ox, oy, CURSOR_RADIUS, nc);
|
||||||
|
if (flags & DF_CURSOR_USEFUL)
|
||||||
|
draw_rect_corners(dr, ox, oy, CURSOR_RADIUS+1, nc);
|
||||||
|
}
|
||||||
|
|
||||||
sprintf(str, "%d", state->numbers->numbers[y*w+x]);
|
sprintf(str, "%d", state->numbers->numbers[y*w+x]);
|
||||||
draw_text(dr, cx+TILESIZE/2, cy+TILESIZE/2, FONT_VARIABLE, TILESIZE/2,
|
draw_text(dr, cx+TILESIZE/2, cy+TILESIZE/2, FONT_VARIABLE, TILESIZE/2,
|
||||||
ALIGN_HCENTRE | ALIGN_VCENTRE, nc, str);
|
ALIGN_HCENTRE | ALIGN_VCENTRE, nc, str);
|
||||||
|
|
||||||
draw_update(dr, cx, cy, TILESIZE, TILESIZE);
|
draw_update(dr, cx, cy, TILESIZE, TILESIZE);
|
||||||
|
unclip(dr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
|
static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
|
||||||
@ -1425,13 +1491,25 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
|
|||||||
n2 = state->numbers->numbers[state->grid[n]];
|
n2 = state->numbers->numbers[state->grid[n]];
|
||||||
di = DINDEX(n1, n2);
|
di = DINDEX(n1, n2);
|
||||||
if (used[di] > 1)
|
if (used[di] > 1)
|
||||||
c |= 0x80; /* highlight a clash */
|
c |= DF_CLASH; /* highlight a clash */
|
||||||
} else {
|
} else {
|
||||||
c |= state->edges[n];
|
c |= state->edges[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flashtime != 0)
|
if (flashtime != 0)
|
||||||
c |= 0x40; /* we're flashing */
|
c |= DF_FLASH; /* we're flashing */
|
||||||
|
|
||||||
|
if (ui->cur_visible) {
|
||||||
|
unsigned curx = (unsigned)(ui->cur_x - (2*x-1));
|
||||||
|
unsigned cury = (unsigned)(ui->cur_y - (2*y-1));
|
||||||
|
if (curx < 3 && cury < 3) {
|
||||||
|
c |= (DF_CURSOR |
|
||||||
|
(curx * DF_CURSOR_XBASE) |
|
||||||
|
(cury * DF_CURSOR_YBASE));
|
||||||
|
if ((ui->cur_x ^ ui->cur_y) & 1)
|
||||||
|
c |= DF_CURSOR_USEFUL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ds->visible[n] != c) {
|
if (ds->visible[n] != c) {
|
||||||
draw_tile(dr, ds, state, x, y, c);
|
draw_tile(dr, ds, state, x, y, c);
|
||||||
|
12
misc.c
12
misc.c
@ -244,6 +244,18 @@ void draw_rect_outline(drawing *dr, int x, int y, int w, int h, int colour)
|
|||||||
draw_polygon(dr, coords, 4, -1, colour);
|
draw_polygon(dr, coords, 4, -1, colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void draw_rect_corners(drawing *dr, int cx, int cy, int r, int col)
|
||||||
|
{
|
||||||
|
draw_line(dr, cx - r, cy - r, cx - r, cy - r/2, col);
|
||||||
|
draw_line(dr, cx - r, cy - r, cx - r/2, cy - r, col);
|
||||||
|
draw_line(dr, cx - r, cy + r, cx - r, cy + r/2, col);
|
||||||
|
draw_line(dr, cx - r, cy + r, cx - r/2, cy + r, col);
|
||||||
|
draw_line(dr, cx + r, cy - r, cx + r, cy - r/2, col);
|
||||||
|
draw_line(dr, cx + r, cy - r, cx + r/2, cy - r, col);
|
||||||
|
draw_line(dr, cx + r, cy + r, cx + r, cy + r/2, col);
|
||||||
|
draw_line(dr, cx + r, cy + r, cx + r/2, cy + r, col);
|
||||||
|
}
|
||||||
|
|
||||||
void move_cursor(int button, int *x, int *y, int maxw, int maxh, int wrap)
|
void move_cursor(int button, int *x, int *y, int maxw, int maxh, int wrap)
|
||||||
{
|
{
|
||||||
int dx = 0, dy = 0;
|
int dx = 0, dy = 0;
|
||||||
|
@ -1440,6 +1440,12 @@ them, which you can use to remind yourself that you know those two
|
|||||||
numbers are \e{not} covered by a single domino. Right-clicking again
|
numbers are \e{not} covered by a single domino. Right-clicking again
|
||||||
removes the line.
|
removes the line.
|
||||||
|
|
||||||
|
You can also use the cursor keys to move a cursor around the grid.
|
||||||
|
When the cursor is half way between two adjacent numbers, pressing
|
||||||
|
the return key will place a domino covering those numbers, or
|
||||||
|
pressing the space bar will lay a line between the two squares.
|
||||||
|
Repeating either action removes the domino or line.
|
||||||
|
|
||||||
(All the actions described in \k{common-actions} are also available.)
|
(All the actions described in \k{common-actions} are also available.)
|
||||||
|
|
||||||
\H{dominosa-parameters} \I{parameters, for Dominosa}Dominosa parameters
|
\H{dominosa-parameters} \I{parameters, for Dominosa}Dominosa parameters
|
||||||
|
@ -303,6 +303,9 @@ void shuffle(void *array, int nelts, int eltsize, random_state *rs);
|
|||||||
void draw_rect_outline(drawing *dr, int x, int y, int w, int h,
|
void draw_rect_outline(drawing *dr, int x, int y, int w, int h,
|
||||||
int colour);
|
int colour);
|
||||||
|
|
||||||
|
/* Draw a set of rectangle corners (e.g. for a cursor display). */
|
||||||
|
void draw_rect_corners(drawing *dr, int cx, int cy, int r, int col);
|
||||||
|
|
||||||
void move_cursor(int button, int *x, int *y, int maxw, int maxh, int wrap);
|
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. */
|
||||||
|
Reference in New Issue
Block a user