mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 08:01:30 -07:00
Substantial infrastructure upheaval. I've separated the drawing API
as seen by the back ends from the one implemented by the front end, and shoved a piece of middleware (drawing.c) in between to permit interchange of multiple kinds of the latter. I've also added a number of functions to the drawing API to permit printing as well as on-screen drawing, and retired print.py in favour of integrated printing done by means of that API. The immediate visible change is that print.py is dead, and each puzzle now does its own printing: where you would previously have typed `print.py solo 2x3', you now type `solo --print 2x3' and it should work in much the same way. Advantages of the new mechanism available right now: - Map is now printable, because the new print function can make use of the output from the existing game ID decoder rather than me having to replicate all those fiddly algorithms in Python. - the new print functions can cope with non-initial game states, which means each puzzle supporting --print also supports --with-solutions. - there's also a --scale option permitting users to adjust the size of the printed puzzles. Advantages which will be available at some point: - the new API should permit me to implement native printing mechanisms on Windows and OS X. [originally from svn r6190]
This commit is contained in:
258
net.c
258
net.c
@ -1517,7 +1517,7 @@ static char *validate_desc(game_params *params, char *desc)
|
||||
* Construct an initial game state, given a description and parameters.
|
||||
*/
|
||||
|
||||
static game_state *new_game(midend_data *me, game_params *params, char *desc)
|
||||
static game_state *new_game(midend *me, game_params *params, char *desc)
|
||||
{
|
||||
game_state *state;
|
||||
int w, h, x, y;
|
||||
@ -1660,6 +1660,8 @@ static char *solve_game(game_state *state, game_state *currstate,
|
||||
tiles[i] = c - 'a' + 10;
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
tiles[i] = c - 'A' + 10;
|
||||
|
||||
tiles[i] |= LOCKED;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2109,7 +2111,7 @@ static game_state *execute_move(game_state *from, char *move)
|
||||
* Routines for drawing the game position on the screen.
|
||||
*/
|
||||
|
||||
static game_drawstate *game_new_drawstate(game_state *state)
|
||||
static game_drawstate *game_new_drawstate(drawing *dr, game_state *state)
|
||||
{
|
||||
game_drawstate *ds = snew(game_drawstate);
|
||||
|
||||
@ -2124,7 +2126,7 @@ static game_drawstate *game_new_drawstate(game_state *state)
|
||||
return ds;
|
||||
}
|
||||
|
||||
static void game_free_drawstate(game_drawstate *ds)
|
||||
static void game_free_drawstate(drawing *dr, game_drawstate *ds)
|
||||
{
|
||||
sfree(ds->visible);
|
||||
sfree(ds);
|
||||
@ -2137,8 +2139,8 @@ static void game_compute_size(game_params *params, int tilesize,
|
||||
*y = WINDOW_OFFSET * 2 + tilesize * params->height + TILE_BORDER;
|
||||
}
|
||||
|
||||
static void game_set_size(game_drawstate *ds, game_params *params,
|
||||
int tilesize)
|
||||
static void game_set_size(drawing *dr, game_drawstate *ds,
|
||||
game_params *params, int tilesize)
|
||||
{
|
||||
ds->tilesize = tilesize;
|
||||
}
|
||||
@ -2201,17 +2203,17 @@ static float *game_colours(frontend *fe, game_state *state, int *ncolours)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void draw_thick_line(frontend *fe, int x1, int y1, int x2, int y2,
|
||||
static void draw_thick_line(drawing *dr, int x1, int y1, int x2, int y2,
|
||||
int colour)
|
||||
{
|
||||
draw_line(fe, x1-1, y1, x2-1, y2, COL_WIRE);
|
||||
draw_line(fe, x1+1, y1, x2+1, y2, COL_WIRE);
|
||||
draw_line(fe, x1, y1-1, x2, y2-1, COL_WIRE);
|
||||
draw_line(fe, x1, y1+1, x2, y2+1, COL_WIRE);
|
||||
draw_line(fe, x1, y1, x2, y2, colour);
|
||||
draw_line(dr, x1-1, y1, x2-1, y2, COL_WIRE);
|
||||
draw_line(dr, x1+1, y1, x2+1, y2, COL_WIRE);
|
||||
draw_line(dr, x1, y1-1, x2, y2-1, COL_WIRE);
|
||||
draw_line(dr, x1, y1+1, x2, y2+1, COL_WIRE);
|
||||
draw_line(dr, x1, y1, x2, y2, colour);
|
||||
}
|
||||
|
||||
static void draw_rect_coords(frontend *fe, int x1, int y1, int x2, int y2,
|
||||
static void draw_rect_coords(drawing *dr, int x1, int y1, int x2, int y2,
|
||||
int colour)
|
||||
{
|
||||
int mx = (x1 < x2 ? x1 : x2);
|
||||
@ -2219,13 +2221,13 @@ static void draw_rect_coords(frontend *fe, int x1, int y1, int x2, int y2,
|
||||
int dx = (x2 + x1 - 2*mx + 1);
|
||||
int dy = (y2 + y1 - 2*my + 1);
|
||||
|
||||
draw_rect(fe, mx, my, dx, dy, colour);
|
||||
draw_rect(dr, mx, my, dx, dy, colour);
|
||||
}
|
||||
|
||||
/*
|
||||
* draw_barrier_corner() and draw_barrier() are passed physical coords
|
||||
*/
|
||||
static void draw_barrier_corner(frontend *fe, game_drawstate *ds,
|
||||
static void draw_barrier_corner(drawing *dr, game_drawstate *ds,
|
||||
int x, int y, int dx, int dy, int phase)
|
||||
{
|
||||
int bx = WINDOW_OFFSET + TILE_SIZE * x;
|
||||
@ -2236,20 +2238,20 @@ static void draw_barrier_corner(frontend *fe, game_drawstate *ds,
|
||||
y1 = (dy > 0 ? TILE_SIZE+TILE_BORDER-1 : 0);
|
||||
|
||||
if (phase == 0) {
|
||||
draw_rect_coords(fe, bx+x1+dx, by+y1,
|
||||
draw_rect_coords(dr, bx+x1+dx, by+y1,
|
||||
bx+x1-TILE_BORDER*dx, by+y1-(TILE_BORDER-1)*dy,
|
||||
COL_WIRE);
|
||||
draw_rect_coords(fe, bx+x1, by+y1+dy,
|
||||
draw_rect_coords(dr, bx+x1, by+y1+dy,
|
||||
bx+x1-(TILE_BORDER-1)*dx, by+y1-TILE_BORDER*dy,
|
||||
COL_WIRE);
|
||||
} else {
|
||||
draw_rect_coords(fe, bx+x1, by+y1,
|
||||
draw_rect_coords(dr, bx+x1, by+y1,
|
||||
bx+x1-(TILE_BORDER-1)*dx, by+y1-(TILE_BORDER-1)*dy,
|
||||
COL_BARRIER);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_barrier(frontend *fe, game_drawstate *ds,
|
||||
static void draw_barrier(drawing *dr, game_drawstate *ds,
|
||||
int x, int y, int dir, int phase)
|
||||
{
|
||||
int bx = WINDOW_OFFSET + TILE_SIZE * x;
|
||||
@ -2262,16 +2264,16 @@ static void draw_barrier(frontend *fe, game_drawstate *ds,
|
||||
h = (Y(dir) ? TILE_BORDER : TILE_SIZE - TILE_BORDER);
|
||||
|
||||
if (phase == 0) {
|
||||
draw_rect(fe, bx+x1-X(dir), by+y1-Y(dir), w, h, COL_WIRE);
|
||||
draw_rect(dr, bx+x1-X(dir), by+y1-Y(dir), w, h, COL_WIRE);
|
||||
} else {
|
||||
draw_rect(fe, bx+x1, by+y1, w, h, COL_BARRIER);
|
||||
draw_rect(dr, bx+x1, by+y1, w, h, COL_BARRIER);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* draw_tile() is passed physical coordinates
|
||||
*/
|
||||
static void draw_tile(frontend *fe, game_state *state, game_drawstate *ds,
|
||||
static void draw_tile(drawing *dr, game_state *state, game_drawstate *ds,
|
||||
int x, int y, int tile, int src, float angle, int cursor)
|
||||
{
|
||||
int bx = WINDOW_OFFSET + TILE_SIZE * x;
|
||||
@ -2287,16 +2289,16 @@ static void draw_tile(frontend *fe, game_state *state, game_drawstate *ds,
|
||||
* we must draw those connections on the borders themselves.
|
||||
*/
|
||||
|
||||
clip(fe, bx, by, TILE_SIZE+TILE_BORDER, TILE_SIZE+TILE_BORDER);
|
||||
clip(dr, bx, by, TILE_SIZE+TILE_BORDER, TILE_SIZE+TILE_BORDER);
|
||||
|
||||
/*
|
||||
* So. First blank the tile out completely: draw a big
|
||||
* rectangle in border colour, and a smaller rectangle in
|
||||
* background colour to fill it in.
|
||||
*/
|
||||
draw_rect(fe, bx, by, TILE_SIZE+TILE_BORDER, TILE_SIZE+TILE_BORDER,
|
||||
draw_rect(dr, bx, by, TILE_SIZE+TILE_BORDER, TILE_SIZE+TILE_BORDER,
|
||||
COL_BORDER);
|
||||
draw_rect(fe, bx+TILE_BORDER, by+TILE_BORDER,
|
||||
draw_rect(dr, bx+TILE_BORDER, by+TILE_BORDER,
|
||||
TILE_SIZE-TILE_BORDER, TILE_SIZE-TILE_BORDER,
|
||||
tile & LOCKED ? COL_LOCKED : COL_BACKGROUND);
|
||||
|
||||
@ -2306,16 +2308,16 @@ static void draw_tile(frontend *fe, game_state *state, game_drawstate *ds,
|
||||
* in.
|
||||
*/
|
||||
if (cursor) {
|
||||
draw_line(fe, bx+TILE_SIZE/8, by+TILE_SIZE/8,
|
||||
draw_line(dr, bx+TILE_SIZE/8, by+TILE_SIZE/8,
|
||||
bx+TILE_SIZE/8, by+TILE_SIZE-TILE_SIZE/8,
|
||||
tile & LOCKED ? COL_BACKGROUND : COL_LOCKED);
|
||||
draw_line(fe, bx+TILE_SIZE/8, by+TILE_SIZE/8,
|
||||
draw_line(dr, bx+TILE_SIZE/8, by+TILE_SIZE/8,
|
||||
bx+TILE_SIZE-TILE_SIZE/8, by+TILE_SIZE/8,
|
||||
tile & LOCKED ? COL_BACKGROUND : COL_LOCKED);
|
||||
draw_line(fe, bx+TILE_SIZE-TILE_SIZE/8, by+TILE_SIZE/8,
|
||||
draw_line(dr, bx+TILE_SIZE-TILE_SIZE/8, by+TILE_SIZE/8,
|
||||
bx+TILE_SIZE-TILE_SIZE/8, by+TILE_SIZE-TILE_SIZE/8,
|
||||
tile & LOCKED ? COL_BACKGROUND : COL_LOCKED);
|
||||
draw_line(fe, bx+TILE_SIZE/8, by+TILE_SIZE-TILE_SIZE/8,
|
||||
draw_line(dr, bx+TILE_SIZE/8, by+TILE_SIZE-TILE_SIZE/8,
|
||||
bx+TILE_SIZE-TILE_SIZE/8, by+TILE_SIZE-TILE_SIZE/8,
|
||||
tile & LOCKED ? COL_BACKGROUND : COL_LOCKED);
|
||||
}
|
||||
@ -2338,7 +2340,7 @@ static void draw_tile(frontend *fe, game_state *state, game_drawstate *ds,
|
||||
ex = (TILE_SIZE - TILE_BORDER - 1.0F) / 2.0F * X(dir);
|
||||
ey = (TILE_SIZE - TILE_BORDER - 1.0F) / 2.0F * Y(dir);
|
||||
MATMUL(tx, ty, matrix, ex, ey);
|
||||
draw_thick_line(fe, bx+(int)cx, by+(int)cy,
|
||||
draw_thick_line(dr, bx+(int)cx, by+(int)cy,
|
||||
bx+(int)(cx+tx), by+(int)(cy+ty),
|
||||
COL_WIRE);
|
||||
}
|
||||
@ -2348,7 +2350,7 @@ static void draw_tile(frontend *fe, game_state *state, game_drawstate *ds,
|
||||
ex = (TILE_SIZE - TILE_BORDER - 1.0F) / 2.0F * X(dir);
|
||||
ey = (TILE_SIZE - TILE_BORDER - 1.0F) / 2.0F * Y(dir);
|
||||
MATMUL(tx, ty, matrix, ex, ey);
|
||||
draw_line(fe, bx+(int)cx, by+(int)cy,
|
||||
draw_line(dr, bx+(int)cx, by+(int)cy,
|
||||
bx+(int)(cx+tx), by+(int)(cy+ty), col);
|
||||
}
|
||||
}
|
||||
@ -2381,7 +2383,7 @@ static void draw_tile(frontend *fe, game_state *state, game_drawstate *ds,
|
||||
points[i+1] = by+(int)(cy+ty);
|
||||
}
|
||||
|
||||
draw_polygon(fe, points, 4, col, COL_WIRE);
|
||||
draw_polygon(dr, points, 4, col, COL_WIRE);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2418,8 +2420,8 @@ static void draw_tile(frontend *fe, game_state *state, game_drawstate *ds,
|
||||
* in: if we are fully connected to the other tile then
|
||||
* the two ACTIVE states will be the same.)
|
||||
*/
|
||||
draw_rect_coords(fe, px-vx, py-vy, px+lx+vx, py+ly+vy, COL_WIRE);
|
||||
draw_rect_coords(fe, px, py, px+lx, py+ly,
|
||||
draw_rect_coords(dr, px-vx, py-vy, px+lx+vx, py+ly+vy, COL_WIRE);
|
||||
draw_rect_coords(dr, px, py, px+lx, py+ly,
|
||||
(tile & ACTIVE) ? COL_POWERED : COL_WIRE);
|
||||
} else {
|
||||
/*
|
||||
@ -2427,7 +2429,7 @@ static void draw_tile(frontend *fe, game_state *state, game_drawstate *ds,
|
||||
* actually connected to us. Just draw a single black
|
||||
* dot.
|
||||
*/
|
||||
draw_rect_coords(fe, px, py, px, py, COL_WIRE);
|
||||
draw_rect_coords(dr, px, py, px, py, COL_WIRE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2471,7 +2473,7 @@ static void draw_tile(frontend *fe, game_state *state, game_drawstate *ds,
|
||||
* At least one barrier terminates here. Draw a
|
||||
* corner.
|
||||
*/
|
||||
draw_barrier_corner(fe, ds, x, y,
|
||||
draw_barrier_corner(dr, ds, x, y,
|
||||
X(dir)+X(A(dir)), Y(dir)+Y(A(dir)),
|
||||
phase);
|
||||
}
|
||||
@ -2479,15 +2481,15 @@ static void draw_tile(frontend *fe, game_state *state, game_drawstate *ds,
|
||||
|
||||
for (dir = 1; dir < 0x10; dir <<= 1)
|
||||
if (barrier(state, GX(x), GY(y)) & dir)
|
||||
draw_barrier(fe, ds, x, y, dir, phase);
|
||||
draw_barrier(dr, ds, x, y, dir, phase);
|
||||
}
|
||||
|
||||
unclip(fe);
|
||||
unclip(dr);
|
||||
|
||||
draw_update(fe, bx, by, TILE_SIZE+TILE_BORDER, TILE_SIZE+TILE_BORDER);
|
||||
draw_update(dr, bx, by, TILE_SIZE+TILE_BORDER, TILE_SIZE+TILE_BORDER);
|
||||
}
|
||||
|
||||
static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
|
||||
static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
|
||||
game_state *state, int dir, game_ui *ui, float t, float ft)
|
||||
{
|
||||
int x, y, tx, ty, frame, last_rotate_dir, moved_origin = FALSE;
|
||||
@ -2503,7 +2505,7 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
|
||||
|
||||
ds->started = TRUE;
|
||||
|
||||
draw_rect(fe, 0, 0,
|
||||
draw_rect(dr, 0, 0,
|
||||
WINDOW_OFFSET * 2 + TILE_SIZE * state->width + TILE_BORDER,
|
||||
WINDOW_OFFSET * 2 + TILE_SIZE * state->height + TILE_BORDER,
|
||||
COL_BACKGROUND);
|
||||
@ -2512,7 +2514,7 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
|
||||
ds->org_y = ui->org_y;
|
||||
moved_origin = TRUE;
|
||||
|
||||
draw_update(fe, 0, 0,
|
||||
draw_update(dr, 0, 0,
|
||||
WINDOW_OFFSET*2 + TILE_SIZE*state->width + TILE_BORDER,
|
||||
WINDOW_OFFSET*2 + TILE_SIZE*state->height + TILE_BORDER);
|
||||
|
||||
@ -2521,38 +2523,38 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
|
||||
for (x = 0; x < ds->width; x++) {
|
||||
if (x+1 < ds->width) {
|
||||
if (barrier(state, GX(x), GY(0)) & R)
|
||||
draw_barrier_corner(fe, ds, x, -1, +1, +1, phase);
|
||||
draw_barrier_corner(dr, ds, x, -1, +1, +1, phase);
|
||||
if (barrier(state, GX(x), GY(ds->height-1)) & R)
|
||||
draw_barrier_corner(fe, ds, x, ds->height, +1, -1, phase);
|
||||
draw_barrier_corner(dr, ds, x, ds->height, +1, -1, phase);
|
||||
}
|
||||
if (barrier(state, GX(x), GY(0)) & U) {
|
||||
draw_barrier_corner(fe, ds, x, -1, -1, +1, phase);
|
||||
draw_barrier_corner(fe, ds, x, -1, +1, +1, phase);
|
||||
draw_barrier(fe, ds, x, -1, D, phase);
|
||||
draw_barrier_corner(dr, ds, x, -1, -1, +1, phase);
|
||||
draw_barrier_corner(dr, ds, x, -1, +1, +1, phase);
|
||||
draw_barrier(dr, ds, x, -1, D, phase);
|
||||
}
|
||||
if (barrier(state, GX(x), GY(ds->height-1)) & D) {
|
||||
draw_barrier_corner(fe, ds, x, ds->height, -1, -1, phase);
|
||||
draw_barrier_corner(fe, ds, x, ds->height, +1, -1, phase);
|
||||
draw_barrier(fe, ds, x, ds->height, U, phase);
|
||||
draw_barrier_corner(dr, ds, x, ds->height, -1, -1, phase);
|
||||
draw_barrier_corner(dr, ds, x, ds->height, +1, -1, phase);
|
||||
draw_barrier(dr, ds, x, ds->height, U, phase);
|
||||
}
|
||||
}
|
||||
|
||||
for (y = 0; y < ds->height; y++) {
|
||||
if (y+1 < ds->height) {
|
||||
if (barrier(state, GX(0), GY(y)) & D)
|
||||
draw_barrier_corner(fe, ds, -1, y, +1, +1, phase);
|
||||
draw_barrier_corner(dr, ds, -1, y, +1, +1, phase);
|
||||
if (barrier(state, GX(ds->width-1), GY(y)) & D)
|
||||
draw_barrier_corner(fe, ds, ds->width, y, -1, +1, phase);
|
||||
draw_barrier_corner(dr, ds, ds->width, y, -1, +1, phase);
|
||||
}
|
||||
if (barrier(state, GX(0), GY(y)) & L) {
|
||||
draw_barrier_corner(fe, ds, -1, y, +1, -1, phase);
|
||||
draw_barrier_corner(fe, ds, -1, y, +1, +1, phase);
|
||||
draw_barrier(fe, ds, -1, y, R, phase);
|
||||
draw_barrier_corner(dr, ds, -1, y, +1, -1, phase);
|
||||
draw_barrier_corner(dr, ds, -1, y, +1, +1, phase);
|
||||
draw_barrier(dr, ds, -1, y, R, phase);
|
||||
}
|
||||
if (barrier(state, GX(ds->width-1), GY(y)) & R) {
|
||||
draw_barrier_corner(fe, ds, ds->width, y, -1, -1, phase);
|
||||
draw_barrier_corner(fe, ds, ds->width, y, -1, +1, phase);
|
||||
draw_barrier(fe, ds, ds->width, y, L, phase);
|
||||
draw_barrier_corner(dr, ds, ds->width, y, -1, -1, phase);
|
||||
draw_barrier_corner(dr, ds, ds->width, y, -1, +1, phase);
|
||||
draw_barrier(dr, ds, ds->width, y, L, phase);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2618,7 +2620,7 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
|
||||
index(state, ds->visible, x, y) != c ||
|
||||
index(state, ds->visible, x, y) == 0xFF ||
|
||||
is_src || is_anim || is_cursor) {
|
||||
draw_tile(fe, state, ds, x, y, c,
|
||||
draw_tile(dr, state, ds, x, y, c,
|
||||
is_src, (is_anim ? angle : 0.0F), is_cursor);
|
||||
if (is_src || is_anim || is_cursor)
|
||||
index(state, ds->visible, x, y) = 0xFF;
|
||||
@ -2646,7 +2648,7 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
|
||||
(state->used_solve ? "Auto-solved. " :
|
||||
state->completed ? "COMPLETED! " : ""), a, n2);
|
||||
|
||||
status_bar(fe, statusbuf);
|
||||
status_bar(dr, statusbuf);
|
||||
}
|
||||
|
||||
sfree(active);
|
||||
@ -2705,6 +2707,143 @@ static int game_timing_state(game_state *state, game_ui *ui)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void game_print_size(game_params *params, float *x, float *y)
|
||||
{
|
||||
int pw, ph;
|
||||
|
||||
/*
|
||||
* I'll use 8mm squares by default.
|
||||
*/
|
||||
game_compute_size(params, 800, &pw, &ph);
|
||||
*x = pw / 100.0;
|
||||
*y = ph / 100.0;
|
||||
}
|
||||
|
||||
static void draw_diagram(drawing *dr, game_drawstate *ds, int x, int y,
|
||||
int topleft, int v, int drawlines, int ink)
|
||||
{
|
||||
int tx, ty, cx, cy, r, br, k, thick;
|
||||
|
||||
tx = WINDOW_OFFSET + TILE_SIZE * x;
|
||||
ty = WINDOW_OFFSET + TILE_SIZE * y;
|
||||
|
||||
/*
|
||||
* Find our centre point.
|
||||
*/
|
||||
if (topleft) {
|
||||
cx = tx + (v & L ? TILE_SIZE / 4 : TILE_SIZE / 6);
|
||||
cy = ty + (v & U ? TILE_SIZE / 4 : TILE_SIZE / 6);
|
||||
r = TILE_SIZE / 8;
|
||||
br = TILE_SIZE / 32;
|
||||
} else {
|
||||
cx = tx + TILE_SIZE / 2;
|
||||
cy = ty + TILE_SIZE / 2;
|
||||
r = TILE_SIZE / 2;
|
||||
br = TILE_SIZE / 8;
|
||||
}
|
||||
thick = r / 20;
|
||||
|
||||
/*
|
||||
* Draw the square block if we have an endpoint.
|
||||
*/
|
||||
if (v == 1 || v == 2 || v == 4 || v == 8)
|
||||
draw_rect(dr, cx - br, cy - br, br*2, br*2, ink);
|
||||
|
||||
/*
|
||||
* Draw each radial line.
|
||||
*/
|
||||
if (drawlines) {
|
||||
print_line_width(dr, thick * 2);
|
||||
for (k = 1; k < 16; k *= 2)
|
||||
if (v & k) {
|
||||
int x1 = min(cx, cx + (r-thick) * X(k));
|
||||
int x2 = max(cx, cx + (r-thick) * X(k));
|
||||
int y1 = min(cy, cy + (r-thick) * Y(k));
|
||||
int y2 = max(cy, cy + (r-thick) * Y(k));
|
||||
draw_rect(dr, x1 - thick, y1 - thick,
|
||||
(x2 - x1) + 2*thick, (y2 - y1) + 2*thick, ink);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void game_print(drawing *dr, game_state *state, int tilesize)
|
||||
{
|
||||
int w = state->width, h = state->height;
|
||||
int ink = print_mono_colour(dr, 0);
|
||||
int x, y;
|
||||
|
||||
/* Ick: fake up `ds->tilesize' for macro expansion purposes */
|
||||
game_drawstate ads, *ds = &ads;
|
||||
ads.tilesize = tilesize;
|
||||
|
||||
/*
|
||||
* Border.
|
||||
*/
|
||||
print_line_width(dr, TILE_SIZE / (state->wrapping ? 128 : 12));
|
||||
draw_rect_outline(dr, WINDOW_OFFSET, WINDOW_OFFSET,
|
||||
TILE_SIZE * w, TILE_SIZE * h, ink);
|
||||
|
||||
/*
|
||||
* Grid.
|
||||
*/
|
||||
print_line_width(dr, TILE_SIZE / 128);
|
||||
for (x = 1; x < w; x++)
|
||||
draw_line(dr, WINDOW_OFFSET + TILE_SIZE * x, WINDOW_OFFSET,
|
||||
WINDOW_OFFSET + TILE_SIZE * x, WINDOW_OFFSET + TILE_SIZE * h,
|
||||
ink);
|
||||
for (y = 1; y < h; y++)
|
||||
draw_line(dr, WINDOW_OFFSET, WINDOW_OFFSET + TILE_SIZE * y,
|
||||
WINDOW_OFFSET + TILE_SIZE * w, WINDOW_OFFSET + TILE_SIZE * y,
|
||||
ink);
|
||||
|
||||
/*
|
||||
* Barriers.
|
||||
*/
|
||||
for (y = 0; y <= h; y++)
|
||||
for (x = 0; x <= w; x++) {
|
||||
int b = barrier(state, x % w, y % h);
|
||||
fprintf(stderr, "%d,%d: %d\n", x, y, b);
|
||||
if (x < w && (b & U))
|
||||
draw_rect(dr, WINDOW_OFFSET + TILE_SIZE * x - TILE_SIZE/24,
|
||||
WINDOW_OFFSET + TILE_SIZE * y - TILE_SIZE/24,
|
||||
TILE_SIZE + TILE_SIZE/24 * 2, TILE_SIZE/24 * 2, ink);
|
||||
if (y < h && (b & L))
|
||||
draw_rect(dr, WINDOW_OFFSET + TILE_SIZE * x - TILE_SIZE/24,
|
||||
WINDOW_OFFSET + TILE_SIZE * y - TILE_SIZE/24,
|
||||
TILE_SIZE/24 * 2, TILE_SIZE + TILE_SIZE/24 * 2, ink);
|
||||
}
|
||||
|
||||
/*
|
||||
* Grid contents.
|
||||
*/
|
||||
for (y = 0; y < h; y++)
|
||||
for (x = 0; x < w; x++) {
|
||||
int vx, v = tile(state, x, y);
|
||||
int locked = v & LOCKED;
|
||||
|
||||
v &= 0xF;
|
||||
|
||||
/*
|
||||
* Rotate into a standard orientation for the top left
|
||||
* corner diagram.
|
||||
*/
|
||||
vx = v;
|
||||
while (vx != 0 && vx != 15 && vx != 1 && vx != 9 && vx != 13 &&
|
||||
vx != 5)
|
||||
vx = A(vx);
|
||||
|
||||
/*
|
||||
* Draw the top left corner diagram.
|
||||
*/
|
||||
draw_diagram(dr, ds, x, y, TRUE, vx, TRUE, ink);
|
||||
|
||||
/*
|
||||
* Draw the real solution diagram, if we're doing so.
|
||||
*/
|
||||
draw_diagram(dr, ds, x, y, FALSE, v, locked, ink);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef COMBINED
|
||||
#define thegame net
|
||||
#endif
|
||||
@ -2740,6 +2879,7 @@ const struct game thegame = {
|
||||
game_redraw,
|
||||
game_anim_length,
|
||||
game_flash_length,
|
||||
TRUE, FALSE, game_print_size, game_print,
|
||||
game_wants_statusbar,
|
||||
FALSE, game_timing_state,
|
||||
0, /* mouse_priorities */
|
||||
|
Reference in New Issue
Block a user