wizard mode level teleport (trunk only)
Responding with '?' to the "what level?" prompt when using ^V in
wizard mode brings up a menu of special level destinations that lets you
move across dungeon branches. But getting in and out of Fort Ludios
didn't work, and jumping to the endgame forced you to arrive on the Plane
of Earth. Now Fort Ludios will not be selectable in the menu until after
the portal ordinarily used to reach it has been created (so you'll need a
level between Bigroom and Medusa with a vault on it to be created before
you can bypass the magic portal and jump directly to the Fort), and you
can go directly to any of the elemental planes, including Astral, without
stopping at Earth first (the Wizard will be there to greet you, whichever
level you pick). Also, this limits the menu to endgame entries once you
are in the endgame. (Previously, picking a non-endgame level would yield
"you can't get there from here"; you can still get that, if you really
want to see it for some reason, by giving a destination level number
outside the range of -1 to -5 instead of using the menu.)
I hadn't realized that this feature has been around since 3.4.2 until
I couldn't find any new feature entry for in the current fixes file....
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
# SCCS Id: @(#)knox.des 3.5 1994/08/20
|
# SCCS Id: @(#)knox.des 3.5 2006/03/20
|
||||||
# Copyright (c) 1989 by Jean-Christophe Collet
|
# Copyright (c) 1989 by Jean-Christophe Collet
|
||||||
# Copyright (c) 1992 by Izchak Miller
|
# Copyright (c) 1992 by Izchak Miller
|
||||||
# NetHack may be freely redistributed. See license for details.
|
# NetHack may be freely redistributed. See license for details.
|
||||||
@@ -32,6 +32,9 @@ ENDMAP
|
|||||||
NON_DIGGABLE:(00,00,75,19)
|
NON_DIGGABLE:(00,00,75,19)
|
||||||
# Portal arrival point
|
# Portal arrival point
|
||||||
BRANCH:(08,16,08,16),(0,0,0,0)
|
BRANCH:(08,16,08,16),(0,0,0,0)
|
||||||
|
# accessible via ^V in wizard mode; arrive near the portal
|
||||||
|
TELEPORT_REGION:(06,16,09,17),(0,0,0,0),up
|
||||||
|
TELEPORT_REGION:(06,16,09,17),(0,0,0,0),down
|
||||||
# Throne room, with Croesus on the throne
|
# Throne room, with Croesus on the throne
|
||||||
REGION:(37,08,46,11),lit,"throne"
|
REGION:(37,08,46,11),lit,"throne"
|
||||||
MONSTER:'@',"Croesus",(43,10),hostile
|
MONSTER:'@',"Croesus",(43,10),hostile
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ prevent scroll of charging that has already disappeared from showing in the
|
|||||||
picklist of things to charge
|
picklist of things to charge
|
||||||
doors break instead of absorbing the blast of a broken wand of striking
|
doors break instead of absorbing the blast of a broken wand of striking
|
||||||
avoid "Something's in the way" message with unidentified wand of locking
|
avoid "Something's in the way" message with unidentified wand of locking
|
||||||
|
better handling for Fort Ludios and endgame in wizard mode's `^V ?' menu
|
||||||
|
|
||||||
|
|
||||||
Platform- and/or Interface-Specific Fixes
|
Platform- and/or Interface-Specific Fixes
|
||||||
|
|||||||
10
src/do.c
10
src/do.c
@@ -1,4 +1,4 @@
|
|||||||
/* SCCS Id: @(#)do.c 3.5 2006/02/15 */
|
/* SCCS Id: @(#)do.c 3.5 2006/03/20 */
|
||||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
|
|
||||||
@@ -995,9 +995,11 @@ boolean at_stairs, falling, portal;
|
|||||||
if (dunlev(newlevel) > dunlevs_in_dungeon(newlevel))
|
if (dunlev(newlevel) > dunlevs_in_dungeon(newlevel))
|
||||||
newlevel->dlevel = dunlevs_in_dungeon(newlevel);
|
newlevel->dlevel = dunlevs_in_dungeon(newlevel);
|
||||||
if (newdungeon && In_endgame(newlevel)) { /* 1st Endgame Level !!! */
|
if (newdungeon && In_endgame(newlevel)) { /* 1st Endgame Level !!! */
|
||||||
if (u.uhave.amulet)
|
if (!u.uhave.amulet) return; /* must have the Amulet */
|
||||||
assign_level(newlevel, &earth_level);
|
#ifdef WIZARD
|
||||||
else return;
|
if (!wizard) /* wizard ^V can bypass Earth level */
|
||||||
|
#endif
|
||||||
|
assign_level(newlevel, &earth_level); /* (redundant) */
|
||||||
}
|
}
|
||||||
new_ledger = ledger_no(newlevel);
|
new_ledger = ledger_no(newlevel);
|
||||||
if (new_ledger <= 0)
|
if (new_ledger <= 0)
|
||||||
|
|||||||
156
src/dungeon.c
156
src/dungeon.c
@@ -1,4 +1,4 @@
|
|||||||
/* SCCS Id: @(#)dungeon.c 3.5 2006/02/24 */
|
/* SCCS Id: @(#)dungeon.c 3.5 2006/03/20 */
|
||||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
|
|
||||||
@@ -49,6 +49,10 @@ STATIC_DCL int FDECL(possible_places, (int, boolean *, struct proto_dungeon *));
|
|||||||
STATIC_DCL xchar FDECL(pick_level, (boolean *, int));
|
STATIC_DCL xchar FDECL(pick_level, (boolean *, int));
|
||||||
STATIC_DCL boolean FDECL(place_level, (int, struct proto_dungeon *));
|
STATIC_DCL boolean FDECL(place_level, (int, struct proto_dungeon *));
|
||||||
#ifdef WIZARD
|
#ifdef WIZARD
|
||||||
|
STATIC_DCL boolean FDECL(unplaced_floater, (struct dungeon *));
|
||||||
|
STATIC_DCL boolean FDECL(unreachable_level, (d_level *,BOOLEAN_P));
|
||||||
|
STATIC_DCL void FDECL(tport_menu, (winid,char *,struct lchoice *,
|
||||||
|
d_level *,BOOLEAN_P));
|
||||||
STATIC_DCL const char *FDECL(br_string, (int));
|
STATIC_DCL const char *FDECL(br_string, (int));
|
||||||
STATIC_DCL void FDECL(print_branch, (winid, int, int, int, BOOLEAN_P, struct lchoice *));
|
STATIC_DCL void FDECL(print_branch, (winid, int, int, int, BOOLEAN_P, struct lchoice *));
|
||||||
#endif
|
#endif
|
||||||
@@ -1510,6 +1514,68 @@ const char *nam;
|
|||||||
|
|
||||||
#ifdef WIZARD
|
#ifdef WIZARD
|
||||||
|
|
||||||
|
STATIC_OVL boolean
|
||||||
|
unplaced_floater(dptr)
|
||||||
|
struct dungeon *dptr;
|
||||||
|
{
|
||||||
|
branch *br;
|
||||||
|
int idx = (int)(dptr - dungeons);
|
||||||
|
|
||||||
|
/* if other floating branches are added, this will need to change */
|
||||||
|
if (idx != knox_level.dnum) return FALSE;
|
||||||
|
for (br = branches; br; br = br->next)
|
||||||
|
if (br->end1.dnum == n_dgns && br->end2.dnum == idx) return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC_OVL boolean
|
||||||
|
unreachable_level(lvl_p, unplaced)
|
||||||
|
d_level *lvl_p;
|
||||||
|
boolean unplaced;
|
||||||
|
{
|
||||||
|
s_level *dummy;
|
||||||
|
|
||||||
|
if (unplaced) return TRUE;
|
||||||
|
if (In_endgame(&u.uz) && !In_endgame(lvl_p)) return TRUE;
|
||||||
|
if ((dummy = find_level("dummy")) != 0 && on_level(lvl_p, &dummy->dlevel))
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
tport_menu(win, entry, lchoices, lvl_p, unreachable)
|
||||||
|
winid win;
|
||||||
|
char *entry;
|
||||||
|
struct lchoice *lchoices;
|
||||||
|
d_level *lvl_p;
|
||||||
|
boolean unreachable;
|
||||||
|
{
|
||||||
|
char tmpbuf[BUFSZ];
|
||||||
|
anything any;
|
||||||
|
|
||||||
|
lchoices->lev[lchoices->idx] = lvl_p->dlevel;
|
||||||
|
lchoices->dgn[lchoices->idx] = lvl_p->dnum;
|
||||||
|
lchoices->playerlev[lchoices->idx] = depth(lvl_p);
|
||||||
|
any.a_void = 0;
|
||||||
|
if (unreachable) {
|
||||||
|
/* not selectable, but still consumes next menuletter;
|
||||||
|
prepend padding in place of missing menu selector */
|
||||||
|
Sprintf(tmpbuf, " %s", entry);
|
||||||
|
entry = tmpbuf;
|
||||||
|
} else {
|
||||||
|
any.a_int = lchoices->idx + 1;
|
||||||
|
}
|
||||||
|
add_menu(win, NO_GLYPH, &any, lchoices->menuletter,
|
||||||
|
0, ATR_NONE, entry, MENU_UNSELECTED);
|
||||||
|
/* this assumes there are at most 52 interesting levels */
|
||||||
|
if (lchoices->menuletter == 'z')
|
||||||
|
lchoices->menuletter = 'A';
|
||||||
|
else
|
||||||
|
lchoices->menuletter++;
|
||||||
|
lchoices->idx++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Convert a branch type to a string usable by print_dungeon(). */
|
/* Convert a branch type to a string usable by print_dungeon(). */
|
||||||
STATIC_OVL const char *
|
STATIC_OVL const char *
|
||||||
br_string(type)
|
br_string(type)
|
||||||
@@ -1526,17 +1592,16 @@ br_string(type)
|
|||||||
|
|
||||||
/* Print all child branches between the lower and upper bounds. */
|
/* Print all child branches between the lower and upper bounds. */
|
||||||
STATIC_OVL void
|
STATIC_OVL void
|
||||||
print_branch(win, dnum, lower_bound, upper_bound, bymenu, lchoices)
|
print_branch(win, dnum, lower_bound, upper_bound, bymenu, lchoices_p)
|
||||||
winid win;
|
winid win;
|
||||||
int dnum;
|
int dnum;
|
||||||
int lower_bound;
|
int lower_bound;
|
||||||
int upper_bound;
|
int upper_bound;
|
||||||
boolean bymenu;
|
boolean bymenu;
|
||||||
struct lchoice *lchoices;
|
struct lchoice *lchoices_p;
|
||||||
{
|
{
|
||||||
branch *br;
|
branch *br;
|
||||||
char buf[BUFSZ];
|
char buf[BUFSZ];
|
||||||
anything any;
|
|
||||||
|
|
||||||
/* This assumes that end1 is the "parent". */
|
/* This assumes that end1 is the "parent". */
|
||||||
for (br = branches; br; br = br->next) {
|
for (br = branches; br; br = br->next) {
|
||||||
@@ -1546,18 +1611,10 @@ print_branch(win, dnum, lower_bound, upper_bound, bymenu, lchoices)
|
|||||||
br_string(br->type),
|
br_string(br->type),
|
||||||
dungeons[br->end2.dnum].dname,
|
dungeons[br->end2.dnum].dname,
|
||||||
depth(&br->end1));
|
depth(&br->end1));
|
||||||
if (bymenu) {
|
if (bymenu)
|
||||||
lchoices->lev[lchoices->idx] = br->end1.dlevel;
|
tport_menu(win, buf, lchoices_p, &br->end1,
|
||||||
lchoices->dgn[lchoices->idx] = br->end1.dnum;
|
unreachable_level(&br->end1, FALSE));
|
||||||
lchoices->playerlev[lchoices->idx] = depth(&br->end1);
|
else
|
||||||
any.a_void = 0;
|
|
||||||
any.a_int = lchoices->idx + 1;
|
|
||||||
add_menu(win, NO_GLYPH, &any, lchoices->menuletter,
|
|
||||||
0, ATR_NONE, buf, MENU_UNSELECTED);
|
|
||||||
if (lchoices->menuletter == 'z') lchoices->menuletter = 'A';
|
|
||||||
else lchoices->menuletter++;
|
|
||||||
lchoices->idx++;
|
|
||||||
} else
|
|
||||||
putstr(win, 0, buf);
|
putstr(win, 0, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1572,7 +1629,8 @@ xchar *rdgn;
|
|||||||
{
|
{
|
||||||
int i, last_level, nlev;
|
int i, last_level, nlev;
|
||||||
char buf[BUFSZ];
|
char buf[BUFSZ];
|
||||||
boolean first;
|
const char *descr;
|
||||||
|
boolean first, unplaced;
|
||||||
s_level *slev;
|
s_level *slev;
|
||||||
dungeon *dptr;
|
dungeon *dptr;
|
||||||
branch *br;
|
branch *br;
|
||||||
@@ -1587,12 +1645,16 @@ xchar *rdgn;
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0, dptr = dungeons; i < n_dgns; i++, dptr++) {
|
for (i = 0, dptr = dungeons; i < n_dgns; i++, dptr++) {
|
||||||
|
if (bymenu && In_endgame(&u.uz) && i != astral_level.dnum) continue;
|
||||||
|
unplaced = unplaced_floater(dptr);
|
||||||
|
descr = unplaced ? "depth" : "level";
|
||||||
nlev = dptr->num_dunlevs;
|
nlev = dptr->num_dunlevs;
|
||||||
if (nlev > 1)
|
if (nlev > 1)
|
||||||
Sprintf(buf, "%s: levels %d to %d", dptr->dname, dptr->depth_start,
|
Sprintf(buf, "%s: %s %d to %d", dptr->dname, makeplural(descr),
|
||||||
dptr->depth_start + nlev - 1);
|
dptr->depth_start, dptr->depth_start + nlev - 1);
|
||||||
else
|
else
|
||||||
Sprintf(buf, "%s: level %d", dptr->dname, dptr->depth_start);
|
Sprintf(buf, "%s: %s %d", dptr->dname, descr,
|
||||||
|
dptr->depth_start);
|
||||||
|
|
||||||
/* Most entrances are uninteresting. */
|
/* Most entrances are uninteresting. */
|
||||||
if (dptr->entry_lev != 1) {
|
if (dptr->entry_lev != 1) {
|
||||||
@@ -1621,24 +1683,10 @@ xchar *rdgn;
|
|||||||
Sprintf(buf, " %s: %d", slev->proto, depth(&slev->dlevel));
|
Sprintf(buf, " %s: %d", slev->proto, depth(&slev->dlevel));
|
||||||
if (Is_stronghold(&slev->dlevel))
|
if (Is_stronghold(&slev->dlevel))
|
||||||
Sprintf(eos(buf), " (tune %s)", tune);
|
Sprintf(eos(buf), " (tune %s)", tune);
|
||||||
if (bymenu) {
|
if (bymenu)
|
||||||
/* If other floating branches are added, this will need to change */
|
tport_menu(win, buf, &lchoices, &slev->dlevel,
|
||||||
if (i != knox_level.dnum) {
|
unreachable_level(&slev->dlevel, unplaced));
|
||||||
lchoices.lev[lchoices.idx] = slev->dlevel.dlevel;
|
else
|
||||||
lchoices.dgn[lchoices.idx] = i;
|
|
||||||
} else {
|
|
||||||
lchoices.lev[lchoices.idx] = depth(&slev->dlevel);
|
|
||||||
lchoices.dgn[lchoices.idx] = 0;
|
|
||||||
}
|
|
||||||
lchoices.playerlev[lchoices.idx] = depth(&slev->dlevel);
|
|
||||||
any.a_void = 0;
|
|
||||||
any.a_int = lchoices.idx + 1;
|
|
||||||
add_menu(win, NO_GLYPH, &any, lchoices.menuletter,
|
|
||||||
0, ATR_NONE, buf, MENU_UNSELECTED);
|
|
||||||
if (lchoices.menuletter == 'z') lchoices.menuletter = 'A';
|
|
||||||
else lchoices.menuletter++;
|
|
||||||
lchoices.idx++;
|
|
||||||
} else
|
|
||||||
putstr(win, 0, buf);
|
putstr(win, 0, buf);
|
||||||
|
|
||||||
last_level = slev->dlevel.dlevel;
|
last_level = slev->dlevel.dlevel;
|
||||||
@@ -1647,24 +1695,8 @@ xchar *rdgn;
|
|||||||
print_branch(win, i, last_level, MAXLEVEL, bymenu, &lchoices);
|
print_branch(win, i, last_level, MAXLEVEL, bymenu, &lchoices);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print out floating branches (if any). */
|
|
||||||
for (first = TRUE, br = branches; br; br = br->next) {
|
|
||||||
if (br->end1.dnum == n_dgns) {
|
|
||||||
if (first) {
|
|
||||||
if (!bymenu) {
|
|
||||||
putstr(win, 0, "");
|
|
||||||
putstr(win, 0, "Floating branches");
|
|
||||||
}
|
|
||||||
first = FALSE;
|
|
||||||
}
|
|
||||||
Sprintf(buf, " %s to %s",
|
|
||||||
br_string(br->type), dungeons[br->end2.dnum].dname);
|
|
||||||
if (!bymenu)
|
|
||||||
putstr(win, 0, buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (bymenu) {
|
if (bymenu) {
|
||||||
int n;
|
int n;
|
||||||
menu_item *selected;
|
menu_item *selected;
|
||||||
int idx;
|
int idx;
|
||||||
|
|
||||||
@@ -1683,6 +1715,20 @@ xchar *rdgn;
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Print out floating branches (if any). */
|
||||||
|
for (first = TRUE, br = branches; br; br = br->next) {
|
||||||
|
if (br->end1.dnum == n_dgns) {
|
||||||
|
if (first) {
|
||||||
|
putstr(win, 0, "");
|
||||||
|
putstr(win, 0, "Floating branches");
|
||||||
|
first = FALSE;
|
||||||
|
}
|
||||||
|
Sprintf(buf, " %s to %s",
|
||||||
|
br_string(br->type), dungeons[br->end2.dnum].dname);
|
||||||
|
putstr(win, 0, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* I hate searching for the invocation pos while debugging. -dean */
|
/* I hate searching for the invocation pos while debugging. -dean */
|
||||||
if (Invocation_lev(&u.uz)) {
|
if (Invocation_lev(&u.uz)) {
|
||||||
putstr(win, 0, "");
|
putstr(win, 0, "");
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* SCCS Id: @(#)teleport.c 3.5 2003/12/12 */
|
/* SCCS Id: @(#)teleport.c 3.5 2006/03/18 */
|
||||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
|
|
||||||
@@ -621,17 +621,16 @@ level_tele()
|
|||||||
newlevel.dnum = destdnum;
|
newlevel.dnum = destdnum;
|
||||||
newlevel.dlevel = destlev;
|
newlevel.dlevel = destlev;
|
||||||
if (In_endgame(&newlevel) && !In_endgame(&u.uz)) {
|
if (In_endgame(&newlevel) && !In_endgame(&u.uz)) {
|
||||||
Sprintf(buf, "Destination is earth level");
|
struct obj *amu;
|
||||||
if (!u.uhave.amulet) {
|
|
||||||
struct obj *obj = mksobj(AMULET_OF_YENDOR,
|
if (!u.uhave.amulet &&
|
||||||
TRUE, FALSE);
|
(amu = mksobj(AMULET_OF_YENDOR, TRUE, FALSE)) != 0) {
|
||||||
if (obj) {
|
/* ordinarily we'd use hold_another_object()
|
||||||
obj = addinv(obj);
|
for something like this, but we don't want
|
||||||
Strcat(buf, " with the amulet");
|
fumbling or already full pack to interfere */
|
||||||
}
|
amu = addinv(amu);
|
||||||
|
prinv("Endgame prerequisite:", amu, 0L);
|
||||||
}
|
}
|
||||||
assign_level(&newlevel, &earth_level);
|
|
||||||
pline("%s.", buf);
|
|
||||||
}
|
}
|
||||||
force_dest = TRUE;
|
force_dest = TRUE;
|
||||||
} else
|
} else
|
||||||
@@ -664,7 +663,7 @@ level_tele()
|
|||||||
/* if in Knox and the requested level > 0, stay put.
|
/* if in Knox and the requested level > 0, stay put.
|
||||||
* we let negative values requests fall into the "heaven" loop.
|
* we let negative values requests fall into the "heaven" loop.
|
||||||
*/
|
*/
|
||||||
if (Is_knox(&u.uz) && newlev > 0) {
|
if (Is_knox(&u.uz) && newlev > 0 && !force_dest) {
|
||||||
You(shudder_for_moment);
|
You(shudder_for_moment);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -690,7 +689,7 @@ level_tele()
|
|||||||
if (u.utrap && u.utraptype == TT_BURIEDBALL)
|
if (u.utrap && u.utraptype == TT_BURIEDBALL)
|
||||||
buried_ball_to_punishment();
|
buried_ball_to_punishment();
|
||||||
|
|
||||||
if (!next_to_u()) {
|
if (!next_to_u() && !force_dest) {
|
||||||
You(shudder_for_moment);
|
You(shudder_for_moment);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user