Move per-puzzle ad-hoc getenv preferences into game_ui.

Environment variables that set specific settings of particular
puzzles, such as SLANT_SWAP_BUTTONS, LIGHTUP_LIT_BLOBS and
LOOPY_AUTOFOLLOW, now all affect the game behaviour via fields in
game_ui instead of being looked up by getenv in the individual
functions that need to know them.

The purpose of this refactoring is to put those config fields in a
place where other more user-friendly configuration systems will also
be able to access them, once I introduce one. However, for the moment,
there's no functional change: I haven't _yet_ changed how the user
sets those options. They're still set by environment variables alone.
All I'm changing here is where the settings are stored inside the
code, and exactly when they're read out of the environment to put into
the game_ui.

Specifically, the getenvs now happen during new_ui(). Or rather, in
all the puzzles I've changed here, they happen in a subroutine
legacy_prefs_override() called from within new_ui(), after it's set up
the default values for the settings, and then gives the environment a
chance to override them. Or rather, legacy_prefs_override() only
actually calls getenv the first time, and after that, it's cached the
answers it got.

In order to make the override functions less wordy, I've altered the
prototype of getenv_bool so that it returns an int rather than a bool,
and takes its default return value in the same form. That way you can
set the default to something other than 0 or 1, and find out whether a
value was present at all.

This commit only touches environment configuration specific to an
individual puzzle. The midend also has some standard environment-based
config options that apply to all puzzles, such as colour scheme and
default presets and preset-menu extension. I haven't handled those
yet.
This commit is contained in:
Simon Tatham
2023-04-21 15:41:18 +01:00
parent a4fca3286f
commit 0d1a1f08ba
11 changed files with 402 additions and 195 deletions

View File

@ -1159,8 +1159,37 @@ struct game_ui {
* allowed on immutable squares.
*/
bool hcursor;
/*
* User preference option which can be set to FALSE to disable the
* 3D graphical style, and instead just display the puzzle as if
* it was a Sudoku variant, i.e. each square just has a digit in
* it.
*
* I was initially a bit uncertain about whether the 3D style
* would be the right thing, on the basis that it uses up space in
* the cells and makes it hard to use many pencil marks. Actually
* nobody seems to have complained, but having put in the option
* while I was still being uncertain, it seems silly not to leave
* it in just in case.
*/
int three_d;
};
static void legacy_prefs_override(struct game_ui *ui_out)
{
static bool initialised = false;
static int three_d = -1;
if (!initialised) {
initialised = true;
three_d = getenv_bool("TOWERS_2D", -1);
}
if (three_d != -1)
ui_out->three_d = three_d;
}
static game_ui *new_ui(const game_state *state)
{
game_ui *ui = snew(game_ui);
@ -1169,6 +1198,9 @@ static game_ui *new_ui(const game_state *state)
ui->hpencil = false;
ui->hshow = ui->hcursor = getenv_bool("PUZZLES_SHOW_CURSOR", false);
ui->three_d = true;
legacy_prefs_override(ui);
return ui;
}
@ -1224,7 +1256,6 @@ static const char *current_key_label(const game_ui *ui,
struct game_drawstate {
int tilesize;
bool three_d; /* default 3D graphics are user-disableable */
long *tiles; /* (w+2)*(w+2) temp space */
long *drawn; /* (w+2)*(w+2)*4: current drawn data */
bool *errtmp;
@ -1356,7 +1387,7 @@ static char *interpret_move(const game_state *state, game_ui *ui,
tx = FROMCOORD(x);
ty = FROMCOORD(y);
if (ds->three_d) {
if (ui->three_d) {
/*
* In 3D mode, just locating the mouse click in the natural
* square grid may not be sufficient to tell which tower the
@ -1630,7 +1661,6 @@ static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state)
int i;
ds->tilesize = 0;
ds->three_d = !getenv_bool("TOWERS_2D", false);
ds->tiles = snewn((w+2)*(w+2), long);
ds->drawn = snewn((w+2)*(w+2)*4, long);
for (i = 0; i < (w+2)*(w+2)*4; i++)
@ -1648,8 +1678,8 @@ static void game_free_drawstate(drawing *dr, game_drawstate *ds)
sfree(ds);
}
static void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues,
int x, int y, long tile)
static void draw_tile(drawing *dr, game_drawstate *ds, const game_ui *ui,
struct clues *clues, int x, int y, long tile)
{
int w = clues->w /* , a = w*w */;
int tx, ty, bg;
@ -1661,7 +1691,7 @@ static void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues,
bg = (tile & DF_HIGHLIGHT) ? COL_HIGHLIGHT : COL_BACKGROUND;
/* draw tower */
if (ds->three_d && (tile & DF_PLAYAREA) && (tile & DF_DIGIT_MASK)) {
if (ui->three_d && (tile & DF_PLAYAREA) && (tile & DF_DIGIT_MASK)) {
int coords[8];
int xoff = X_3D_DISP(tile & DF_DIGIT_MASK, w);
int yoff = Y_3D_DISP(tile & DF_DIGIT_MASK, w);
@ -1762,10 +1792,10 @@ static void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues,
* to put the pencil marks.
*/
/* Start with the whole square, minus space for impinging towers */
pl = tx + (ds->three_d ? X_3D_DISP(w,w) : 0);
pl = tx + (ui->three_d ? X_3D_DISP(w,w) : 0);
pr = tx + TILESIZE;
pt = ty;
pb = ty + TILESIZE - (ds->three_d ? Y_3D_DISP(w,w) : 0);
pb = ty + TILESIZE - (ui->three_d ? Y_3D_DISP(w,w) : 0);
/*
* We arrange our pencil marks in a grid layout, with
@ -1901,13 +1931,13 @@ static void game_redraw(drawing *dr, game_drawstate *ds,
ds->drawn[i*4+2] != bl || ds->drawn[i*4+3] != br) {
clip(dr, COORD(x-1), COORD(y-1), TILESIZE, TILESIZE);
draw_tile(dr, ds, state->clues, x-1, y-1, tr);
draw_tile(dr, ds, ui, state->clues, x-1, y-1, tr);
if (x > 0)
draw_tile(dr, ds, state->clues, x-2, y-1, tl);
draw_tile(dr, ds, ui, state->clues, x-2, y-1, tl);
if (y <= w)
draw_tile(dr, ds, state->clues, x-1, y, br);
draw_tile(dr, ds, ui, state->clues, x-1, y, br);
if (x > 0 && y <= w)
draw_tile(dr, ds, state->clues, x-2, y, bl);
draw_tile(dr, ds, ui, state->clues, x-2, y, bl);
unclip(dr);
draw_update(dr, COORD(x-1), COORD(y-1), TILESIZE, TILESIZE);