diff --git a/include/config.h b/include/config.h index 5016c6702..b54d073de 100644 --- a/include/config.h +++ b/include/config.h @@ -681,6 +681,16 @@ typedef unsigned char uchar; #endif #endif +/* experimential; if the platform/window-port supports it; when the game has + * started to wait for player input, and the wait lasts longer than + * IDLECHECKPOINT_WAIT_TIME seconds (defined in hack.h or *conf.h), the game + * will perform an update to the checkpoint file. + * Currently has support in: + * WIN32CON + */ + +/* #define IDLECHECKPOINT */ + /* End of Section 4 */ #ifdef TTY_TILES_ESCCODES diff --git a/include/flag.h b/include/flag.h index f48b4693c..e125694b3 100644 --- a/include/flag.h +++ b/include/flag.h @@ -246,6 +246,8 @@ struct instance_flags { * to input becoming taken over); * True => enable fuzzer when entering moveloop */ boolean herecmd_menu; /* use menu when mouseclick on yourself */ + boolean idlecheckpoint; /* platform should perform a checkpoint update + * if waiting for input longer than 10 seconds */ boolean invis_goldsym; /* gold symbol is ' '? */ boolean in_lua; /* executing a lua script */ boolean lua_testing; /* doing lua tests */ diff --git a/include/hack.h b/include/hack.h index 1a8e07f14..19f543ac0 100644 --- a/include/hack.h +++ b/include/hack.h @@ -588,6 +588,13 @@ enum inventory_counts { /* 2023/11/30 invlet_max is not yet used anywhere */ }; +#ifndef IDLECHECKPOINT_WAIT_TIME +#define IDLECHECKPOINT_WAIT_TIME 10 /* seconds to wait before executing a checkpoint; + * always #define'd but only has meaning if + * IDLECHECKPOINT is defined. + */ +#endif + struct kinfo { struct kinfo *next; /* chain of delayed killers */ int id; /* uprop keys to ID a delayed killer */ diff --git a/include/optlist.h b/include/optlist.h index 4d3474a4b..e91fb0238 100644 --- a/include/optlist.h +++ b/include/optlist.h @@ -387,6 +387,9 @@ static int optfn_##a(int, int, boolean, char *, char *); Yes, Yes, No, No, NoAlias, "load IBMGraphics display symbols into symset") #endif + NHOPTB(idlecheckpoint, Advanced, 0, opt_in, set_in_game, + Off, Yes, No, No, NoAlias, &iflags.idlecheckpoint, Term_Off, + "update checkpoint file if input is idle for 10 seconds") #ifndef MAC NHOPTB(ignintr, Advanced, 0, opt_in, set_in_game, Off, Yes, No, No, NoAlias, &flags.ignintr, Term_False, diff --git a/include/windconf.h b/include/windconf.h index 81ad8baeb..5644451da 100644 --- a/include/windconf.h +++ b/include/windconf.h @@ -35,6 +35,10 @@ #define EARLY_CONFIGFILE_PASS #define TTY_PERM_INVENT +#ifdef WIN32CON +#define IDLECHECKPOINT +#endif + /* * ----------------------------------------------------------------- * The remaining code shouldn't need modification. diff --git a/src/options.c b/src/options.c index 786c5757e..4897e7e7f 100644 --- a/src/options.c +++ b/src/options.c @@ -5310,6 +5310,14 @@ optfn_boolean( #endif go.opt_need_redraw = TRUE; break; +#ifndef IDLECHECKPOINT + case opt_idlecheckpoint: + pline("There is no underlying support for 'idlecheckpoint'" + " compiled in."); + iflags.idlecheckpoint = FALSE; + give_opt_msg = FALSE; + break; +#endif default: break; } diff --git a/sys/windows/consoletty.c b/sys/windows/consoletty.c index 9ffdc5880..926b4033f 100644 --- a/sys/windows/consoletty.c +++ b/sys/windows/consoletty.c @@ -3097,7 +3097,8 @@ default_checkinput( DWORD dwWait; #endif int ch = 0; - boolean valid = 0, done = 0; + boolean valid = 0, done = 0, done_a_checkpoint = FALSE; + DWORD how_many_milliseconds = 0; #ifdef QWERTZ_SUPPORT if (numberpad & 0x10) { @@ -3107,54 +3108,78 @@ default_checkinput( qwertz = FALSE; } #endif + done_a_checkpoint = FALSE; + how_many_milliseconds = (iflags.idlecheckpoint) + ? (IDLECHECKPOINT_WAIT_TIME * 1000) + : INFINITE; while (!done) { -#if defined(SAFERHANGUP) dwWait = WaitForSingleObjectEx(hConIn, // event object to wait for - INFINITE, // waits indefinitely + how_many_milliseconds, TRUE); // alertable wait enabled +#if defined(SAFERHANGUP) if (dwWait == WAIT_FAILED) return '\033'; #endif - ReadConsoleInput(hConIn, ir, 1, count); - if (mode == 0) { - if ((ir->EventType == KEY_EVENT) && ir->Event.KeyEvent.bKeyDown) { - ch = default_processkeystroke(hConIn, ir, &valid, numberpad, 0); - done = valid; - } - } else { - if (*count > 0) { - if (ir->EventType == KEY_EVENT +#ifdef INSURANCE + if (iflags.idlecheckpoint + && dwWait == WAIT_TIMEOUT && !done_a_checkpoint) { + /* no input for 30 seconds, so let's take + * advantage and do a game checkpoint, + * then resume the wait. + */ + save_currentstate(); + done_a_checkpoint = TRUE; + } else +#endif /* INSURANCE */ + { + ReadConsoleInput(hConIn, ir, 1, count); + if (mode == 0) { + if ((ir->EventType == KEY_EVENT) && ir->Event.KeyEvent.bKeyDown) { + ch = default_processkeystroke(hConIn, ir, &valid, + numberpad, 0); + done = valid; + } + } else { + if (*count > 0) { + if (ir->EventType == KEY_EVENT + && ir->Event.KeyEvent.bKeyDown) { #ifdef QWERTZ_SUPPORT - if (qwertz) - numberpad |= 0x10; + if (qwertz) + numberpad |= 0x10; #endif - ch = default_processkeystroke(hConIn, ir, &valid, numberpad, 0); + ch = default_processkeystroke(hConIn, ir, &valid, + numberpad, 0); #ifdef QWERTZ_SUPPORT - numberpad &= ~0x10; + numberpad &= ~0x10; #endif - if (valid) - return ch; - } else if (ir->EventType == MOUSE_EVENT) { - if ((ir->Event.MouseEvent.dwEventFlags == 0) - && (ir->Event.MouseEvent.dwButtonState & MOUSEMASK)) { - cc->x = ir->Event.MouseEvent.dwMousePosition.X + 1; - cc->y = ir->Event.MouseEvent.dwMousePosition.Y - 1; + if (valid) + return ch; + } else if (ir->EventType == MOUSE_EVENT) { + if ((ir->Event.MouseEvent.dwEventFlags == 0) + && (ir->Event.MouseEvent.dwButtonState + & MOUSEMASK)) { + cc->x = + ir->Event.MouseEvent.dwMousePosition.X + 1; + cc->y = + ir->Event.MouseEvent.dwMousePosition.Y - 1; - if (ir->Event.MouseEvent.dwButtonState & LEFTBUTTON) - *mod = CLICK_1; - else if (ir->Event.MouseEvent.dwButtonState - & RIGHTBUTTON) - *mod = CLICK_2; + if (ir->Event.MouseEvent.dwButtonState + & LEFTBUTTON) + *mod = CLICK_1; + else if (ir->Event.MouseEvent.dwButtonState + & RIGHTBUTTON) + *mod = CLICK_2; #if 0 /* middle button */ else if (ir->Event.MouseEvent.dwButtonState & MIDBUTTON) *mod = CLICK_3; #endif - return 0; + return 0; + } } - } - } else - done = 1; + } else + done = 1; + } } } return mode ? 0 : ch; diff --git a/sys/windows/windmain.c b/sys/windows/windmain.c index 99567f9d2..20f5ebdb6 100644 --- a/sys/windows/windmain.c +++ b/sys/windows/windmain.c @@ -300,7 +300,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ if WINDOWPORT(tty) { int i; - for (i = 0; i < 20; ++i) { + for (i = 0; i < 5; ++i) { nh_delay_output(); }