]> granicus.if.org Git - nethack/commitdiff
#overview, level difficulty
authorPatR <rankin@nethack.org>
Mon, 15 Jun 2015 01:14:14 +0000 (18:14 -0700)
committerPatR <rankin@nethack.org>
Mon, 15 Jun 2015 01:14:14 +0000 (18:14 -0700)
Three fixes, the first leading to the need to fix the second, and that
fix making dealing with the third be straightforward.

First, make the furthest level reached in any given branch be considered
interesting by #overview, even if no interesting features have been
encountered.  This will result in listing Gnomish Mines and their first
level when someone goes down the stairs and immediately back up.  It will
also produce a reminder of how far you've been--in each branch--after
retreating for any reason, without the need to manually add an annotation.

Second, #overview was suppressing the range of level numbers for Sokoban
because the author realized that the values were wrong.  The record of
the furthest level reached was incorrect for builds-up branches, always
sticking with the deepest level even though it was the entrance.  The
overview patch neglected to do the same suppression for Vlad's Tower and
the level range ("36 to 38" or similar) there was wrong.  This fixes the
furthest level reached problem and also fixes #overview's level range
handling for builds-up branches.

Third and last, a long-standing issue which I don't think has ever been
formally reported:  the level difficulty calculation used for monster
creation treated the upper (harder to get to) levels of builds-up branches
as if they were easier since they're closer to the surface as the gopher
burrows.  So sokoban generated easier monsters on its final level than on
the ones leading up to that.  Make depth for difficulty purposes account
for descent to the entrance and then ascent to the level of interest.

There was a distressing amount of trial and error involved.  The dungeon
layout structures are not exactly easy to work with, and I never managed
to get builds_up() based on branch data to work correctly.  Basing it on
dungeon data works as intended provided the branch has more than one
level, but it will yield incorrect result if we ever add a single-level
branch reached via stairs up rather than stairs down.

include/extern.h
src/do.c
src/dungeon.c

index e4a868c52307f9421b54b732f91a99ba62e7e51f..0a45129e098ae2ec640bbe72507fcfb5481d6ac5 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 extern.h        $NHDT-Date: 1433207912 2015/06/02 01:18:32 $  $NHDT-Branch: master $:$NHDT-Revision: 1.500 $ */
+/* NetHack 3.6 extern.h        $NHDT-Date: 1434330826 2015/06/15 01:13:46 $  $NHDT-Branch: master $:$NHDT-Revision: 1.503 $ */
 /* Copyright (c) Steve Creps, 1988.                              */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -537,6 +537,7 @@ E void NDECL(init_dungeons);
 E s_level *FDECL(find_level, (const char *));
 E s_level *FDECL(Is_special, (d_level *));
 E branch *FDECL(Is_branchlev, (d_level *));
+E boolean FDECL(builds_up, (d_level *));
 E xchar FDECL(ledger_no, (d_level *));
 E xchar NDECL(maxledgerno);
 E schar FDECL(depth, (d_level *));
index 21ea4d86b254e4797fcc0ef50597ded8768c2c6f..6f933aeee9e93662e7d99dcf91704c3975d44000 100644 (file)
--- a/src/do.c
+++ b/src/do.c
@@ -1,4 +1,4 @@
-/* NetHack 3.6 do.c    $NHDT-Date: 1432512769 2015/05/25 00:12:49 $  $NHDT-Branch: master $:$NHDT-Revision: 1.142 $ */
+/* NetHack 3.6 do.c    $NHDT-Date: 1434330833 2015/06/15 01:13:53 $  $NHDT-Branch: master $:$NHDT-Revision: 1.144 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1224,8 +1224,14 @@ boolean at_stairs, falling, portal;
     assign_level(&u.uz, newlevel);
     assign_level(&u.utolev, newlevel);
     u.utotype = 0;
-    if (dunlev_reached(&u.uz) < dunlev(&u.uz))
-        dunlev_reached(&u.uz) = dunlev(&u.uz);
+    if (!builds_up(&u.uz)) { /* usual case */
+        if (dunlev(&u.uz) > dunlev_reached(&u.uz))
+            dunlev_reached(&u.uz) = dunlev(&u.uz);
+    } else {
+        if (dunlev_reached(&u.uz) == 0
+            || dunlev(&u.uz) < dunlev_reached(&u.uz))
+            dunlev_reached(&u.uz) = dunlev(&u.uz);
+    }
     reset_rndmonst(NON_PM); /* u.uz change affects monster generation */
 
     /* set default level change destination areas */
index 2888e6f05d7fd7e9b250f6e3c1dd5998fc0221fd..9d6777d0a2b2c94615e14d7408ddc84598e66fad 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 dungeon.c       $NHDT-Date: 1432512766 2015/05/25 00:12:46 $  $NHDT-Branch: master $:$NHDT-Revision: 1.58 $ */
+/* NetHack 3.6 dungeon.c       $NHDT-Date: 1434330836 2015/06/15 01:13:56 $  $NHDT-Branch: master $:$NHDT-Revision: 1.59 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1067,8 +1067,7 @@ xchar
 ledger_to_dlev(ledgerno)
 xchar ledgerno;
 {
-    return (
-        (xchar)(ledgerno - dungeons[ledger_to_dnum(ledgerno)].ledger_start));
+    return (xchar)(ledgerno - dungeons[ledger_to_dnum(ledgerno)].ledger_start);
 }
 
 /* returns the depth of a level, in floors below the surface   */
@@ -1077,14 +1076,16 @@ schar
 depth(lev)
 d_level *lev;
 {
-    return ((schar)(dungeons[lev->dnum].depth_start + lev->dlevel - 1));
+    return (schar) (dungeons[lev->dnum].depth_start + lev->dlevel - 1);
 }
 
-boolean on_level(lev1, lev2) /* are "lev1" and "lev2" actually the same? */
+/* are "lev1" and "lev2" actually the same? */
+boolean
+on_level(lev1, lev2)
 d_level *lev1, *lev2;
 {
-    return ((boolean)((lev1->dnum == lev2->dnum)
-                      && (lev1->dlevel == lev2->dlevel)));
+    return (boolean) ((lev1->dnum == lev2->dnum)
+                      && (lev1->dlevel == lev2->dlevel));
 }
 
 /* is this level referenced in the special level chain? */
@@ -1098,7 +1099,7 @@ d_level *lev;
         if (on_level(lev, &levtmp->dlevel))
             return (levtmp);
 
-    return ((s_level *) 0);
+    return (s_level *) 0;
 }
 
 /*
@@ -1118,6 +1119,20 @@ d_level *lev;
     return (branch *) 0;
 }
 
+/* returns True iff the branch 'lev' is in a branch which builds up */
+boolean
+builds_up(lev)
+d_level *lev;
+{
+    dungeon *dptr = &dungeons[lev->dnum];
+    /*
+     * FIXME:  this misclassifies a single level branch reached via stairs
+     * from below.  Saving grace is that no such branches currently exist.
+     */
+    return (boolean) (dptr->num_dunlevs > 1
+                      && dptr->entry_lev == dptr->num_dunlevs);
+}
+
 /* goto the next level (or appropriate dungeon) */
 void
 next_level(at_stairs)
@@ -1523,12 +1538,39 @@ d_level *lev;
 xchar
 level_difficulty()
 {
-    if (In_endgame(&u.uz))
-        return ((xchar)(depth(&sanctum_level) + u.ulevel / 2));
-    else if (u.uhave.amulet)
-        return (deepest_lev_reached(FALSE));
-    else
-        return ((xchar) depth(&u.uz));
+    int res;
+
+    if (In_endgame(&u.uz)) {
+        res = depth(&sanctum_level) + u.ulevel / 2;
+    } else if (u.uhave.amulet) {
+        res = deepest_lev_reached(FALSE);
+    } else {
+        res = depth(&u.uz);
+        /* depth() is the number of elevation units (levels) below
+           the theorhetical surface; in a builds-up branch, that value
+           ends up making the harder to reach levels be treated as if
+           they were easier; adjust for the extra effort involved in
+           going down to the entrance and then up to the location */
+        if (builds_up(&u.uz))
+            res += 2 * (dungeons[u.uz.dnum].entry_lev - u.uz.dlevel + 1);
+            /*
+             * 'Proof' by example:  suppose the entrance to sokoban is
+             * on dungeon level 9, leading up to bottom sokoban level
+             * of 8 [entry_lev].  When the hero is on sokoban level 8
+             * [uz.dlevel], depth() yields eight but he has ventured
+             * one level beyond 9, so difficulty depth should be 10:
+             *   8 + 2 * (8 - 8 + 1) => 10.
+             * Going up to 7, depth is 7 but hero will be two beyond 9:
+             *   7 + 2 * (8 - 7 + 1) => 11.
+             * When he goes up to level 6, three levels beyond 9:
+             *   6 + 2 * (8 - 6 + 1) => 12.
+             * And the top level of sokoban at 5, four levels beyond 9:
+             *   5 + 2 * (8 - 5 + 1) => 13.
+             * The same applies to Vlad's Tower, although the increment
+             * there is inconsequential compared to overall depth.
+             */
+    }
+    return (xchar) res;
 }
 
 /* Take one word and try to match it to a level.
@@ -2143,10 +2185,12 @@ mapseen *mptr;
     if (In_endgame(&u.uz))
         return In_endgame(&mptr->lev);
     /* level is of interest if it has non-zero feature count or known bones
-       or user annotation or known connection to another dungeon brancth */
+       or user annotation or known connection to another dungeon branch
+       or is the furthest level reached in its branch */
     return (INTEREST(mptr->feat) || (mptr->final_resting_place
                                      && (mptr->flags.knownbones || wizard))
-            || mptr->custom || mptr->br);
+            || mptr->custom || mptr->br
+            || mptr->lev.dlevel == dungeons[mptr->lev.dnum].dunlev_ureached);
 }
 
 /* recalculate mapseen for the current level */
@@ -2634,30 +2678,33 @@ int how;   /* cause of death; only used if final==2 and mptr->lev==u.uz */
 boolean printdun;
 {
     char buf[BUFSZ], tmpbuf[BUFSZ];
-    int i, depthstart;
+    int i, depthstart, dnum;
     boolean died_here = (final == 2 && on_level(&u.uz, &mptr->lev));
 
     /* Damnable special cases */
     /* The quest and knox should appear to be level 1 to match
      * other text.
      */
-    if (mptr->lev.dnum == quest_dnum || mptr->lev.dnum == knox_level.dnum)
+    dnum = mptr->lev.dnum;
+    if (dnum == quest_dnum || dnum == knox_level.dnum)
         depthstart = 1;
     else
-        depthstart = dungeons[mptr->lev.dnum].depth_start;
+        depthstart = dungeons[dnum].depth_start;
 
     if (printdun) {
-        /* Sokoban lies about dunlev_ureached and we should
-         * suppress the negative numbers in the endgame.
-         */
-        if (dungeons[mptr->lev.dnum].dunlev_ureached == 1
-            || mptr->lev.dnum == sokoban_dnum || In_endgame(&mptr->lev))
-            Sprintf(buf, "%s:", dungeons[mptr->lev.dnum].dname);
+        if (dungeons[dnum].dunlev_ureached == dungeons[dnum].entry_lev
+            /* suppress the negative numbers in the endgame */
+            || In_endgame(&mptr->lev))
+            Sprintf(buf, "%s:", dungeons[dnum].dname);
+        else if (builds_up(&mptr->lev))
+            Sprintf(buf, "%s: levels %d up to %d",
+                    dungeons[dnum].dname,
+                    depthstart + dungeons[dnum].entry_lev - 1,
+                    depthstart + dungeons[dnum].dunlev_ureached - 1);
         else
             Sprintf(buf, "%s: levels %d to %d",
-                    dungeons[mptr->lev.dnum].dname, depthstart,
-                    depthstart + dungeons[mptr->lev.dnum].dunlev_ureached
-                        - 1);
+                    dungeons[dnum].dname, depthstart,
+                    depthstart + dungeons[dnum].dunlev_ureached - 1);
         putstr(win, !final ? ATR_INVERSE : 0, buf);
     }