so that disclosing them can use the gender which applied at the time */
ACH_RNK1 = 23, ACH_RNK2 = 24, ACH_RNK3 = 25, ACH_RNK4 = 26,
ACH_RNK5 = 27, ACH_RNK6 = 28, ACH_RNK7 = 29, ACH_RNK8 = 30,
- /* foo=31, 1 available potential achievement; #32 currently off-limits */
+ ACH_TUNE = 31, /* discovered the castle drawbridge's open/close tune */
N_ACH = 32 /* allocate room for 31 plus a slot for 0 terminator */
};
/*
* entered Fort Ludios level/branch (not guaranteed to be achieveable),
* entered Medusa level,
* entered castle level,
- * opened castle drawbridge,
* obtained castle wand (handle similarly to mines and sokoban prizes),
* passed Valley level (entered-Gehennom already covers Valley itself),
* [assorted demon lairs?],
if (!strcmp(buf, g.tune)) {
/* Search for the drawbridge */
for (y = u.uy - 1; y <= u.uy + 1; y++)
- for (x = u.ux - 1; x <= u.ux + 1; x++)
- if (isok(x, y))
- if (find_drawbridge(&x, &y)) {
- /* tune now fully known */
- u.uevent.uheard_tune = 2;
- if (levl[x][y].typ == DRAWBRIDGE_DOWN)
- close_drawbridge(x, y);
- else
- open_drawbridge(x, y);
- return ECMD_TIME;
- }
+ for (x = u.ux - 1; x <= u.ux + 1; x++) {
+ if (!isok(x, y))
+ continue;
+ if (find_drawbridge(&x, &y)) {
+ /* tune now fully known */
+ u.uevent.uheard_tune = 2;
+ record_achievement(ACH_TUNE);
+ if (levl[x][y].typ == DRAWBRIDGE_DOWN)
+ close_drawbridge(x, y);
+ else
+ open_drawbridge(x, y);
+ return ECMD_TIME;
+ }
+ }
} else if (!Deaf) {
if (u.uevent.uheard_tune < 1)
u.uevent.uheard_tune = 1;
/* could only get `gears == 5' by playing five
correct notes followed by excess; otherwise,
tune would have matched above */
- if (gears == 5)
+ if (gears == 5) {
u.uevent.uheard_tune = 2;
+ record_achievement(ACH_TUNE);
+ }
}
}
}
static long encodeconduct(void);
static long encodeachieve(boolean);
static void add_achieveX(char *, const char *, boolean);
-static char *encode_extended_achievements(void);
-static char *encode_extended_conducts(void);
+static char *encode_extended_achievements(char *);
+static char *encode_extended_conducts(char *);
#endif
static void free_ttlist(struct toptenentry *);
static int classmon(char *);
#define Fprintf (void) fprintf
#define XLOG_SEP '\t' /* xlogfile field separator. */
char buf[BUFSZ], tmpbuf[DTHSZ + 1];
+ char achbuf[N_ACH * 40];
Sprintf(buf, "version=%d.%d.%d", tt->ver_major, tt->ver_minor,
tt->patchlevel);
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, "%cachieveX=%s", XLOG_SEP,
+ encode_extended_achievements(achbuf));
+ Fprintf(rfile, "%cconductX=%s", XLOG_SEP,
+ encode_extended_conducts(buf)); /* reuse 'buf[]' */
Fprintf(rfile, "%crealtime=%ld%cstarttime=%ld%cendtime=%ld", XLOG_SEP,
urealtime.realtime, XLOG_SEP,
timet_to_seconds(ubirthday), XLOG_SEP,
/* add the achievement or conduct comma-separated to string */
static void
-add_achieveX(char* buf, const char* achievement, boolean condition)
+add_achieveX(char *buf, const char *achievement, boolean condition)
{
if (condition) {
if (buf[0] != '\0') {
}
static char *
-encode_extended_achievements(void)
+encode_extended_achievements(char *buf)
{
- static char buf[N_ACH * 40];
char rnkbuf[40];
const char *achievement = NULL;
int i, achidx, absidx;
case ACH_BGRM:
achievement = "entered_bigroom";
break;
+ case ACH_TUNE:
+ achievement = "learned_castle_drawbridge_tune";
+ break;
/* rank 0 is the starting condition, not an achievement; 8 is Xp 30 */
case ACH_RNK1: case ACH_RNK2: case ACH_RNK3: case ACH_RNK4:
case ACH_RNK5: case ACH_RNK6: case ACH_RNK7: case ACH_RNK8:
}
static char *
-encode_extended_conducts(void)
+encode_extended_conducts(char *buf)
{
- static char buf[BUFSZ];
-
buf[0] = '\0';
add_achieveX(buf, "foodless", !u.uconduct.food);
add_achieveX(buf, "vegan", !u.uconduct.unvegan);