diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 5354bd565..ad806d427 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -303,6 +303,7 @@ item-using monsters will zap wand of undead turning at corpse-wielding hero when the corpse is harmful boiling a pool or fountain now creates a temporary cloud of steam random themed rooms in the dungeons of doom +extended achievement and conduct fields for xlogfile Platform- and/or Interface-Specific New Features diff --git a/src/topten.c b/src/topten.c index c1ef77f32..f83e52b51 100644 --- a/src/topten.c +++ b/src/topten.c @@ -11,10 +11,10 @@ #include "patchlevel.h" #endif -/* If UPDATE_RECORD_IN_PLACE is defined, we don't want to rewrite the - * whole file, because that entails creating a new version which +/* If UPDATE_RECORD_IN_PLACE is defined, we don't want to rewrite the + * whole file, because that entails creating a new version which * requires that the old one be deletable. UPDATE_RECORD_IN_PLACE - * had to be defined more centrally in 3.7 to ensure that the + * had to be defined more centrally in 3.7 to ensure that the * final_fpos field gets included in struct instance_globals aka 'g'. */ @@ -71,6 +71,9 @@ static void FDECL(writexlentry, (FILE *, struct toptenentry *, int)); static long NDECL(encodexlogflags); static long NDECL(encodeconduct); static long FDECL(encodeachieve, (BOOLEAN_P)); +static void FDECL(add_achieveX, (char *, const char *, BOOLEAN_P)); +static char *NDECL(encode_extended_achievements); +static char *NDECL(encode_extended_conducts); #endif static void FDECL(free_ttlist, (struct toptenentry *)); static int FDECL(classmon, (char *, BOOLEAN_P)); @@ -367,6 +370,8 @@ int how; Fprintf(rfile, "%cconduct=0x%lx%cturns=%ld%cachieve=0x%lx", XLOG_SEP, encodeconduct(), XLOG_SEP, g.moves, XLOG_SEP, encodeachieve(FALSE)); + Fprintf(rfile, "%cachieveX=%s", XLOG_SEP, encode_extended_achievements()); + Fprintf(rfile, "%cconductX=%s", XLOG_SEP, encode_extended_conducts()); Fprintf(rfile, "%crealtime=%ld%cstarttime=%ld%cendtime=%ld", XLOG_SEP, (long) urealtime.realtime, XLOG_SEP, (long) ubirthday, XLOG_SEP, (long) urealtime.finish_time); @@ -450,6 +455,127 @@ boolean secondlong; /* False: handle achievements 1..31, True: 32..62 */ return r; } +/* add the achievement or conduct comma-separated to string */ +static void +add_achieveX(buf, achievement, condition) +char *buf; +const char *achievement; +boolean condition; +{ + if (condition) { + if (buf[0] != '\0') { + Strcat(buf, ","); + } + Strcat(buf, achievement); + } +} + +static char * +encode_extended_achievements() +{ + static char buf[N_ACH*40]; + const char *achievement = NULL; + int i; + + buf[0] = '\0'; + for (i = 0; u.uachieved[i]; i++) { + switch (u.uachieved[i]) { + case ACH_UWIN: + achievement = "ascended"; + break; + case ACH_ASTR: + achievement = "entered_astral_plane"; + break; + case ACH_ENDG: + achievement = "entered_elemental_planes"; + break; + case ACH_AMUL: + achievement = "obtained_the_amulet_of_yendor"; + break; + case ACH_INVK: + achievement = "performed_the_invocation_ritual"; + break; + case ACH_BOOK: + achievement = "obtained_the_book_of_the_dead"; + break; + case ACH_BELL: + achievement = "obtained_the_bell_of_opening"; + break; + case ACH_CNDL: + achievement = "obtained_the_candelabrum_of_invocation"; + break; + case ACH_HELL: + achievement = "entered_gehennom"; + break; + case ACH_MEDU: + achievement = "defeated_medusa"; + break; + case ACH_MINE_PRIZE: + achievement = "obtained_the_luckstone_from_the_mines"; + break; + case ACH_SOKO_PRIZE: + achievement = "obtained_the_sokoban_prize"; + break; + + case ACH_ORCL: + achievement = "consulted_the_oracle"; + break; + case ACH_NOVL: + achievement = "read_a_discworld_novel"; + break; + case ACH_MINE: + achievement = "entered_the_gnomish_mines"; + break; + case ACH_TOWN: + achievement = "entered_mine_town"; + break; + case ACH_SHOP: + achievement = "entered_a_shop"; + break; + case ACH_TMPL: + achievement = "entered_a_temple"; + break; + case ACH_SOKO: + achievement = "entered_sokoban"; + break; + case ACH_BGRM: + achievement = "entered_bigroom"; + break; + default: + continue; + } + add_achieveX(buf, achievement, TRUE); + } + + return buf; +} + +static char * +encode_extended_conducts() +{ + static char buf[BUFSZ]; + const char *achievement = NULL; + int i; + + buf[0] = '\0'; + add_achieveX(buf, "foodless", !u.uconduct.food); + add_achieveX(buf, "vegan", !u.uconduct.unvegan); + add_achieveX(buf, "vegetarian", !u.uconduct.unvegetarian); + add_achieveX(buf, "atheist", !u.uconduct.gnostic); + add_achieveX(buf, "weaponless", !u.uconduct.weaphit); + add_achieveX(buf, "pacifist", !u.uconduct.killer); + add_achieveX(buf, "illiterate", !u.uconduct.literate); + add_achieveX(buf, "polyless", !u.uconduct.polypiles); + add_achieveX(buf, "polyselfless", !u.uconduct.polyselfs); + add_achieveX(buf, "wishless", !u.uconduct.wishes); + add_achieveX(buf, "artiwishless", !u.uconduct.wisharti); + add_achieveX(buf, "genocideless", !num_genocides()); + add_achieveX(buf, "blind", u.uroleplay.blind); + add_achieveX(buf, "nudist", u.uroleplay.nudist); + + return buf; +} + #endif /* XLOGFILE */ static void