[PATCH] Extended logfile, v2
- From: Aardvark Joe <aardvarkjoe@xxxxxxxxxxx>
- Date: Wed, 10 Aug 2005 21:32:48 GMT
This is an update to the extended logfile patch that I posted last
December, fixing all of the issues that I managed to find in the
original version, and taking some of the suggestions made when I
first posted it.
The short description is that this patch causes the game to create
another logfile that is more verbose, flexible, and easy to parse than
the standard logfile. It also logs a few more things that are not
included in the normal logfile (except through other patches): the
number of turns taken, the conducts followed, the amount of real time
(in seconds) spent playing, and whether the player reached some
important milestones during his game.
The notable changes between this version and the original are:
- The events recorded by RECORD_ACHIEVE were altered, based on the
comments made by several people when I first announced the patch.
- A new option to display elapsed time on the bottom line was added.
(This is disabled by default.)
- The achievement flags were moved so that bones files are not
needlessly invalidated.
- The conduct and achievement bitfields are stored in hex rather than
decimal format.
- The RECORD_REALTIME option now stores the correct time when
checkpointing, so a crash/recover is handled properly.
Bones files should be compatible after applying this patch; however,
save files will not be compatible if any of RECORD_ACHIEVE,
RECORD_REALTIME, or REALTIME_ON_BOTL are defined. As always, back up
your nethack directory before attempting to install a patched version.
A readme is included inside the patch with all of the boring details.
If anyone has any comments on how it might be improved, I'm all ears.
I am attaching the patch here, because my old homepage was hosted at my
school, and I'm no longer a student there. Is there anyone who would be
willing to donate some space to host it?
aardvark
aardvarkjoe@xxxxxxxxxxx
--- xlog.patch
diff -urN nethack-3.4.3/include/config.h nethack-3.4.3-xlog/include/config.h
--- nethack-3.4.3/include/config.h 2004-12-05 19:49:38.000000000 -0700
+++ nethack-3.4.3-xlog/include/config.h 2005-08-10 08:41:15.000000000 -0700
@@ -151,6 +151,7 @@
#endif
#define LOGFILE "logfile" /* larger file for debugging purposes */
+#define XLOGFILE "xlogfile" /* even larger logfile */
#define NEWS "news" /* the file containing the latest hack news */
#define PANICLOG "paniclog" /* log of panic and impossible events */
@@ -340,6 +341,21 @@
#define EXP_ON_BOTL /* Show experience on bottom line */
/* #define SCORE_ON_BOTL */ /* added by Gary Erickson (erickson@ucivax) */
+/* #define REALTIME_ON_BOTL */ /* Show elapsed time on bottom line. Note:
+ * this breaks savefile compatibility. */
+
+/* The options in this section require the extended logfile support */
+#ifdef XLOGFILE
+#define RECORD_CONDUCT /* Record conducts kept in logfile */
+#define RECORD_TURNS /* Record turns elapsed in logfile */
+#define RECORD_ACHIEVE /* Record certain notable achievements in the
+ * logfile. Note: this breaks savefile compatibility
+ * due to the addition of the u_achieve struct. */
+#define RECORD_REALTIME /* Record the amount of actual playing time (in
+ * seconds) in the record file. Note: this breaks
+ * savefile compatibility. */
+#endif
+
/*
* Section 5: EXPERIMENTAL STUFF
*
diff -urN nethack-3.4.3/include/decl.h nethack-3.4.3-xlog/include/decl.h
--- nethack-3.4.3/include/decl.h 2004-12-05 19:49:38.000000000 -0700
+++ nethack-3.4.3-xlog/include/decl.h 2005-07-28 16:32:01.000000000 -0700
@@ -385,6 +385,36 @@
};
#endif /* AUTOPICKUP_EXCEPTIONS */
+#ifdef RECORD_ACHIEVE
+struct u_achieve {
+ Bitfield(get_bell,1); /* You have obtained the bell of
+ * opening */
+ Bitfield(get_candelabrum,1); /* You have obtained the candelabrum */
+ Bitfield(get_book,1); /* You have obtained the book of
+ * the dead */
+ Bitfield(enter_gehennom,1); /* Entered Gehennom (including the
+ * Valley) by any means */
+ Bitfield(perform_invocation,1); /* You have performed the invocation
+ * ritual */
+ Bitfield(get_amulet,1); /* You have obtained the amulet
+ * of Yendor */
+ Bitfield(ascended,1); /* You ascended to demigod[dess]hood.
+ * Not quite the same as
+ * u.uevent.ascended. */
+};
+
+E struct u_achieve achieve;
+#endif
+
+#if defined(RECORD_REALTIME) || defined(REALTIME_ON_BOTL)
+E struct realtime_data {
+ time_t realtime; /* Amount of actual playing time up until the last time
+ * the game was restored. */
+ time_t restoretime; /* The time that the game was started or restored. */
+ time_t last_displayed_time; /* Last time displayed on the status line */
+} realtime_data;
+#endif /* RECORD_REALTIME || REALTIME_ON_BOTL */
+
#undef E
#endif /* DECL_H */
diff -urN nethack-3.4.3/include/extern.h nethack-3.4.3-xlog/include/extern.h
--- nethack-3.4.3/include/extern.h 2004-12-05 19:49:38.000000000 -0700
+++ nethack-3.4.3-xlog/include/extern.h 2005-08-10 08:41:15.000000000 -0700
@@ -25,6 +25,9 @@
E void NDECL(display_gamewindows);
E void NDECL(newgame);
E void FDECL(welcome, (BOOLEAN_P));
+#if defined(RECORD_REALTIME) || defined(REALTIME_ON_BOTL)
+E time_t NDECL(get_realtime);
+#endif
/* ### apply.c ### */
diff -urN nethack-3.4.3/include/flag.h nethack-3.4.3-xlog/include/flag.h
--- nethack-3.4.3/include/flag.h 2004-12-05 19:49:38.000000000 -0700
+++ nethack-3.4.3-xlog/include/flag.h 2005-07-28 11:49:48.000000000 -0700
@@ -280,6 +280,9 @@
#define MAX_ALTKEYHANDLER 25
char altkeyhandler[MAX_ALTKEYHANDLER];
#endif
+#ifdef REALTIME_ON_BOTL
+ boolean showrealtime; /* show actual elapsed time */
+#endif
};
/*
diff -urN nethack-3.4.3/parsexlog.pl nethack-3.4.3-xlog/parsexlog.pl
--- nethack-3.4.3/parsexlog.pl 1969-12-31 17:00:00.000000000 -0700
+++ nethack-3.4.3-xlog/parsexlog.pl 2005-08-10 08:41:15.000000000 -0700
@@ -0,0 +1,71 @@
+#!/usr/bin/perl
+
+# Dungeon names
+%dungeons = ( 0 => "the Dungeons of Doom",
+ 1 => "Gehennom",
+ 2 => "the Gnomish Mines",
+ 3 => "the Quest",
+ 4 => "Sokoban",
+ 5 => "Fort Ludios",
+ 6 => "Vlad's Tower",
+ 7 => "the Elemental Planes" );
+
+# Conducts, in the order that they are stored in the conduct bitfield
+@conducts = ( "Foodless", "Vegan", "Vegetarian", "Atheist", "Weaponless",
+ "Pacifist", "Illiterate", "Polypileless", "Polyselfless",
+ "Wishless", "Artifact Wishless", "Genocideless" );
+
+# Achievements, in the order that they are stored in the achievement
+# bitfield
+@achievements = ( "Obtained the Bell of Opening",
+ "Entered Gehennom",
+ "Obtained the Candelabrum of Invocation",
+ "Obtained the Book of the Dead",
+ "Performed the invocation ritual",
+ "Obtained the Amulet of Yendor",
+ "Reached the Elemental Planes",
+ "Reached the Astral Plane",
+ "Ascended" );
+
+while($entry = <>) {
+ # Parse the line and store in the hash %field
+ @fields = split /:/, $entry;
+
+ foreach $field (@fields) {
+ if($field =~ /^([^=]*)=(.*)$/) {
+ $fname = $1;
+ $fval = $2;
+ $field{$fname} = $fval;
+ }
+ }
+
+ # Display
+ printf "%s-%s-%s-%s-%s, %s\n", $field{name},
+ $field{role}, $field{race}, $field{gender}, $field{align},
+ $field{death};
+ printf " Died in %s on level %d (max %d). Final HP %d/%d.\n",
+ $dungeons{$field{deathdnum}}, $field{deathlev}, $field{maxlvl},
+ $field{hp}, $field{maxhp};
+
+ @c = ();
+ $field{conduct} = oct $field{conduct};
+ for($i = 0; $i <= $#conducts; $i++) {
+ if($field{conduct} & (1 << $i)) {
+ push @c, $conducts[$i];
+ }
+ }
+ print " Conducts: ", join(', ', @c), "\n";
+
+ @a = ();
+ $field{achieve} = oct $field{achieve};
+ for($i = 0; $i <= $#achievements; $i++) {
+ if($field{achieve} & (1 << $i)) {
+ push @a, $achievements[$i];
+ }
+ }
+ print " Notable achievements: ", join(', ', @a), "\n";
+
+
+ printf " The game lasted %d turns, and took %d seconds of playtime.\n",
+ $field{turns}, $field{realtime};
+}
diff -urN nethack-3.4.3/src/allmain.c nethack-3.4.3-xlog/src/allmain.c
--- nethack-3.4.3/src/allmain.c 2004-12-05 19:49:38.000000000 -0700
+++ nethack-3.4.3-xlog/src/allmain.c 2005-08-10 09:01:13.000000000 -0700
@@ -316,6 +316,16 @@
if (vision_full_recalc) vision_recalc(0); /* vision! */
}
+
+#ifdef REALTIME_ON_BOTL
+ if(iflags.showrealtime) {
+ /* Update the bottom line if the number of minutes has
+ * changed */
+ if(get_realtime() / 60 != realtime_data.last_displayed_time / 60)
+ flags.botl = 1;
+ }
+#endif
+
if(flags.botl || flags.botlx) bot();
flags.move = 1;
@@ -537,6 +547,19 @@
#endif
program_state.something_worth_saving++; /* useful data now exists */
+#if defined(RECORD_REALTIME) || defined(REALTIME_ON_BOTL)
+
+ /* Start the timer here */
+ realtime_data.realtime = (time_t)0L;
+
+#if defined(BSD) && !defined(POSIX_TYPES)
+ (void) time((long *)&realtime_data.restoretime);
+#else
+ (void) time(&realtime_data.restoretime);
+#endif
+
+#endif /* RECORD_REALTIME || REALTIME_ON_BOTL */
+
/* Success! */
welcome(TRUE);
return;
@@ -628,6 +651,33 @@
}
#endif
+#if defined(REALTIME_ON_BOTL) || defined (RECORD_REALTIME)
+time_t
+get_realtime(void)
+{
+ time_t curtime;
+
+ /* Calculate current time */
+#if defined(BSD) && !defined(POSIX_TYPES)
+ (void) time((long *)&curtime);
+#else
+ (void) time(&curtime);
+#endif
+
+ /* Since the timer isn't set until the game starts, this prevents us
+ * from displaying nonsense on the bottom line before it does. */
+ if(realtime_data.restoretime == 0) {
+ curtime = realtime_data.realtime;
+ } else {
+ curtime -= realtime_data.restoretime;
+ curtime += realtime_data.realtime;
+ }
+
+ return curtime;
+}
+#endif /* REALTIME_ON_BOTL || RECORD_REALTIME */
+
+
#endif /* OVLB */
/*allmain.c*/
diff -urN nethack-3.4.3/src/botl.c nethack-3.4.3-xlog/src/botl.c
--- nethack-3.4.3/src/botl.c 2004-12-05 19:49:38.000000000 -0700
+++ nethack-3.4.3-xlog/src/botl.c 2005-07-28 16:32:01.000000000 -0700
@@ -275,6 +275,15 @@
if(flags.time)
Sprintf(nb = eos(nb), " T:%ld", moves);
+
+#ifdef REALTIME_ON_BOTL
+ if(iflags.showrealtime) {
+ time_t currenttime = get_realtime();
+ Sprintf(nb = eos(nb), " %d:%2.2d", currenttime / 3600,
+ (currenttime % 3600) / 60);
+ }
+#endif
+
if(strcmp(hu_stat[u.uhs], " ")) {
Sprintf(nb = eos(nb), " ");
Strcat(newbot2, hu_stat[u.uhs]);
diff -urN nethack-3.4.3/src/decl.c nethack-3.4.3-xlog/src/decl.c
--- nethack-3.4.3/src/decl.c 2004-12-05 19:49:38.000000000 -0700
+++ nethack-3.4.3-xlog/src/decl.c 2005-07-28 16:32:01.000000000 -0700
@@ -271,6 +271,14 @@
"lockdir", "configdir", "troubledir" };
#endif
+#ifdef RECORD_ACHIEVE
+struct u_achieve achieve = DUMMY;
+#endif
+
+#if defined(RECORD_REALTIME) || defined(REALTIME_ON_BOTL)
+struct realtime_data realtime_data = { 0, 0, 0 };
+#endif
+
/* dummy routine used to force linkage */
void
decl_init()
diff -urN nethack-3.4.3/src/do.c nethack-3.4.3-xlog/src/do.c
--- nethack-3.4.3/src/do.c 2004-12-05 19:49:38.000000000 -0700
+++ nethack-3.4.3-xlog/src/do.c 2004-12-13 13:03:16.000000000 -0700
@@ -1283,6 +1283,10 @@
#endif
You_hear("groans and moans everywhere.");
} else pline("It is hot here. You smell smoke...");
+
+#ifdef RECORD_ACHIEVE
+ achieve.enter_gehennom = 1;
+#endif
}
if (familiar) {
diff -urN nethack-3.4.3/src/end.c nethack-3.4.3-xlog/src/end.c
--- nethack-3.4.3/src/end.c 2004-12-05 19:49:38.000000000 -0700
+++ nethack-3.4.3-xlog/src/end.c 2005-07-28 16:32:01.000000000 -0700
@@ -620,6 +620,12 @@
it's gone prior to inventory disclosure and creation of bones data */
inven_inuse(TRUE);
+#ifdef RECORD_REALTIME
+ /* Update the realtime counter to reflect the playtime of the current
+ * game. */
+ realtime_data.realtime = get_realtime();
+#endif /* RECORD_REALTIME */
+
/* Sometimes you die on the first move. Life's not fair.
* On those rare occasions you get hosed immediately, go out
* smiling... :-) -3.
diff -urN nethack-3.4.3/src/invent.c nethack-3.4.3-xlog/src/invent.c
--- nethack-3.4.3/src/invent.c 2004-12-05 19:49:38.000000000 -0700
+++ nethack-3.4.3-xlog/src/invent.c 2004-12-13 15:23:47.000000000 -0700
@@ -253,15 +253,27 @@
} else if (obj->otyp == AMULET_OF_YENDOR) {
if (u.uhave.amulet) impossible("already have amulet?");
u.uhave.amulet = 1;
+#ifdef RECORD_ACHIEVE
+ achieve.get_amulet = 1;
+#endif
} else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
if (u.uhave.menorah) impossible("already have candelabrum?");
u.uhave.menorah = 1;
+#ifdef RECORD_ACHIEVE
+ achieve.get_candelabrum = 1;
+#endif
} else if (obj->otyp == BELL_OF_OPENING) {
if (u.uhave.bell) impossible("already have silver bell?");
u.uhave.bell = 1;
+#ifdef RECORD_ACHIEVE
+ achieve.get_bell = 1;
+#endif
} else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
if (u.uhave.book) impossible("already have the book?");
u.uhave.book = 1;
+#ifdef RECORD_ACHIEVE
+ achieve.get_book = 1;
+#endif
} else if (obj->oartifact) {
if (is_quest_artifact(obj)) {
if (u.uhave.questart)
diff -urN nethack-3.4.3/src/mklev.c nethack-3.4.3-xlog/src/mklev.c
--- nethack-3.4.3/src/mklev.c 2004-12-05 19:49:38.000000000 -0700
+++ nethack-3.4.3-xlog/src/mklev.c 2004-12-05 20:08:03.000000000 -0700
@@ -1462,6 +1462,10 @@
mkstairs(u.ux, u.uy, 0, (struct mkroom *)0); /* down */
newsym(u.ux, u.uy);
vision_full_recalc = 1; /* everything changed */
+
+#ifdef RECORD_ACHIEVE
+ achieve.perform_invocation = 1;
+#endif
}
/* Change level topology. Boulders in the vicinity are eliminated.
diff -urN nethack-3.4.3/src/options.c nethack-3.4.3-xlog/src/options.c
--- nethack-3.4.3/src/options.c 2004-12-05 19:49:38.000000000 -0700
+++ nethack-3.4.3-xlog/src/options.c 2005-07-28 11:49:48.000000000 -0700
@@ -166,6 +166,9 @@
{"showexp", (boolean *)0, FALSE, SET_IN_FILE},
#endif
{"showrace", &iflags.showrace, FALSE, SET_IN_GAME},
+#ifdef REALTIME_ON_BOTL
+ {"showrealtime", &iflags.showrealtime, FALSE, SET_IN_GAME},
+#endif
#ifdef SCORE_ON_BOTL
{"showscore", &flags.showscore, FALSE, SET_IN_GAME},
#else
diff -urN nethack-3.4.3/src/pray.c nethack-3.4.3-xlog/src/pray.c
--- nethack-3.4.3/src/pray.c 2004-12-05 19:49:38.000000000 -0700
+++ nethack-3.4.3-xlog/src/pray.c 2004-12-13 13:03:16.000000000 -0700
@@ -1287,6 +1287,11 @@
done(ESCAPED);
} else { /* super big win */
adjalign(10);
+
+#ifdef RECORD_ACHIEVE
+ achieve.ascended = 1;
+#endif
+
pline("An invisible choir sings, and you are bathed in radiance...");
godvoice(altaralign, "Congratulations, mortal!");
display_nhwindow(WIN_MESSAGE, FALSE);
diff -urN nethack-3.4.3/src/restore.c nethack-3.4.3-xlog/src/restore.c
--- nethack-3.4.3/src/restore.c 2004-12-05 19:49:38.000000000 -0700
+++ nethack-3.4.3-xlog/src/restore.c 2005-07-28 16:32:01.000000000 -0700
@@ -445,6 +445,15 @@
restnames(fd);
restore_waterlevel(fd);
+
+#ifdef RECORD_ACHIEVE
+ mread(fd, (genericptr_t) &achieve, sizeof achieve);
+#endif
+#if defined(RECORD_REALTIME) || defined(REALTIME_ON_BOTL)
+ mread(fd, (genericptr_t) &realtime_data.realtime,
+ sizeof realtime_data.realtime);
+#endif
+
/* must come after all mons & objs are restored */
relink_timers(FALSE);
relink_light_sources(FALSE);
@@ -676,6 +685,17 @@
clear_nhwindow(WIN_MESSAGE);
program_state.something_worth_saving++; /* useful data now exists */
+#if defined(RECORD_REALTIME) || defined(REALTIME_ON_BOTL)
+
+/* Start the timer here (realtime has already been set) */
+#if defined(BSD) && !defined(POSIX_TYPES)
+ (void) time((long *)&realtime_data.restoretime);
+#else
+ (void) time(&realtime_data.restoretime);
+#endif
+
+#endif /* RECORD_REALTIME || REALTIME_ON_BOTL */
+
/* Success! */
welcome(FALSE);
return(1);
diff -urN nethack-3.4.3/src/save.c nethack-3.4.3-xlog/src/save.c
--- nethack-3.4.3/src/save.c 2004-12-05 19:49:38.000000000 -0700
+++ nethack-3.4.3-xlog/src/save.c 2005-07-28 16:32:01.000000000 -0700
@@ -210,6 +210,7 @@
#ifdef STEED
usteed_id = (u.usteed ? u.usteed->m_id : 0);
#endif
+
savelev(fd, ledger_no(&u.uz), WRITE_SAVE | FREE_SAVE);
savegamestate(fd, WRITE_SAVE | FREE_SAVE);
@@ -274,6 +275,10 @@
register int fd, mode;
{
int uid;
+#if defined(RECORD_REALTIME) || defined(REALTIME_ON_BOTL)
+ time_t realtime;
+#endif
+
#ifdef MFLOPPY
count_only = (mode & COUNT_SAVE);
@@ -319,6 +324,15 @@
savefruitchn(fd, mode);
savenames(fd, mode);
save_waterlevel(fd, mode);
+
+#ifdef RECORD_ACHIEVE
+ bwrite(fd, (genericptr_t) &achieve, sizeof achieve);
+#endif
+#if defined(RECORD_REALTIME) || defined(REALTIME_ON_BOTL)
+ realtime = get_realtime();
+ bwrite(fd, (genericptr_t) &realtime, sizeof realtime);
+#endif
+
bflush(fd);
}
diff -urN nethack-3.4.3/src/topten.c nethack-3.4.3-xlog/src/topten.c
--- nethack-3.4.3/src/topten.c 2004-12-05 19:49:38.000000000 -0700
+++ nethack-3.4.3-xlog/src/topten.c 2005-08-10 08:41:15.000000000 -0700
@@ -66,10 +66,20 @@
STATIC_DCL void FDECL(outentry, (int,struct toptenentry *,BOOLEAN_P));
STATIC_DCL void FDECL(readentry, (FILE *,struct toptenentry *));
STATIC_DCL void FDECL(writeentry, (FILE *,struct toptenentry *));
+#ifdef XLOGFILE
+STATIC_DCL void FDECL(munge_xlstring, (char *dest, char *src, int n));
+STATIC_DCL void FDECL(write_xlentry, (FILE *,struct toptenentry *));
+#endif
STATIC_DCL void FDECL(free_ttlist, (struct toptenentry *));
STATIC_DCL int FDECL(classmon, (char *,BOOLEAN_P));
STATIC_DCL int FDECL(score_wanted,
(BOOLEAN_P, int,struct toptenentry *,int,const char **,int));
+#ifdef RECORD_CONDUCT
+STATIC_DCL long FDECL(encodeconduct, (void));
+#endif
+#ifdef RECORD_ACHIEVE
+STATIC_DCL long FDECL(encodeachieve, (void));
+#endif
#ifdef NO_SCAN_BRACK
STATIC_DCL void FDECL(nsb_mung_line,(char*));
STATIC_DCL void FDECL(nsb_unmung_line,(char*));
@@ -226,6 +236,95 @@
#endif
}
+#ifdef XLOGFILE
+#define SEP ":"
+#define SEPC ':'
+
+/* copy a maximum of n-1 characters from src to dest, changing ':' and '\n'
+ * to '_'; always null-terminate. */
+STATIC_OVL void
+munge_xlstring(dest, src, n)
+char *dest;
+char *src;
+int n;
+{
+ int i;
+
+ for(i = 0; i < (n - 1) && src[i] != '\0'; i++) {
+ if(src[i] == SEPC || src[i] == '\n')
+ dest[i] = '_';
+ else
+ dest[i] = src[i];
+ }
+
+ dest[i] = '\0';
+
+ return;
+}
+
+STATIC_OVL void
+write_xlentry(rfile,tt)
+FILE *rfile;
+struct toptenentry *tt;
+{
+
+ char buf[DTHSZ+1];
+
+ /* Log all of the data found in the regular logfile */
+ (void)fprintf(rfile,
+ "version=%d.%d.%d"
+ SEP "points=%ld"
+ SEP "deathdnum=%d"
+ SEP "deathlev=%d"
+ SEP "maxlvl=%d"
+ SEP "hp=%d"
+ SEP "maxhp=%d"
+ SEP "deaths=%d"
+ SEP "deathdate=%d"
+ SEP "birthdate=%d"
+ SEP "uid=%d",
+ tt->ver_major, tt->ver_minor, tt->patchlevel,
+ tt->points, tt->deathdnum, tt->deathlev,
+ tt->maxlvl, tt->hp, tt->maxhp, tt->deaths,
+ tt->deathdate, tt->birthdate, tt->uid);
+
+ (void)fprintf(rfile,
+ SEP "role=%s"
+ SEP "race=%s"
+ SEP "gender=%s"
+ SEP "align=%s",
+ tt->plrole, tt->plrace, tt->plgend, tt->plalign);
+
+ munge_xlstring(buf, plname, DTHSZ + 1);
+ (void)fprintf(rfile, SEP "name=%s", buf);
+
+ munge_xlstring(buf, tt->death, DTHSZ + 1);
+ (void)fprintf(rfile, SEP "death=%s", buf);
+
+#ifdef RECORD_CONDUCT
+ (void)fprintf(rfile, SEP "conduct=0x%lx", encodeconduct());
+#endif
+
+#ifdef RECORD_TURNS
+ (void)fprintf(rfile, SEP "turns=%ld", moves);
+#endif
+
+#ifdef RECORD_ACHIEVE
+ (void)fprintf(rfile, SEP "achieve=0x%lx", encodeachieve());
+#endif
+
+#ifdef RECORD_REALTIME
+ (void)fprintf(rfile, SEP "realtime=%ld", (long)realtime_data.realtime);
+#endif
+
+ (void)fprintf(rfile, "\n");
+
+}
+
+#undef SEP
+#undef SEPC
+#endif /* XLOGFILE */
+
STATIC_OVL void
free_ttlist(tt)
struct toptenentry *tt;
@@ -255,6 +354,9 @@
#ifdef LOGFILE
FILE *lfile;
#endif /* LOGFILE */
+#ifdef XLOGFILE
+ FILE *xlfile;
+#endif /* XLOGFILE */
/* Under DICE 3.0, this crashes the system consistently, apparently due to
* corruption of *rfile somewhere. Until I figure this out, just cut out
@@ -350,6 +452,18 @@
}
#endif /* LOGFILE */
+#ifdef XLOGFILE
+ if(lock_file(XLOGFILE, SCOREPREFIX, 10)) {
+ if(!(xlfile = fopen_datafile(XLOGFILE, "a", SCOREPREFIX))) {
+ HUP raw_print("Cannot open extended log file!");
+ } else {
+ write_xlentry(xlfile, t0);
+ (void) fclose(xlfile);
+ }
+ unlock_file(XLOGFILE);
+ }
+#endif /* XLOGFILE */
+
if (wizard || discover) {
if (how != PANICKED) HUP {
char pbuf[BUFSZ];
@@ -735,6 +849,64 @@
return 0;
}
+#ifdef RECORD_CONDUCT
+long
+encodeconduct(void)
+{
+ long e = 0L;
+
+ if(!u.uconduct.food) e |= 0x001L;
+ if(!u.uconduct.unvegan) e |= 0x002L;
+ if(!u.uconduct.unvegetarian) e |= 0x004L;
+ if(!u.uconduct.gnostic) e |= 0x008L;
+ if(!u.uconduct.weaphit) e |= 0x010L;
+ if(!u.uconduct.killer) e |= 0x020L;
+ if(!u.uconduct.literate) e |= 0x040L;
+ if(!u.uconduct.polypiles) e |= 0x080L;
+ if(!u.uconduct.polyselfs) e |= 0x100L;
+ if(!u.uconduct.wishes) e |= 0x200L;
+ if(!u.uconduct.wisharti) e |= 0x400L;
+ if(!num_genocides()) e |= 0x800L;
+
+ return e;
+}
+#endif
+
+#ifdef RECORD_ACHIEVE
+long
+encodeachieve(void)
+{
+ /* Achievement bitfield:
+ * bit meaning
+ * 0 obtained the Bell of Opening
+ * 1 entered gehennom (by any means)
+ * 2 obtained the Candelabrum of Invocation
+ * 3 obtained the Book of the Dead
+ * 4 performed the invocation ritual
+ * 5 obtained the amulet
+ * 6 entered elemental planes
+ * 7 entered astral plane
+ * 8 ascended (not "escaped in celestial disgrace!")
+ */
+
+ long r;
+
+ r = 0;
+
+ if(achieve.get_bell) r |= 1L << 0;
+ if(achieve.enter_gehennom) r |= 1L << 1;
+ if(achieve.get_candelabrum) r |= 1L << 2;
+ if(achieve.get_book) r |= 1L << 3;
+ if(achieve.perform_invocation) r |= 1L << 4;
+ if(achieve.get_amulet) r |= 1L << 5;
+ if(In_endgame(&u.uz)) r |= 1L << 6;
+ if(Is_astralevel(&u.uz)) r |= 1L << 7;
+ if(achieve.ascended) r |= 1L << 8;
+
+ return r;
+}
+#endif
+
/*
* print selected parts of score list.
* argc >= 2, with argv[0] untrustworthy (directory names, et al.),
diff -urN nethack-3.4.3/sys/unix/Makefile.top nethack-3.4.3-xlog/sys/unix/Makefile.top
--- nethack-3.4.3/sys/unix/Makefile.top 2004-12-05 19:49:38.000000000 -0700
+++ nethack-3.4.3-xlog/sys/unix/Makefile.top 2004-12-05 20:08:03.000000000 -0700
@@ -243,10 +243,10 @@
# set up the game files
( $(MAKE) dofiles )
# set up some additional files
- touch $(VARDIR)/perm $(VARDIR)/record $(VARDIR)/logfile
- -( cd $(VARDIR) ; $(CHOWN) $(GAMEUID) perm record logfile ; \
- $(CHGRP) $(GAMEGRP) perm record logfile ; \
- chmod $(FILEPERM) perm record logfile )
+ touch $(VARDIR)/perm $(VARDIR)/record $(VARDIR)/logfile $(VARDIR)/xlogfile
+ -( cd $(VARDIR) ; $(CHOWN) $(GAMEUID) perm record logfile xlogfile ; \
+ $(CHGRP) $(GAMEGRP) perm record logfile xlogfile ; \
+ chmod $(FILEPERM) perm record logfile xlogfile )
# and a reminder
@echo You may also want to reinstall the man pages via the doc Makefile.
diff -urN nethack-3.4.3/util/makedefs.c nethack-3.4.3-xlog/util/makedefs.c
--- nethack-3.4.3/util/makedefs.c 2004-12-05 19:49:38.000000000 -0700
+++ nethack-3.4.3-xlog/util/makedefs.c 2005-07-28 12:57:32.000000000 -0700
@@ -652,6 +652,9 @@
#ifdef WIZARD
"debug mode",
#endif
+#ifdef REALTIME_ON_BOTL
+ "elapsed time on status line",
+#endif
#ifdef ELBERETH
"Elbereth",
#endif
@@ -676,6 +679,9 @@
#ifdef LOGFILE
"log file",
#endif
+#ifdef XLOGFILE
+ "extended log file",
+#endif
#ifdef MAIL
"mail daemon",
#endif
@@ -774,6 +780,18 @@
#ifdef ZEROCOMP
"zero-compressed save files",
#endif
+#ifdef RECORD_TURNS
+ "record turns in xlogfile",
+#endif
+#ifdef RECORD_CONDUCT
+ "record conduct in xlogfile",
+#endif
+#ifdef RECORD_ACHIEVE
+ "record major achievements in xlogfile",
+#endif
+#ifdef RECORD_REALTIME
+ "record real time in xlogfile",
+#endif
save_bones_compat_buf,
"basic NetHack features"
};
diff -urN nethack-3.4.3/xlog.readme nethack-3.4.3-xlog/xlog.readme
--- nethack-3.4.3/xlog.readme 1969-12-31 17:00:00.000000000 -0700
+++ nethack-3.4.3-xlog/xlog.readme 2005-07-29 11:21:54.000000000 -0700
@@ -0,0 +1,155 @@
+Extended logfile patch for Nethack 3.4.3
+Version 2
+
+This patch creates a new, more verbose logfile of all of the games
+completed, in order to make interpreting the logfile easier, as well as
+providing a simple way to add new fields to the log. A new file (named, by
+default, 'xlogfile') is created, with each line representing a completed
+game. The format looks something like:
+
+version=3.4.3:points=687:deathdnum=0:deathlev=5:maxlvl=5:hp=0:maxhp=15:deaths=1:
+deathdate=20041202:birthdate=20041202:uid=1:role=Sam:race=Hum:gender=Fem:align=L
+aw:name=aardvark:death=killed by a homunculus:conduct=4047:turns=483:achieve=0:r
+ealtime=166
+
+The standard record and logfile both work the same as usual.
+
+All of the information from the standard logfile is stored in the extended
+logfile. In addition, code to record some extra game data is included.
+
+version - the version of nethack (eg '3.4.3')
+points - the final score
+deathdnum - death dungeon number
+deathlev - death level
+maxlvl - max dungeon level
+hp - final hit points
+maxhp - max hit points
+deaths - number of deaths
+deathdate - the date that the game ended (eg '20041130' is Nov 30, 2004)
+birthdate - the date that the game started
+uid - the player's UID
+role - the player's role (3-letter abbreviation, eg 'Sam')
+race - the player's race (3-letter abbreviation, eg 'Hum')
+gender - the player's gender (3-letter abbreviation, eg 'Mal')
+align - the player's alignment (3-letter abbreviation, eg 'Law')
+name - the player's name
+death - the death string (eg 'killed by a woodchuck')
+
+* turns - The number of turn elapsed during the game
+
+* conduct - The conducts followed during the game
+ The conducts are encoded as a bitfield, with each bit representing one
+ conduct. If a bit is set, then the corresponding conduct was followed
+ during the game. (Note: this is backwards from my original conduct
+ patch, but it seems more natural this way.)
+
+ Bit 1 (0x0001) - Went without food
+ Bit 2 (0x0002) - Strict vegan diet
+ Bit 3 (0x0004) - Vegetarian diet
+ Bit 4 (0x0008) - Atheist
+ Bit 5 (0x0010) - Never hit with a wielded weapon
+ Bit 6 (0x0020) - Pacifist
+ Bit 7 (0x0040) - Illiterate
+ Bit 8 (0x0080) - Never polymorphed an object
+ Bit 9 (0x0100) - Never changed form
+ Bit 10 (0x0200) - Used no wishes
+ Bit 11 (0x0400) - Did not wish for any artifacts
+ Bit 12 (0x0800) - Never genocided any monsters
+
+* realtime - The amount of time spent playing the game
+ Records the time (in seconds) actually spent playing the game. (Or, more
+ accurately, all of the time that nethack is loaded and running the game.)
+ Specifically, the timer is started right before giving the welcome
+ message, and stopped when you save or when the game is over.
+
+ Note that this will invalidate save files, because the current value of
+ the timer is recorded in the save file. Bones files should not be
+ invalidated.
+
+* achieve - Whether or not the player reached certain milestones
+ This is another bitfield that records whether or not certain things were
+ achieved.
+
+ Achievement bitfield:
+ bit meaning
+ 1 obtained the Bell of Opening
+ 2 entered gehennom (by any means)
+ 3 obtained the Candelabrum of Invocation
+ 4 obtained the Book of the Dead
+ 5 performed the invocation ritual
+ 6 obtained the amulet
+ 7 entered elemental planes
+ 8 entered astral plane
+ 9 ascended (not "escaped in celestial disgrace!")
+
+ This will also invalidate save files, as a structure (u_achieve)
+ containing flags corresponding to a few of these achievements is added
+ to the savefile. Bones files should not be invalidated.
+
+The file sys/unix/Makefile.top is modified to add xlogfile to the install
+target. If you are using a different system, you may need to either initially
+create xlogfile, or modify your makefiles appropriately.
+
+Also included in this patch is an option to display the actual elapsed time
+(the time that RECORD_REALTIME logs) on the status line. It is disabled
+by default, so to enable it you can uncomment the definition of
+REALTIME_ON_BOTL in config.h (and then set the flag showrealtime in either
+nethackrc or via the options menu.)
+
+The REALTIME_ON_BOTL option does not depend on XLOGFILE being defined; I
+just added it to the same patch because they share most of the same code.
+It does break savefile compatibility for the same reasons that
+RECORD_REALTIME does.
+
+Breakdown of files changed:
+include/config.h
+ Added a definition for XLOGFILE, the extended logfile filename
+ Added definition of REALTIME_ON_BOTL
+ Added definitions for RECORD_CONDUCT, RECORD_TURNS, RECORD_ACHIEVE,
+ RECORD_REALTIME, in order to give fine-grained control of what should be
+ logged.
+include/decl.h
+ declaration of u_achieve structure and extern definition of achieve
+ declaration of realtime_data structure and extern definition
+include/extern.h
+ declaration of get_realtime function
+include/flag.h
+ added showrealtime to iflags structure
+src/allmain.c
+ update the status line whenever the number of elapsed minutes changes
+ start the realtime timer and store the time that the game started
+ add get_realtime() function to calculate elapsed time
+src/botl.c
+ display elapsed time
+src/decl.c
+ declaration of globals achieve, realtime_data
+src/do.c
+ set enter_gehennom=1 when the player enters gehennom
+src/end.c
+ update the realtime counter when the game ends
+src/invent.c
+ set get_amulet=1, get_candelabrum=1, get_bell=1, and get_book=1 when the
+ corresponding item enters your inventory
+src/mklev.c
+ set perform_invocation=1 when you successfully perform the invocation
+ ritual.
+src/options.c
+ add "showrealtime" option
+src/pray.c
+ set ascended=1 when ascending
+src/restore.c
+ read the stored value of the realtime timer from the savefile, and set the
+ restore time properly
+src/save.c
+ write the elapsed time to the savefile
+src/topten.c
+ add munge_xlstring to convert any ':' in a string to '_'
+ add write_xlentry which writes a single xlogfile entry
+ add encodeconduct which converts the current player's conduct to a number
+ add encodeachieve which converts the game achievements to a number
+ open and write to the xlogfile just after writing to the logfile
+sys/unix/Makefile.top
+ create and set permissions on xlogfile when doing a 'make install'
+util/makedefs.c
+ add entries for XLOGFILE, RECORD_*, and REALTIME_ON_BOTL to
+ build_opts[] list
.
- Prev by Date: Re: YAFAP - Sharyana the Heroine, lawful human female Valkyrie
- Next by Date: YAFAP - Beren Belagund, neutral human male barbarian
- Previous by thread: Some more hearse questions
- Next by thread: YAFAP - Beren Belagund, neutral human male barbarian
- Index(es):
Relevant Pages
|
|