]> granicus.if.org Git - nethack/commitdiff
new achievement: drawbridge tune
authorPatR <rankin@nethack.org>
Sun, 27 Feb 2022 09:55:25 +0000 (01:55 -0800)
committerPatR <rankin@nethack.org>
Sun, 27 Feb 2022 09:55:25 +0000 (01:55 -0800)
Use up the last available bit for achievements:
"You learned the tune to open and close the castle's drawbridge."
(More can still be added but xlogfile will need another field to
track a second set of 31 in order to keep its achievement bitmask(s)
within portable size.)

As achievements go, it's not very exciting, but players who normally
destroy the drawbridge have to choose whether to earn an achievement
first since once it's gone, there's no way to find out the tune
(either via prayer reward or successful Mastermind).  I'm guessing
that most will probably decide to ignore this achievement since it
has no effect on the outcome of the game.  However, that might not
be true for future tournament play.

There's no need to bump EDITLEVEL for this; room for recording one
additional achievement is already allocated.

include/you.h
src/insight.c
src/music.c
src/pray.c
src/topten.c

index a563a4063740134cc87f6ae1274b6c4242dbccca..b088fedb358ebe81d14213ec31b940d74232fc5e 100644 (file)
@@ -98,7 +98,7 @@ enum achivements {
        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 */
 };
     /*
@@ -117,7 +117,6 @@ enum achivements {
      *  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?],
index 10bd74dd2b84b5b0e9973be5a5b213a8cfddb05a..9624fb83448997d3d86b7b0b1a4a80f5842faa04 100644 (file)
@@ -2183,6 +2183,10 @@ show_achievements(
         case ACH_MEDU:
             you_have_X("defeated Medusa");
             break;
+        case ACH_TUNE:
+            you_have_X(
+                "learned the tune to open and close the Castle's drawbridge");
+            break;
         case ACH_BELL:
             /* alternate phrasing for present vs past and also for
                possessing the item vs once held it */
index f471210c8711e90609caa2743660193414c76660..9cd41d1248337e01d37a1b476737d8d0c2c5f43d 100644 (file)
@@ -744,17 +744,20 @@ do_play_instrument(struct obj* instr)
             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;
@@ -804,8 +807,10 @@ do_play_instrument(struct obj* instr)
                         /* 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);
+                        }
                     }
                 }
             }
index d12b848cb437ca2e4cd95ff481f00361fe76210e..44f0c6e501898da4b7c721d085741a76e0477ba5 100644 (file)
@@ -1068,7 +1068,7 @@ pleased(aligntyp g_align)
             if (!u.uevent.uopened_dbridge && !u.uevent.gehennom_entered) {
                 if (u.uevent.uheard_tune < 1) {
                     godvoice(g_align, (char *) 0);
-                    verbalize("Hark, %s!", g.youmonst.data->mlet == S_HUMAN
+                    verbalize("Hark, %s!", (g.youmonst.data->mlet == S_HUMAN)
                                                ? "mortal"
                                                : "creature");
                     verbalize(
@@ -1079,6 +1079,7 @@ pleased(aligntyp g_align)
                     You_hear("a divine music...");
                     pline("It sounds like:  \"%s\".", g.tune);
                     u.uevent.uheard_tune++;
+                    record_achievement(ACH_TUNE);
                     break;
                 }
             }
index 62ae49a4e82fa369f65abb0b1be04e90d5f902c6..f15aeb34989b78c56a9c62e9d760ae29eebe8874 100644 (file)
@@ -72,8 +72,8 @@ static long encodexlogflags(void);
 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 *);
@@ -339,6 +339,7 @@ writexlentry(FILE* rfile, struct toptenentry* tt, int how)
 #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);
@@ -364,8 +365,10 @@ writexlentry(FILE* rfile, struct toptenentry* tt, 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, "%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,
@@ -466,7 +469,7 @@ encodeachieve(
 
 /* 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') {
@@ -477,9 +480,8 @@ add_achieveX(char* buf, const char* achievement, boolean condition)
 }
 
 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;
@@ -549,6 +551,9 @@ encode_extended_achievements(void)
         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:
@@ -568,10 +573,8 @@ encode_extended_achievements(void)
 }
 
 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);