.ds vr "NetHack 3.4
.ds f0 "\*(vr
.ds f1
-.ds f2 "October 29, 2004
+.ds f2 "January 9, 2005
.mt
A Guide to the Mazes of Menace
(Guidebook for NetHack)
.lp scroll_margin
NetHack should scroll the display when the hero or cursor
is this number of cells away from the edge of the window.
+.lp selectsaved
+NetHack should display a menu of existing saved games for the player to
+choose from at game startup, if it can. Not all ports support this option.
.lp softkeyboard
Display an onscreen keyboard. Handhelds are most likely to support this option.
.lp splash_screen
\begin{document}
%
% input file: guidebook.mn
-% $Revision: 1.87 $ $Date: 2004/11/06 02:42:03 $
+% $Revision: 1.88 $ $Date: 2005/01/02 17:10:47 $
%
%.ds h0 "
%.ds h1 %.ds h2 \%
%.au
\author{Eric S. Raymond\\
(Extensively edited and expanded for 3.5)}
-\date{October 29, 2004}
+\date{January 9, 2005}
\maketitle
NetHack should scroll the display when the hero or cursor
is this number of cells away from the edge of the window.
%.lp
+\item[\ib{selectsaved}]
+NetHack should display a menu of existing saved games for the player to
+choose from at game startup, if it can. Not all ports support this option.
+%.lp
\item[\ib{softkeyboard}]
Display an onscreen keyboard. Handhelds are most likely to support this option.
%.lp
continue to fight in its native form
container lknown flag for locked/unlocked/broken awareness
container cknown flag for container content awareness
+plname is stored in the save file on all platforms now
Platform- and/or Interface-Specific New Features
win32gui: support for saving/restoring message history
win32gui: added menu options "Copy ASCII Screenshot To Clipboard" and "Save
ASCII Screenshot To File"
+win32tty: support for 'selectsaved' option for menu of existing save files
+ to choose from at game startup
tty: add window port routines for saving/restoring message history
| fullscreen | WC2_FULLSCREEN | wc2_fullscreen |boolean |
| softkeyboard | WC2_SOFTKEYBOARD | wc2_softkeyboard |boolean |
| wraptext | WC2_WRAPTEXT | wc2_wraptext |boolean |
+ | selectsaved | WC2_SELECTSAVED | wc2_selectsaved |boolean |
+--------------------+--------------------+--------------------+--------+
align_message -- where to place message window (top, bottom, left, right)
-- dialog or prompts for choosing character.
popup_dialog -- port should pop up dialog boxes for input.
preload_tiles -- port should preload tiles into memory.
+saveselection -- if port can display a menu of the user's saved games do so.
scroll_amount -- scroll this amount when scroll_margin is reached.
scroll_margin -- port should scroll the display when the hero or cursor
is this number of cells away from the edge of the window.
E int FDECL(dorecover, (int));
E void FDECL(trickery, (char *));
E void FDECL(getlev, (int,int,XCHAR_P,BOOLEAN_P));
+E void FDECL(get_plname_from_file, (int, char *));
E void NDECL(minit);
E boolean FDECL(lookup_id_mapping, (unsigned, unsigned *));
#ifdef ZEROCOMP
E void FDECL(bwrite, (int,genericptr_t,unsigned int));
E void FDECL(bclose, (int));
E void FDECL(savefruitchn, (int,int));
+E void FDECL(store_plname_in_file, (int));
E void NDECL(free_dungeons);
E void NDECL(freedynamicdata);
boolean wc2_fullscreen; /* run fullscreen */
boolean wc2_softkeyboard; /* use software keyboard */
boolean wc2_wraptext; /* wrap text */
+ boolean wc2_selectsaved; /* display a menu of user's saved games */
boolean cmdassist; /* provide detailed assistance for some commands */
boolean clicklook; /* allow right-clicking for look */
boolean obsolete; /* obsolete options can point at this, it isn't used */
#define SELF_RECOVER /* Allow the game itself to recover from an aborted game */
#define USER_SOUNDS
+
+#ifdef WIN32CON
+#define SELECTSAVED /* Provide menu of saved games to choose from at start */
+#endif
+
/*
* -----------------------------------------------------------------
* The remaining code shouldn't need modification.
* Incrementing EDITLEVEL can be used to force invalidation of old bones
* and save files.
*/
-#define EDITLEVEL 18
+#define EDITLEVEL 19
#define COPYRIGHT_BANNER_A \
"NetHack, Copyright 1985-2005"
#define WC2_SOFTKEYBOARD 0x02L /* 02 software keyboard */
#define WC2_WRAPTEXT 0x04L /* 03 wrap long lines of text */
#define WC2_HILITE_STATUS 0x08L /* 04 hilite fields in status */
- /* 28 free bits */
+#define WC2_SELECTSAVED 0x10L /* 05 saved game selection menu */
+ /* 27 free bits */
#define ALIGN_LEFT 1
#define ALIGN_RIGHT 2
extern int n_dgns; /* from dungeon.c */
#if defined(UNIX) && defined(QT_GRAPHICS)
+#define SELECTSAVED
+#endif
+
+#ifdef SELECTSAVED
STATIC_DCL int FDECL(strcmp_wrap, (const void *, const void *));
#endif
STATIC_DCL char *FDECL(set_bonesfile_name, (char *,d_level*));
#endif
}
-#if defined(UNIX) && defined(QT_GRAPHICS)
+#if defined(SELECTSAVED)
STATIC_OVL int
strcmp_wrap(p, q)
const void *p;
const void *q;
{
+#if defined(UNIX) && defined(QT_GRAPHICS)
return strncasecmp(*(char **) p, *(char **) q, 16);
+# else
+ return strncmpi(*(char **) p, *(char **) q, 16);
+# endif
}
#endif
return fd;
}
-#if defined(UNIX) && defined(QT_GRAPHICS)
+#if defined(SELECTSAVED)
/*ARGSUSED*/
static char*
plname_from_file(filename)
const char* filename;
{
-#ifdef STORE_PLNAME_IN_FILE
int fd;
char* result = 0;
Strcpy(SAVEF,filename);
-#ifdef COMPRESS_EXTENSION
+# ifdef COMPRESS_EXTENSION
SAVEF[strlen(SAVEF)-strlen(COMPRESS_EXTENSION)] = '\0';
-#endif
+# endif
uncompress(SAVEF);
if ((fd = open_savefile()) >= 0) {
if (uptodate(fd, filename)) {
char tplname[PL_NSIZ];
- mread(fd, (genericptr_t) tplname, PL_NSIZ);
+ get_plname_from_file(fd, tplname);
result = strdup(tplname);
}
(void) close(fd);
compress(SAVEF);
return result;
-#else
-# if defined(UNIX) && defined(QT_GRAPHICS)
+# if 0
+/* --------- obsolete - used to be ifndef STORE_PLNAME_IN_FILE ----*/
+# if defined(UNIX) && defined(QT_GRAPHICS)
/* Name not stored in save file, so we have to extract it from
the filename, which loses information
(eg. "/", "_", and "." characters are lost. */
int k;
int uid;
char name[64]; /* more than PL_NSIZ */
-#ifdef COMPRESS_EXTENSION
+# ifdef COMPRESS_EXTENSION
#define EXTSTR COMPRESS_EXTENSION
-#else
+# else
#define EXTSTR ""
-#endif
+# endif
if ( sscanf( filename, "%*[^/]/%d%63[^.]" EXTSTR, &uid, name ) == 2 ) {
#undef EXTSTR
/* "_" most likely means " ", which certainly looks nicer */
name[k]=' ';
return strdup(name);
} else
-# endif
+# endif /* UNIX && QT_GRAPHICS */
{
return 0;
}
-#endif
+/* --------- end of obsolete code ----*/
+# endif /* 0 - WAS STORE_PLNAME_IN_FILE*/
}
-#endif /* defined(UNIX) && defined(QT_GRAPHICS) */
+#endif /* defined(SELECTSAVED) */
char**
get_saved_games()
{
-#if defined(UNIX) && defined(QT_GRAPHICS)
+#if defined(SELECTSAVED)
+ int n, j;
+ char **result;
+# ifdef WIN32CON
+ char fnamebuf[BUFSZ], encodedfnamebuf[BUFSZ];
+ char *foundfile;
+ const char *fq_save;
+
+ Sprintf(fnamebuf, "%s-", get_username(0));
+ (void)fname_encode("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-.",
+ '%', fnamebuf, encodedfnamebuf, BUFSZ);
+ Sprintf(SAVEF, "%s*.NetHack-saved-game", encodedfnamebuf);
+ fq_save = fqname(SAVEF, SAVEPREFIX, 0);
+
+ foundfile = foundfile_buffer();
+ if (findfirst((char *)fq_save)) {
+ n = 0;
+ do {
+ ++n;
+ } while (findnext());
+ }
+ if (n > 0) {
+ result = (char**)alloc((n+1)*sizeof(char*)); /* at most */
+ if (findfirst((char *)fq_save)) {
+ j = n = 0;
+ do {
+ char *r;
+ r = plname_from_file(foundfile);
+ if (r)
+ result[j++] = r;
+ ++n;
+ } while (findnext());
+# endif
+# if defined(UNIX) && defined(QT_GRAPHICS)
/* posixly correct version */
int myuid=getuid();
DIR *dir;
}
}
closedir(dir);
+# endif
qsort(result, j, sizeof(char *), strcmp_wrap);
result[j++] = 0;
return result;
#else
{"sanity_check", (boolean *)0, FALSE, SET_IN_FILE},
#endif
+ {"selectsaved", &iflags.wc2_selectsaved, TRUE, DISP_IN_GAME}, /*WC*/
#ifdef EXP_ON_BOTL
{"showexp", &flags.showexp, FALSE, SET_IN_GAME},
#else
int rtmp;
struct obj *otmp;
-#ifdef STORE_PLNAME_IN_FILE
- mread(fd, (genericptr_t) plname, PL_NSIZ);
-#endif
-
restoring = TRUE;
+ get_plname_from_file(fd, plname);
getlev(fd, 0, (xchar)0, FALSE);
if (!restgamestate(fd, &stuckid, &steedid)) {
display_nhwindow(WIN_MESSAGE, TRUE);
(void) lseek(fd, (off_t)0, 0);
#endif
(void) uptodate(fd, (char *)0); /* skip version info */
-#ifdef STORE_PLNAME_IN_FILE
- mread(fd, (genericptr_t) plname, PL_NSIZ);
-#endif
+ get_plname_from_file(fd, plname);
+
getlev(fd, 0, (xchar)0, FALSE);
(void) close(fd);
clear_id_mapping();
}
+void
+get_plname_from_file(fd, plbuf)
+int fd;
+char *plbuf;
+{
+ int rlen, pltmpsiz = 0;
+ rlen = read(fd, (genericptr_t) &pltmpsiz, sizeof(pltmpsiz));
+ rlen = read(fd, (genericptr_t) plbuf, pltmpsiz);
+ return;
+}
+
STATIC_OVL void
restore_msghistory(fd)
register int fd;
#endif /* MFLOPPY */
store_version(fd);
-#ifdef STORE_PLNAME_IN_FILE
- bwrite(fd, (genericptr_t) plname, PL_NSIZ);
-#endif
+ store_plname_in_file(fd);
ustuck_id = (u.ustuck ? u.ustuck->m_id : 0);
#ifdef STEED
usteed_id = (u.usteed ? u.usteed->m_id : 0);
(void) write(fd, (genericptr_t) &currlev, sizeof(currlev));
save_savefile_name(fd);
store_version(fd);
-#ifdef STORE_PLNAME_IN_FILE
- bwrite(fd, (genericptr_t) plname, PL_NSIZ);
-#endif
+ store_plname_in_file(fd);
+
ustuck_id = (u.ustuck ? u.ustuck->m_id : 0);
#ifdef STEED
usteed_id = (u.usteed ? u.usteed->m_id : 0);
ffruit = 0;
}
+void
+store_plname_in_file(fd)
+int fd;
+{
+ int plsiztmp = PL_NSIZ;
+ bufoff(fd);
+ /* bwrite() before bufon() uses plain write() */
+ bwrite(fd, (genericptr_t) &plsiztmp, sizeof(plsiztmp));
+ bwrite(fd, (genericptr_t) plname, plsiztmp);
+ bufon(fd);
+ return;
+}
+
STATIC_OVL void
save_msghistory(fd, mode)
register int fd, mode;
WC_MOUSE_SUPPORT|
#endif
WC_COLOR|WC_HILITE_PET|WC_INVERSE|WC_EIGHT_BIT_IN,
+#if defined(SELECTSAVED) && defined(WIN32CON)
+ WC2_SELECTSAVED|
+#endif
0L,
tty_init_nhwindows,
tty_player_selection,
{
static char who_are_you[] = "Who are you? ";
register int c, ct, tryct = 0;
+#ifdef SELECTSAVED
+# if defined(WIN32CON)
+ int ch = -2;
+ char** saved = (char **)0;
+
+ if (iflags.wc2_selectsaved)
+ saved = get_saved_games();
+ if (saved && *saved) {
+ int k, clet = 'a';
+ winid tmpwin;
+ anything any;
+ menu_item *chosen_game = (menu_item *)0;
+
+ ch = -1;
+ saved = get_saved_games();
+ tty_clear_nhwindow(BASE_WINDOW);
+ tmpwin = create_nhwindow(NHW_MENU);
+ start_menu(tmpwin);
+ any.a_int = 0; /* no selection */
+ add_menu(tmpwin, NO_GLYPH, &any, 0, 0,
+ ATR_NONE, COPYRIGHT_BANNER_A, MENU_UNSELECTED);
+ add_menu(tmpwin, NO_GLYPH, &any, 0, 0,
+ ATR_NONE, COPYRIGHT_BANNER_B, MENU_UNSELECTED);
+ add_menu(tmpwin, NO_GLYPH, &any, 0, 0,
+ ATR_NONE, COPYRIGHT_BANNER_C, MENU_UNSELECTED);
+ add_menu(tmpwin, NO_GLYPH, &any, 0, 0,
+ ATR_NONE, "", MENU_UNSELECTED);
+ add_menu(tmpwin, NO_GLYPH, &any, 0, 0,
+ ATR_NONE, "Select one of your saved games", MENU_UNSELECTED);
+ for (k = 0; saved[k]; ++k) {
+ if (clet == 'z' + 1) clet = 'A';
+ if (clet == 'Z') break;
+ any.a_int = k + 1;
+ add_menu(tmpwin, NO_GLYPH, &any, clet++, 0,
+ ATR_NONE, saved[k], MENU_UNSELECTED);
+ }
+ any.a_int = -2;
+ add_menu(tmpwin, NO_GLYPH, &any, clet, 0,
+ ATR_NONE, "Start a new character", MENU_UNSELECTED);
+ /* no prompt on end_menu, as we've done our own at the top */
+ end_menu(tmpwin, (char *)0);
+ if (select_menu(tmpwin, PICK_ONE, &chosen_game) > 0) {
+ ch = chosen_game->item.a_int;
+ if (ch > 0) {
+ ch--;
+ strcpy(plname,saved[ch]);
+ }
+ free((genericptr_t)chosen_game);
+ }
+ destroy_nhwindow(tmpwin);
+ }
+ free_saved_games(saved);
+ if (ch >= 0) return;
+ if (ch == -1) bail("Until next time then...");
+# endif /* WIN32CON */
+#endif /* SELECTSAVED */
tty_putstr(BASE_WINDOW, 0, "");
do {
} else
clear_screen();
ttyDisplay->toplin = 0;
- } else
- tty_clear_nhwindow(WIN_MESSAGE);
+ } else {
+ if (WIN_MESSAGE != WIN_ERR)
+ tty_clear_nhwindow(WIN_MESSAGE);
+ }
if (cw->data || !cw->maxrow)
process_text_window(window, cw);