return TRUE;
}
+static int game_timing_state(game_state *state)
+{
+ return TRUE;
+}
+
#ifdef COMBINED
#define thegame cube
#endif
game_anim_length,
game_flash_length,
game_wants_statusbar,
+ FALSE, game_timing_state,
};
return TRUE;
}
+static int game_timing_state(game_state *state)
+{
+ return TRUE;
+}
+
#ifdef COMBINED
#define thegame fifteen
#endif
game_anim_length,
game_flash_length,
game_wants_statusbar,
+ FALSE, game_timing_state,
};
void status_bar(frontend *fe, char *text)
{
+ char *rewritten;
+
assert(fe->statusbar);
+ rewritten = midend_rewrite_statusbar(fe->me, text);
gtk_statusbar_pop(GTK_STATUSBAR(fe->statusbar), fe->statusctx);
- gtk_statusbar_push(GTK_STATUSBAR(fe->statusbar), fe->statusctx, text);
+ gtk_statusbar_push(GTK_STATUSBAR(fe->statusbar), fe->statusctx, rewritten);
+ sfree(rewritten);
}
void start_draw(frontend *fe)
float flash_time, flash_pos;
int dir;
+ int timing;
+ float elapsed;
+ char *laststatus;
+
int pressed_mouse_button;
};
me->dir = 0;
me->ui = NULL;
me->pressed_mouse_button = 0;
+ me->laststatus = NULL;
+ me->timing = FALSE;
+ me->elapsed = 0.0F;
sfree(randseed);
me->ourgame->free_params(me->params);
if (me->curparams)
me->ourgame->free_params(me->curparams);
+ sfree(me->laststatus);
sfree(me);
}
me->params = me->ourgame->dup_params(params);
}
+static void midend_set_timer(midend_data *me)
+{
+ me->timing = (me->ourgame->is_timed &&
+ me->ourgame->timing_state(me->states[me->statepos-1].state));
+ if (me->timing || me->flash_time || me->anim_time)
+ activate_timer(me->frontend);
+ else
+ deactivate_timer(me->frontend);
+}
+
void midend_new_game(midend_data *me)
{
while (me->nstates > 0)
me->nstates++;
me->statepos = 1;
me->drawstate = me->ourgame->new_drawstate(me->states[0].state);
+ me->elapsed = 0.0F;
+ midend_set_timer(me);
if (me->ui)
me->ourgame->free_ui(me->ui);
me->ui = me->ourgame->new_ui(me->states[0].state);
me->anim_pos = me->anim_time = 0;
me->dir = 0;
- if (me->flash_time == 0 && me->anim_time == 0)
- deactivate_timer(me->frontend);
- else
- activate_timer(me->frontend);
+ midend_set_timer(me);
}
static void midend_stop_anim(midend_data *me)
me->anim_time = 0.0;
midend_finish_move(me);
midend_redraw(me);
- activate_timer(me->frontend);
+ midend_set_timer(me);
}
static int midend_really_process_key(midend_data *me, int x, int y, int button)
midend_redraw(me);
- activate_timer(me->frontend);
+ midend_set_timer(me);
return 1;
}
if (me->anim_time > 0)
midend_finish_move(me);
}
+
me->flash_pos += tplus;
if (me->flash_pos >= me->flash_time || me->flash_time == 0) {
me->flash_pos = me->flash_time = 0;
}
- if (me->flash_time == 0 && me->anim_time == 0)
- deactivate_timer(me->frontend);
+
midend_redraw(me);
+
+ if (me->timing) {
+ float oldelapsed = me->elapsed;
+ me->elapsed += tplus;
+ if ((int)oldelapsed != (int)me->elapsed)
+ status_bar(me->frontend, me->laststatus ? me->laststatus : "");
+ }
+
+ midend_set_timer(me);
}
float *midend_colours(midend_data *me, int *ncolours)
me->anim_time = 0.0;
midend_finish_move(me);
midend_redraw(me);
- activate_timer(me->frontend);
+ midend_set_timer(me);
return NULL;
}
+
+char *midend_rewrite_statusbar(midend_data *me, char *text)
+{
+ /*
+ * An important special case is that we are occasionally called
+ * with our own laststatus, to update the timer.
+ */
+ if (me->laststatus != text) {
+ sfree(me->laststatus);
+ me->laststatus = dupstr(text);
+ }
+
+ if (me->ourgame->is_timed) {
+ char timebuf[100], *ret;
+ int min, sec;
+
+ sec = me->elapsed;
+ min = sec / 60;
+ sec %= 60;
+ sprintf(timebuf, "[%d:%02d] ", min, sec);
+
+ ret = snewn(strlen(timebuf) + strlen(text) + 1, char);
+ strcpy(ret, timebuf);
+ strcat(ret, text);
+ return ret;
+
+ } else {
+ return dupstr(text);
+ }
+}
* That hook can talk to the game_ui and set the cheated flag,
* and then make_move can avoid setting the `won' flag after that.
*
- * - timer
- *
* - question marks (arrgh, preferences?)
*
* - sensible parameter constraints
return TRUE;
}
+static int game_timing_state(game_state *state)
+{
+ if (state->dead || state->won || !state->layout->mines)
+ return FALSE;
+ return TRUE;
+}
+
#ifdef COMBINED
#define thegame mines
#endif
game_anim_length,
game_flash_length,
game_wants_statusbar,
+ TRUE, game_timing_state,
};
return TRUE;
}
+static int game_timing_state(game_state *state)
+{
+ return TRUE;
+}
+
#ifdef COMBINED
#define thegame net
#endif
game_anim_length,
game_flash_length,
game_wants_statusbar,
+ FALSE, game_timing_state,
};
return TRUE;
}
+static int game_timing_state(game_state *state)
+{
+ return FALSE;
+}
+
#ifdef COMBINED
#define thegame netslide
#endif
game_anim_length,
game_flash_length,
game_wants_statusbar,
+ FALSE, game_timing_state,
};
return FALSE;
}
+static int game_timing_state(game_state *state)
+{
+ return TRUE;
+}
+
#ifdef COMBINED
#define thegame nullgame
#endif
game_anim_length,
game_flash_length,
game_wants_statusbar,
+ FALSE, game_timing_state,
};
- (void)keyDown:(NSEvent *)ev;
- (void)activateTimer;
- (void)deactivateTimer;
-- (void)setStatusLine:(NSString *)text;
+- (void)setStatusLine:(char *)text;
@end
@implementation MyImageView
[self sheetEndWithStatus:NO];
}
-- (void)setStatusLine:(NSString *)text
+- (void)setStatusLine:(char *)text
{
- [[status cell] setTitle:text];
+ char *rewritten = midend_rewrite_statusbar(me, text);
+ [[status cell] setTitle:[NSString stringWithCString:rewritten]];
+ sfree(rewritten);
}
@end
void status_bar(frontend *fe, char *text)
{
- [fe->window setStatusLine:[NSString stringWithCString:text]];
+ [fe->window setStatusLine:text];
}
/* ----------------------------------------------------------------------
return FALSE;
}
+static int game_timing_state(game_state *state)
+{
+ return TRUE;
+}
+
#ifdef COMBINED
#define thegame pattern
#endif
game_anim_length,
game_flash_length,
game_wants_statusbar,
+ FALSE, game_timing_state,
};
#ifdef STANDALONE_SOLVER
char *midend_text_format(midend_data *me);
char *midend_solve(midend_data *me);
void midend_supersede_game_desc(midend_data *me, char *desc);
+char *midend_rewrite_statusbar(midend_data *me, char *text);
/*
* malloc.c
float (*flash_length)(game_state *oldstate, game_state *newstate, int dir,
game_ui *ui);
int (*wants_statusbar)(void);
+ int is_timed;
+ int (*timing_state)(game_state *state);
};
/*
return FALSE;
}
+static int game_timing_state(game_state *state)
+{
+ return TRUE;
+}
+
#ifdef COMBINED
#define thegame rect
#endif
game_anim_length,
game_flash_length,
game_wants_statusbar,
+ FALSE, game_timing_state,
};
return TRUE;
}
+static int game_timing_state(game_state *state)
+{
+ return TRUE;
+}
+
#ifdef COMBINED
#define thegame sixteen
#endif
game_anim_length,
game_flash_length,
game_wants_statusbar,
+ FALSE, game_timing_state,
};
return FALSE;
}
+static int game_timing_state(game_state *state)
+{
+ return TRUE;
+}
+
#ifdef COMBINED
#define thegame solo
#endif
game_anim_length,
game_flash_length,
game_wants_statusbar,
+ FALSE, game_timing_state,
};
#ifdef STANDALONE_SOLVER
return TRUE;
}
+static int game_timing_state(game_state *state)
+{
+ return TRUE;
+}
+
#ifdef COMBINED
#define thegame twiddle
#endif
game_anim_length,
game_flash_length,
game_wants_statusbar,
+ FALSE, game_timing_state,
};
HFONT cfgfont;
char *help_path;
int help_has_contents;
+ char *laststatus;
};
void fatal(char *fmt, ...)
void status_bar(frontend *fe, char *text)
{
- SetWindowText(fe->statusbar, text);
+ char *rewritten = midend_rewrite_statusbar(fe->me, text);
+ if (!fe->laststatus || strcmp(rewritten, fe->laststatus)) {
+ SetWindowText(fe->statusbar, rewritten);
+ sfree(fe->laststatus);
+ fe->laststatus = rewritten;
+ } else {
+ sfree(rewritten);
+ }
}
void frontend_default_colour(frontend *fe, float *output)
fe->fonts = NULL;
fe->nfonts = fe->fontsize = 0;
+ fe->laststatus = NULL;
+
{
int i, ncolours;
float *colours;