'selectsaved' extension
Instead of a menu listing a - hero1 b - hero2 n - New game q - Quit show a - hero1-role1-race1-gend1-algn1 b - hero2-role2-race2-gend2-algn2 n - New game q - Quit or a - - hero1-role1-race1-gend1-algn1 b - X hero2-role2-race2-gend2-algn2 c - D wizard-role3-race3-gend3-algn3 n - New game q - Quit when any game in the list wasn't saved during normal play. (Those are sorted by character name; the playmode is just coincidence.) The dash for 'normal' doesn't look great but -/X/D are codes used in entries written to paniclog. The whole playmode prefix doesn't look particularly good but I suspect that most players relying on restore via menu won't see it. It should work when the character name has dashes in it but that hasn't been properly tested. The gender and alignment suffices reflect their value at the time of save rather than at the start of the game. That might be considered a bug but it was easiest. Increments EDITLEVEL; existing save and bones files are invalidated.
This commit is contained in:
@@ -2710,6 +2710,12 @@ livelog/#chronicle for saving-grace: if saving-grace prevents hero's death,
|
||||
enlightenment/attribute disclosure for saving-grace: include a line for have
|
||||
or haven't been saved (game in progress) or did or didn't get saved
|
||||
(game over) via saving-grace
|
||||
'selectsaved' lists "name-role-race-gend-algn" instead of just "name" in the
|
||||
menu of save files available to be restored
|
||||
'selectsaved' prefixes "name-role-race-gend-algn" with "- " for normal play,
|
||||
"X " for explore mode, or "D " for debug mode if any of the games
|
||||
shown in its menu weren't saved during normal play; if they're all
|
||||
normal play, the prefix is suppressed
|
||||
|
||||
|
||||
Platform- and/or Interface-Specific New Features
|
||||
|
||||
@@ -2618,7 +2618,7 @@ extern int dorecover(NHFILE *) NONNULLARG1;
|
||||
extern void restcemetery(NHFILE *, struct cemetery **) NONNULLARG12;
|
||||
extern void trickery(char *) NO_NNARGS;
|
||||
extern void getlev(NHFILE *, int, xint8) NONNULLARG1;
|
||||
extern void get_plname_from_file(NHFILE *, char *) NONNULLARG12;
|
||||
extern void get_plname_from_file(NHFILE *, char *, boolean) NONNULLARG12;
|
||||
#ifdef SELECTSAVED
|
||||
extern int restore_menu(winid);
|
||||
#endif
|
||||
|
||||
@@ -431,6 +431,8 @@ extern struct nomakedefs_s nomakedefs;
|
||||
#define PL_CSIZ 32 /* sizeof pl_character */
|
||||
#define PL_FSIZ 32 /* fruit name */
|
||||
#define PL_PSIZ 63 /* player-given names for pets, other monsters, objects */
|
||||
/* room for "name-role-race-gend-algn" plus 1 character playmode code */
|
||||
#define PL_NSIZ_PLUS (PL_NSIZ + 4 * (1 + 4) + 1) /* 53 */
|
||||
|
||||
#define MAXDUNGEON 16 /* current maximum number of dungeons */
|
||||
#define MAXLEVEL 32 /* max number of levels in one dungeon */
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Incrementing EDITLEVEL can be used to force invalidation of old bones
|
||||
* and save files.
|
||||
*/
|
||||
#define EDITLEVEL 107
|
||||
#define EDITLEVEL 108
|
||||
|
||||
/*
|
||||
* Development status possibilities.
|
||||
|
||||
89
src/files.c
89
src/files.c
@@ -719,11 +719,7 @@ clearlocks(void)
|
||||
staticfn int QSORTCALLBACK
|
||||
strcmp_wrap(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
|
||||
return strcmp(*(char **) p, *(char **) q);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -989,7 +985,7 @@ set_savefile_name(boolean regularize_it)
|
||||
if (strlen(gs.SAVEF) < (SAVESIZE - 1))
|
||||
(void) strncat(gs.SAVEF, svp.plname, (SAVESIZE - strlen(gs.SAVEF)));
|
||||
#endif
|
||||
#if defined(MICRO) && !defined(VMS) && !defined(WIN32) && !defined(MSDOS)
|
||||
#if defined(MICRO) && !defined(WIN32) && !defined(MSDOS)
|
||||
if (strlen(gs.SAVEP) < (SAVESIZE - 1))
|
||||
Strcpy(gs.SAVEF, gs.SAVEP);
|
||||
else
|
||||
@@ -1252,9 +1248,12 @@ check_panic_save(void)
|
||||
#if defined(SELECTSAVED)
|
||||
|
||||
char *
|
||||
plname_from_file(const char *filename, boolean without_wait_synch_per_file)
|
||||
plname_from_file(
|
||||
const char *filename,
|
||||
boolean without_wait_synch_per_file)
|
||||
{
|
||||
NHFILE *nhfp = (NHFILE *) 0;
|
||||
NHFILE *nhfp;
|
||||
unsigned ln;
|
||||
char *result = 0;
|
||||
|
||||
Strcpy(gs.SAVEF, filename);
|
||||
@@ -1271,60 +1270,32 @@ plname_from_file(const char *filename, boolean without_wait_synch_per_file)
|
||||
nh_uncompress(gs.SAVEF);
|
||||
if ((nhfp = open_savefile()) != 0) {
|
||||
if (validate(nhfp, filename, without_wait_synch_per_file) == 0) {
|
||||
char tplname[PL_NSIZ];
|
||||
|
||||
get_plname_from_file(nhfp, tplname);
|
||||
result = dupstr(tplname);
|
||||
/* room for "name+role+race+gend+algn X" where the space before
|
||||
X is actually NUL and X is playmode: one of '-', 'X', or 'D' */
|
||||
ln = (unsigned) PL_NSIZ_PLUS;
|
||||
result = memset((genericptr_t) alloc(ln), '\0', ln);
|
||||
get_plname_from_file(nhfp, result, FALSE);
|
||||
}
|
||||
close_nhfile(nhfp);
|
||||
}
|
||||
nh_compress(gs.SAVEF);
|
||||
|
||||
return result;
|
||||
#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
|
||||
#define EXTSTR COMPRESS_EXTENSION
|
||||
#else
|
||||
#define EXTSTR ""
|
||||
#endif
|
||||
|
||||
if (sscanf(filename, "%*[^/]/%d%63[^.]" EXTSTR, &uid, name) == 2) {
|
||||
#undef EXTSTR
|
||||
/* "_" most likely means " ", which certainly looks nicer */
|
||||
for (k = 0; name[k]; k++)
|
||||
if (name[k] == '_')
|
||||
name[k] = ' ';
|
||||
return dupstr(name);
|
||||
} else
|
||||
#endif /* UNIX && QT_GRAPHICS */
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/* --------- end of obsolete code ----*/
|
||||
#endif /* 0 - WAS STORE_PLNAME_IN_FILE*/
|
||||
return result; /* file's plname[]+playmode value */
|
||||
}
|
||||
#endif /* defined(SELECTSAVED) */
|
||||
|
||||
#define SUPPRESS_WAITSYNCH_PERFILE TRUE
|
||||
#define ALLOW_WAITSYNCH_PERFILE FALSE
|
||||
|
||||
/* get list of saved games owned by current user */
|
||||
char **
|
||||
get_saved_games(void)
|
||||
{
|
||||
char **result = NULL;
|
||||
#if defined(SELECTSAVED)
|
||||
#if defined(WIN32) || defined(UNIX)
|
||||
int n;
|
||||
#endif
|
||||
int j = 0;
|
||||
char **result = 0;
|
||||
|
||||
#ifdef WIN32
|
||||
{
|
||||
@@ -1351,8 +1322,8 @@ get_saved_games(void)
|
||||
}
|
||||
|
||||
if (n > 0) {
|
||||
files = (char **) alloc((n + 1) * sizeof(char *)); /* at most */
|
||||
(void) memset((genericptr_t) files, 0, (n + 1) * sizeof(char *));
|
||||
files = (char **) alloc((n + 1) * sizeof (char *)); /* at most */
|
||||
(void) memset((genericptr_t) files, 0, (n + 1) * sizeof (char *));
|
||||
if (findfirst((char *) fq_save)) {
|
||||
i = 0;
|
||||
do {
|
||||
@@ -1362,8 +1333,8 @@ get_saved_games(void)
|
||||
}
|
||||
|
||||
if (n > 0) {
|
||||
result = (char **) alloc((n + 1) * sizeof(char *)); /* at most */
|
||||
(void) memset((genericptr_t) result, 0, (n + 1) * sizeof(char *));
|
||||
result = (char **) alloc((n + 1) * sizeof (char *)); /* at most */
|
||||
(void) memset((genericptr_t) result, 0, (n + 1) * sizeof (char *));
|
||||
for(i = 0; i < n; i++) {
|
||||
char *r;
|
||||
r = plname_from_file(files[i], SUPPRESS_WAITSYNCH_PERFILE);
|
||||
@@ -1390,7 +1361,7 @@ get_saved_games(void)
|
||||
if (count_failures)
|
||||
wait_synch();
|
||||
}
|
||||
#endif
|
||||
#endif /* WIN32 */
|
||||
#ifdef UNIX
|
||||
/* posixly correct version */
|
||||
int myuid = getuid();
|
||||
@@ -1409,7 +1380,7 @@ get_saved_games(void)
|
||||
(void) memset((genericptr_t) result, 0, (n + 1) * sizeof(char *));
|
||||
for (i = 0, j = 0; i < n; i++) {
|
||||
int uid;
|
||||
char name[64]; /* more than PL_NSIZ */
|
||||
char name[64]; /* more than PL_NSIZ+1 */
|
||||
struct dirent *entry = readdir(dir);
|
||||
|
||||
if (!entry)
|
||||
@@ -1430,7 +1401,7 @@ get_saved_games(void)
|
||||
closedir(dir);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* UNIX */
|
||||
#ifdef VMS
|
||||
Strcpy(svp.plname, "*");
|
||||
set_savefile_name(FALSE);
|
||||
@@ -1440,14 +1411,14 @@ get_saved_games(void)
|
||||
if (j > 0) {
|
||||
if (j > 1)
|
||||
qsort(result, j, sizeof (char *), strcmp_wrap);
|
||||
result[j] = 0;
|
||||
return result;
|
||||
result[j] = (char *) NULL;
|
||||
} else if (result) { /* could happen if save files are obsolete */
|
||||
free_saved_games(result);
|
||||
result = (char **) NULL;
|
||||
}
|
||||
#endif /* SELECTSAVED */
|
||||
|
||||
return 0;
|
||||
return result;
|
||||
}
|
||||
#undef SUPPRESS_WAITSYNCH_PERFILE
|
||||
#undef ALLOW_WAITSYNCH_PERFILE
|
||||
@@ -1456,10 +1427,10 @@ void
|
||||
free_saved_games(char **saved)
|
||||
{
|
||||
if (saved) {
|
||||
int i = 0;
|
||||
int i;
|
||||
|
||||
while (saved[i])
|
||||
free((genericptr_t) saved[i++]);
|
||||
for (i = 0; saved[i]; ++i)
|
||||
free((genericptr_t) saved[i]);
|
||||
free((genericptr_t) saved);
|
||||
}
|
||||
}
|
||||
@@ -4260,7 +4231,7 @@ recover_savefile(void)
|
||||
int processed[256];
|
||||
char savename[SAVESIZE], errbuf[BUFSZ], indicator;
|
||||
struct savefile_info sfi;
|
||||
char tmpplbuf[PL_NSIZ];
|
||||
char tmpplbuf[PL_NSIZ_PLUS];
|
||||
const char *savewrite_failure = (const char *) 0;
|
||||
|
||||
for (lev = 0; lev < 256; lev++)
|
||||
@@ -4307,7 +4278,7 @@ recover_savefile(void)
|
||||
!= sizeof version_data)
|
||||
|| (read(gnhfp->fd, (genericptr_t) &sfi, sizeof sfi) != sizeof sfi)
|
||||
|| (read(gnhfp->fd, (genericptr_t) &pltmpsiz, sizeof pltmpsiz)
|
||||
!= sizeof pltmpsiz) || (pltmpsiz > PL_NSIZ)
|
||||
!= sizeof pltmpsiz) || (pltmpsiz > PL_NSIZ_PLUS)
|
||||
|| (read(gnhfp->fd, (genericptr_t) &tmpplbuf, pltmpsiz)
|
||||
!= pltmpsiz)) {
|
||||
raw_printf("\nError reading %s -- can't recover.\n", gl.lock);
|
||||
|
||||
@@ -740,7 +740,7 @@ dorecover(NHFILE *nhfp)
|
||||
/* suppress map display if some part of the code tries to update that */
|
||||
program_state.restoring = REST_GSTATE;
|
||||
|
||||
get_plname_from_file(nhfp, svp.plname);
|
||||
get_plname_from_file(nhfp, svp.plname, TRUE);
|
||||
getlev(nhfp, 0, (xint8) 0);
|
||||
if (!restgamestate(nhfp)) {
|
||||
NHFILE tnhfp;
|
||||
@@ -828,7 +828,7 @@ dorecover(NHFILE *nhfp)
|
||||
restoreinfo.mread_flags = 0;
|
||||
rewind_nhfile(nhfp); /* return to beginning of file */
|
||||
(void) validate(nhfp, (char *) 0, FALSE);
|
||||
get_plname_from_file(nhfp, svp.plname);
|
||||
get_plname_from_file(nhfp, svp.plname, TRUE);
|
||||
|
||||
/* not 0 nor REST_GSTATE nor REST_LEVELS */
|
||||
program_state.restoring = REST_CURRENT_LEVEL;
|
||||
@@ -1245,15 +1245,33 @@ getlev(NHFILE *nhfp, int pid, xint8 lev)
|
||||
program_state.in_getlev = FALSE;
|
||||
}
|
||||
|
||||
/* "name-role-race-gend-algn" occurs very early in a save file; sometimes we
|
||||
want the whole thing, other times just "name" (for svp.plname[]) */
|
||||
void
|
||||
get_plname_from_file(NHFILE *nhfp, char *plbuf)
|
||||
get_plname_from_file(
|
||||
NHFILE *nhfp,
|
||||
char *outbuf, /* size must be at least [PL_NSIZ_PLUS] even if name_only */
|
||||
boolean name_only) /* True: just name; False: name-role-race-gend-algn */
|
||||
{
|
||||
char plbuf[PL_NSIZ_PLUS];
|
||||
int pltmpsiz = 0;
|
||||
|
||||
plbuf[0] = '\0';
|
||||
if (nhfp->structlevel) {
|
||||
(void) read(nhfp->fd, (genericptr_t) &pltmpsiz, sizeof(pltmpsiz));
|
||||
(void) read(nhfp->fd, (genericptr_t) &pltmpsiz, sizeof pltmpsiz);
|
||||
/* pltmpsiz should now be PL_NSIZ_PLUS */
|
||||
(void) read(nhfp->fd, (genericptr_t) plbuf, pltmpsiz);
|
||||
/* plbuf[PL_NSIZ_PLUS-2] should be '\0';
|
||||
plbuf[PL_NSIZ_PLUS-1] should be '-' or 'X' or 'D' */
|
||||
}
|
||||
/* "-race-role-gend-algn" is already present except that it has been
|
||||
hidden by replacing the initial dash with NUL; if we want that
|
||||
information, replace the NUL with a dash */
|
||||
if (!name_only)
|
||||
*eos(plbuf) = '-';
|
||||
/* not simple strcpy(); playmode is in the last slot and could (probably
|
||||
will) be preceded by NULs */
|
||||
(void) memcpy((genericptr_t) outbuf, (genericptr_t) plbuf, PL_NSIZ_PLUS);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1418,7 +1436,8 @@ restore_menu(
|
||||
{
|
||||
winid tmpwin;
|
||||
anything any;
|
||||
char **saved;
|
||||
char **saved, *next, mode, menutext[BUFSZ];
|
||||
boolean all_normal;
|
||||
menu_item *chosen_game = (menu_item *) 0;
|
||||
int k, clet, ch = 0; /* ch: 0 => new game */
|
||||
int clr = NO_COLOR;
|
||||
@@ -1438,19 +1457,35 @@ restore_menu(
|
||||
add_menu_str(tmpwin, "");
|
||||
}
|
||||
add_menu_str(tmpwin, "Select one of your saved games");
|
||||
/* if all the save files have a playmode of '-' then we'll just list
|
||||
their character name-role-race-gend-algn values, but if any are
|
||||
'X' or 'D', we'll list playmode along with name-role-&c values
|
||||
for every entry; first, figure out if they're all normal play */
|
||||
for (all_normal = TRUE, k = 0; all_normal && saved[k]; ++k) {
|
||||
next = saved[k];
|
||||
mode = next[PL_NSIZ_PLUS - 1]; /* fixed last char, beyond '\0' */
|
||||
if (mode != '-')
|
||||
all_normal = FALSE;
|
||||
}
|
||||
for (k = 0; saved[k]; ++k) {
|
||||
any.a_int = k + 1;
|
||||
add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0,
|
||||
ATR_NONE, clr, saved[k], MENU_ITEMFLAGS_NONE);
|
||||
next = saved[k];
|
||||
mode = next[PL_NSIZ_PLUS - 1];
|
||||
if (all_normal)
|
||||
Sprintf(menutext, "%.*s", PL_NSIZ_PLUS - 1, next);
|
||||
else
|
||||
Sprintf(menutext, "%c %.*s", mode, PL_NSIZ_PLUS - 1, next);
|
||||
add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0, ATR_NONE, clr,
|
||||
menutext, MENU_ITEMFLAGS_SKIPMENUCOLORS);
|
||||
}
|
||||
clet = (k <= 'n' - 'a') ? 'n' : 0; /* new game */
|
||||
any.a_int = -1; /* not >= 0 */
|
||||
add_menu(tmpwin, &nul_glyphinfo, &any, clet, 0, ATR_NONE,
|
||||
clr, "Start a new character", MENU_ITEMFLAGS_NONE);
|
||||
add_menu(tmpwin, &nul_glyphinfo, &any, clet, 0, ATR_NONE, clr,
|
||||
"Start a new character", MENU_ITEMFLAGS_NONE);
|
||||
clet = (k + 1 <= 'q' - 'a') ? 'q' : 0; /* quit */
|
||||
any.a_int = -2;
|
||||
add_menu(tmpwin, &nul_glyphinfo, &any, clet, 0, ATR_NONE,
|
||||
clr, "Never mind (quit)", MENU_ITEMFLAGS_SELECTED);
|
||||
add_menu(tmpwin, &nul_glyphinfo, &any, clet, 0, ATR_NONE, clr,
|
||||
"Never mind (quit)", MENU_ITEMFLAGS_SELECTED);
|
||||
/* 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) {
|
||||
|
||||
23
src/save.c
23
src/save.c
@@ -1071,16 +1071,35 @@ savelevchn(NHFILE *nhfp)
|
||||
svs.sp_levchn = 0;
|
||||
}
|
||||
|
||||
/* write "name-role-race-gend-algn" into save file for menu-based restore;
|
||||
the first dash is actually stored as '\0' instead of '-' */
|
||||
void
|
||||
store_plname_in_file(NHFILE *nhfp)
|
||||
{
|
||||
int plsiztmp = PL_NSIZ;
|
||||
char hero[PL_NSIZ_PLUS]; /* [PL_NSIZ + 4*4 + 1] */
|
||||
int plsiztmp = (int) sizeof hero;
|
||||
|
||||
(void) memset((genericptr_t) hero, '\0', sizeof hero);
|
||||
/* augment svp.plname[]; the gender and alignment values reflect those
|
||||
in effect at time of saving rather than at start of game */
|
||||
Snprintf(hero, sizeof hero, "%s-%.3s-%.3s-%.3s-%.3s",
|
||||
svp.plname, gu.urole.filecode,
|
||||
gu.urace.filecode, genders[flags.female].filecode,
|
||||
aligns[1 - u.ualign.type].filecode);
|
||||
/* replace "-role-race..." with "\0role-race..." so that we can include
|
||||
or exclude the role-&c suffix easily, without worrying about whether
|
||||
plname contains any dashes; but don't rely on snprintf() for this */
|
||||
hero[strlen(svp.plname)] = '\0';
|
||||
/* insert playmode into final slot of hero[];
|
||||
'D','X','-' are the same characters as are used for paniclog entries */
|
||||
assert(hero[PL_NSIZ_PLUS - 1 - 1] == '\0');
|
||||
hero[PL_NSIZ_PLUS - 1] = wizard ? 'D' : discover ? 'X' : '-';
|
||||
|
||||
if (nhfp->structlevel) {
|
||||
bufoff(nhfp->fd);
|
||||
/* bwrite() before bufon() uses plain write() */
|
||||
bwrite(nhfp->fd, (genericptr_t) &plsiztmp, sizeof plsiztmp);
|
||||
bwrite(nhfp->fd, (genericptr_t) svp.plname, plsiztmp);
|
||||
bwrite(nhfp->fd, (genericptr_t) hero, plsiztmp);
|
||||
bufon(nhfp->fd);
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -603,8 +603,9 @@ vmscond lib$find_file_end(void **);
|
||||
|
||||
/* collect a list of character names from all save files for this player */
|
||||
int
|
||||
vms_get_saved_games(const char *savetemplate, /* wildcarded save file name in native VMS format */
|
||||
char ***outarray)
|
||||
vms_get_saved_games(
|
||||
const char *savetemplate, /* wildcarded save name in native VMS format */
|
||||
char ***outarray)
|
||||
{
|
||||
struct dsc in, out;
|
||||
unsigned short l;
|
||||
|
||||
Reference in New Issue
Block a user