From: PatR Date: Mon, 15 Jun 2015 01:14:14 +0000 (-0700) Subject: #overview, level difficulty X-Git-Tag: NetHack-3.6.0_RC01~265^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=29f9a8a33d9748d23c027e548f7a99049ff63854;p=nethack #overview, level difficulty 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. --- diff --git a/include/extern.h b/include/extern.h index e4a868c52..0a45129e0 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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 *)); diff --git a/src/do.c b/src/do.c index 21ea4d86b..6f933aeee 100644 --- 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 */ diff --git a/src/dungeon.c b/src/dungeon.c index 2888e6f05..9d6777d0a 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -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); }