Change of policy on game_changed_state(). Originally, it was called

by the midend every time the game state changed _other_ than as a
result of make_move(), on the basis that when the game state changed
due to make_move() the game backend had probably noticed anyway.
However, when make_move() split up, this became more fiddly: if the
game_ui had to be updated based on some property of the final game
state, then execute_move() couldn't do it because it didn't have a
pointer to the game_ui, but it was fiddly to do it in
interpret_move() because that didn't directly have a copy of the
finished game state to examine. Same Game (the only game to be
affected) had to deal with this by actually having interpret_move()
_call_ execute_move() to construct a temporary new game state,
update the UI, and then throw it away.

So now, game_changed_state() is called _every_ time the current game
state changes, which means that if anything needs doing to the
game_ui as a result of examining the new game state, it can be done
there and save a lot of effort.

[originally from svn r6087]
This commit is contained in:
Simon Tatham
2005-07-10 10:06:04 +00:00
parent ac36314b02
commit 145301d0dc
2 changed files with 13 additions and 17 deletions

View File

@ -491,6 +491,10 @@ static int midend_really_process_key(midend_data *me, int x, int y, int button)
me->states[me->nstates].movetype = MOVE; me->states[me->nstates].movetype = MOVE;
me->statepos = ++me->nstates; me->statepos = ++me->nstates;
me->dir = +1; me->dir = +1;
if (me->ui)
me->ourgame->changed_state(me->ui,
me->states[me->statepos-2].state,
me->states[me->statepos-1].state);
} else { } else {
goto done; goto done;
} }

View File

@ -429,6 +429,14 @@ static void game_changed_state(game_ui *ui, game_state *oldstate,
game_state *newstate) game_state *newstate)
{ {
sel_clear(ui, newstate); sel_clear(ui, newstate);
/*
* If the game state has just changed into an unplayable one
* (either completed or impossible), we vanish the keyboard-
* control cursor.
*/
if (newstate->complete || newstate->impossible)
ui->displaysel = 0;
} }
static char *sel_movedesc(game_ui *ui, game_state *state) static char *sel_movedesc(game_ui *ui, game_state *state)
@ -588,8 +596,6 @@ struct game_drawstate {
int *tiles; /* contains colour and SELECTED. */ int *tiles; /* contains colour and SELECTED. */
}; };
static game_state *execute_move(game_state *from, char *move);
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)
{ {
@ -624,22 +630,8 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
if (ISSEL(ui,tx,ty)) { if (ISSEL(ui,tx,ty)) {
if (button == RIGHT_BUTTON) if (button == RIGHT_BUTTON)
sel_clear(ui, state); sel_clear(ui, state);
else { else
game_state *tmp;
ret = sel_movedesc(ui, state); ret = sel_movedesc(ui, state);
/*
* Unfortunately, we must check for completeness or
* impossibility now, in order to update the game_ui;
* and we can't do that without constructing the new
* grid. Sigh.
*/
tmp = execute_move(state, ret);
if (tmp->complete || tmp->impossible)
ui->displaysel = 0;
free_game(tmp);
}
} else { } else {
sel_clear(ui, state); /* might be no-op */ sel_clear(ui, state); /* might be no-op */
sel_expand(ui, state, tx, ty); sel_expand(ui, state, tx, ty);