Merge branch 'NetHack-3.6.2'

This commit is contained in:
nhmall
2019-01-04 23:08:49 -05:00
9 changed files with 407 additions and 199 deletions

View File

@@ -1,4 +1,4 @@
$NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.221 $ $NHDT-Date: 1546467443 2019/01/02 22:17:23 $
$NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.223 $ $NHDT-Date: 1546655319 2019/01/05 02:28:39 $
This fixes36.2 file is here to capture information about updates in the 3.6.x
lineage following the release of 3.6.1 in April 2018. Please note, however,
@@ -322,6 +322,11 @@ since knives became stackable in 3.6.0, fake player monsters could be given
using 'O' to attempt to set bouldersym to a monster letter or warning digit
while it still had its default value would override the display value
for it to be <NUL> ('\0') after 'badoption' feedback
when ^T resorted to the teleport-away spell if hero didn't have intrinsic
telepotation, it used different hunger/strength/energy requirements
than casting with 'Z'; ^T also required that the corresponding book
be known even though knowing and casting a spell should be (and is
with 'Z') possible after forgetting the spellbook due to amnesia
Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository
@@ -366,6 +371,8 @@ wizard mode ^G, creating a monster via class name using "lo" through "long wor"
if bouldersym bug (via 'O', above) put a <NUL> ('\0') on the map, examining
that spot matched placeholder monster class #0 and triggered impossible
"Alphabet soup: 'an("")'."
wizard mode m^T, not selecting a teleport choice didn't teardown the menu
properly and could eventually lead to "No window slots!" panic
tty: turn off an optimization that is the suspected cause of Windows reported
partial status lines following level changes
tty: ensure that current status fields are always copied to prior status
@@ -493,6 +500,8 @@ when sortloot is enabled, gems are grouped in subsets (1) unseen gems and
(4) identified glass, (5) unseen stones (includes unseen rocks),
(6) seen but unidentified gray stones, (7) identified gray stones,
and (8) seen rocks (IDed/unIDed not applicable)
in wizard mode, ^T can be preceded by 'm' prefix in order to test teleporting
without having wizard mode override various restrictions
NetHack Community Patches (or Variation) Included

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 extern.h $NHDT-Date: 1545964581 2018/12/28 02:36:21 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.678 $ */
/* NetHack 3.6 extern.h $NHDT-Date: 1546565812 2019/01/04 01:36:52 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.680 $ */
/* Copyright (c) Steve Creps, 1988. */
/* NetHack may be freely redistributed. See license for details. */
@@ -2330,6 +2330,7 @@ E void NDECL(age_spells);
E int NDECL(docast);
E int FDECL(spell_skilltype, (int));
E int FDECL(spelleffects, (int, BOOLEAN_P));
E int FDECL(tport_spell, (int));
E void NDECL(losespells);
E int NDECL(dovspell);
E void FDECL(initialspell, (struct obj *));

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 cmd.c $NHDT-Date: 1546038393 2018/12/28 23:06:33 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.323 $ */
/* NetHack 3.6 cmd.c $NHDT-Date: 1546565813 2019/01/04 01:36:53 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.324 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2013. */
/* NetHack may be freely redistributed. See license for details. */
@@ -4393,8 +4393,8 @@ int NDECL((*cmd_func));
|| cmd_func == doloot
/* travel: pop up a menu of interesting targets in view */
|| cmd_func == dotravel
/* wizard mode ^V */
|| cmd_func == wiz_level_tele
/* wizard mode ^V and ^T */
|| cmd_func == wiz_level_tele || cmd_func == dotelecmd
/* 'm' prefix allowed for some extended commands */
|| cmd_func == doextcmd || cmd_func == doextlist)
return TRUE;

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 drawing.c $NHDT-Date: 1546212616 2018/12/30 23:30:16 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.58 $ */
/* NetHack 3.6 drawing.c $NHDT-Date: 1546656404 2019/01/05 02:46:44 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.59 $ */
/* Copyright (c) NetHack Development Team 1992. */
/* NetHack may be freely redistributed. See license for details. */
@@ -496,7 +496,7 @@ int nondefault;
#endif
# ifdef CURSES_GRAPHICS
if (SYMHANDLING(H_CURS) && cursesgraphics_mode_callback)
(*cursesgraphics_mode_callback)();
(*cursesgraphics_mode_callback)();
# endif
} else {
init_l_symbols();

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 hack.c $NHDT-Date: 1545530973 2018/12/23 02:09:33 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.202 $ */
/* NetHack 3.6 hack.c $NHDT-Date: 1546656413 2019/01/05 02:46:53 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.203 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */
@@ -277,7 +277,7 @@ moverock()
/* note: reset to zero after save/restore cycle */
static NEARDATA long lastmovetime;
#endif
dopush:
dopush:
if (!u.usteed) {
if (g.moves > lastmovetime + 2 || g.moves < lastmovetime)
pline("With %s effort you move %s.",
@@ -302,7 +302,7 @@ moverock()
newsym(sx, sy);
}
} else {
nopushmsg:
nopushmsg:
if (u.usteed)
pline("%s tries to move %s, but cannot.",
upstart(y_monnam(u.usteed)), the(xname(otmp)));
@@ -310,7 +310,7 @@ moverock()
You("try to move %s, but in vain.", the(xname(otmp)));
if (Blind)
feel_location(sx, sy);
cannot_push:
cannot_push:
if (throws_rocks(g.youmonst.data)) {
boolean
canpickup = (!Sokoban
@@ -795,7 +795,7 @@ int mode;
return FALSE;
}
} else {
testdiag:
testdiag:
if (dx && dy && !Passes_walls
&& (!doorless_door(x, y) || block_door(x, y))) {
/* Diagonal moves into a door are not allowed. */
@@ -953,8 +953,8 @@ int mode;
uy = u.uy;
}
noguess:
(void) memset((genericptr_t) travel, 0, sizeof(travel));
noguess:
(void) memset((genericptr_t) travel, 0, sizeof travel);
travelstepx[0][0] = tx;
travelstepy[0][0] = ty;
@@ -1139,7 +1139,7 @@ int mode;
return FALSE;
}
found:
found:
u.dx = 0;
u.dy = 0;
nomul(0);
@@ -1292,7 +1292,7 @@ struct trap *desttrap; /* nonnull if another trap at <x,y> */
Norep("You are %s %s.", predicament, culprit);
}
} else {
wriggle_free:
wriggle_free:
if (u.usteed)
pline("%s finally %s free.", upstart(steedname),
!anchored ? "lurches" : "wrenches the ball");
@@ -1491,7 +1491,7 @@ domove()
case 0:
case 1:
case 2:
pull_free:
pull_free:
You("pull free from %s.", mon_nam(u.ustuck));
u.ustuck = 0;
break;
@@ -2201,7 +2201,7 @@ boolean pick;
}
mnexto(mtmp); /* have to move the monster */
}
spotdone:
spotdone:
if (!--inspoteffects) {
spotterrain = STONE; /* 0 */
spotloc.x = spotloc.y = 0;
@@ -2579,7 +2579,8 @@ dopickup(VOID_ARGS)
int count, tmpcount, ret;
/* awful kludge to work around parse()'s pre-decrement */
count = (g.multi || (g.save_cm && *g.save_cm == cmd_from_func(dopickup))) ? g.multi + 1 : 0;
count = (g.multi || (g.save_cm && *g.save_cm == cmd_from_func(dopickup)))
? g.multi + 1 : 0;
g.multi = 0; /* always reset */
if ((ret = pickup_checks() >= 0))
@@ -2652,7 +2653,7 @@ lookaround()
}
goto bcorr;
} else if (levl[x][y].typ == CORR) {
bcorr:
bcorr:
if (levl[u.ux][u.uy].typ != ROOM) {
if (g.context.run == 1 || g.context.run == 3
|| g.context.run == 8) {
@@ -2710,7 +2711,7 @@ lookaround()
|| ((y == u.uy - u.dy) && (x != u.ux + u.dx)))
continue;
}
stop:
stop:
nomul(0);
return;
} /* end for loops */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 options.c $NHDT-Date: 1546212618 2018/12/30 23:30:18 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.350 $ */
/* NetHack 3.6 options.c $NHDT-Date: 1546657409 2019/01/05 03:03:29 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.351 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2008. */
/* NetHack may be freely redistributed. See license for details. */
@@ -279,7 +279,7 @@ static struct Comp_Opt {
{ "catname", "the name of your (first) cat (e.g., catname:Tabby)",
PL_PSIZ, DISP_IN_GAME },
{ "disclose", "the kinds of information to disclose at end of game",
sizeof(flags.end_disclose) * 2, SET_IN_GAME },
sizeof flags.end_disclose * 2, SET_IN_GAME },
{ "dogname", "the name of your (first) dog (e.g., dogname:Fang)", PL_PSIZ,
DISP_IN_GAME },
{ "dungeon", "the symbols to use in drawing the dungeon map",
@@ -712,7 +712,7 @@ initoptions_init()
#endif
#ifdef SYSFLAGS
Strcpy(sysflags.sysflagsid, "sysflags");
sysflags.sysflagsid[9] = (char) sizeof(struct sysflag);
sysflags.sysflagsid[9] = (char) sizeof (struct sysflag);
#endif
flags.end_own = FALSE;
flags.end_top = 3;
@@ -900,6 +900,8 @@ int maxlen;
/*
* escapes(): escape expansion for showsyms. C-style escapes understood
* include \n, \b, \t, \r, \xnnn (hex), \onnn (octal), \nnn (decimal).
* (Note: unlike in C, leading digit 0 is not used to indicate octal;
* the letter o (either upper or lower case) is used for that.
* The ^-prefix for control characters is also understood, and \[mM]
* has the effect of 'meta'-ing the value which follows (so that the
* alternate character set will be enabled).
@@ -1005,7 +1007,7 @@ const char *optname;
/*
# errors:
OPTIONS=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
OPTIONS=aaaaaaaaaa[ more than 247 (255 - 8 for 'OPTIONS=') total ]aaaaaaaaaa
OPTIONS
OPTIONS=
MSGTYPE=stop"You swap places with "
@@ -1376,7 +1378,7 @@ char *str;
/* allow "lightblue", "light blue", and "light-blue" to match "light blue"
(also junk like "_l i-gh_t---b l u e" but we won't worry about that);
also copes with trailing space; mungspaces removed any leading space */
also copes with trailing space; caller has removed any leading space */
for (i = 0; i < SIZE(colornames); i++)
if (colornames[i].name
&& fuzzymatch(str, colornames[i].name, " -_", TRUE)) {
@@ -1603,8 +1605,7 @@ msgtype_add(typ, pattern)
int typ;
char *pattern;
{
struct plinemsg_type
*tmp = (struct plinemsg_type *) alloc(sizeof (struct plinemsg_type));
struct plinemsg_type *tmp = (struct plinemsg_type *) alloc(sizeof *tmp);
tmp->msgtype = typ;
tmp->regex = regex_init();
@@ -1775,7 +1776,7 @@ int c, a;
if (!str)
return FALSE;
tmp = (struct menucoloring *) alloc(sizeof (struct menucoloring));
tmp = (struct menucoloring *) alloc(sizeof *tmp);
tmp->match = regex_init();
if (!regex_compile(str, tmp->match)) {
config_error_add("%s: %s", re_error, regex_error_desc(tmp->match));
@@ -1836,7 +1837,6 @@ char *tmpstr;
tmps++;
}
}
return add_menu_coloring_parsed(tmps, c, a);
}
@@ -1860,15 +1860,13 @@ int *color, *attr;
void
free_menu_coloring()
{
struct menucoloring *tmp = g.menu_colorings;
while (tmp) {
struct menucoloring *tmp2 = tmp->next;
struct menucoloring *tmp, *tmp2;
for (tmp = menu_colorings; tmp; tmp = tmp2) {
tmp2 = tmp->next;
regex_free(tmp->match);
free((genericptr_t) tmp->origstr);
free((genericptr_t) tmp);
tmp = tmp2;
}
}
@@ -1901,13 +1899,11 @@ int idx; /* 0 .. */
STATIC_OVL int
count_menucolors(VOID_ARGS)
{
struct menucoloring *tmp;
int count = 0;
struct menucoloring *tmp = g.menu_colorings;
while (tmp) {
for (tmp = g.menu_colorings; tmp; tmp = tmp->next)
count++;
tmp = tmp->next;
}
return count;
}
@@ -2056,7 +2052,7 @@ boolean tinitial, tfrom_file;
/* align:string */
fullname = "align";
if (match_optname(opts, fullname, sizeof("align") - 1, TRUE)) {
if (match_optname(opts, fullname, sizeof "align" - 1, TRUE)) {
if (parse_role_opts(negated, fullname, opts, &op)) {
if ((flags.initalign = str2align(op)) == ROLE_NONE) {
config_error_add("Unknown %s '%s'", fullname, op);
@@ -2610,7 +2606,7 @@ boolean tinitial, tfrom_file;
}
}
}
goodfruit:
goodfruit:
nmcpy(g.pl_fruit, op, PL_FSIZ);
sanitize_name(g.pl_fruit);
/* OBJ_NAME(objects[SLIME_MOLD]) won't work for this after
@@ -2783,16 +2779,16 @@ boolean tinitial, tfrom_file;
/* WINCAP
* align_status:[left|top|right|bottom] */
fullname = "align_status";
if (match_optname(opts, fullname, sizeof("align_status") - 1, TRUE)) {
if (match_optname(opts, fullname, sizeof "align_status" - 1, TRUE)) {
op = string_for_opt(opts, negated);
if (op && !negated) {
if (!strncmpi(op, "left", sizeof("left") - 1))
if (!strncmpi(op, "left", sizeof "left" - 1))
iflags.wc_align_status = ALIGN_LEFT;
else if (!strncmpi(op, "top", sizeof("top") - 1))
else if (!strncmpi(op, "top", sizeof "top" - 1))
iflags.wc_align_status = ALIGN_TOP;
else if (!strncmpi(op, "right", sizeof("right") - 1))
else if (!strncmpi(op, "right", sizeof "right" - 1))
iflags.wc_align_status = ALIGN_RIGHT;
else if (!strncmpi(op, "bottom", sizeof("bottom") - 1))
else if (!strncmpi(op, "bottom", sizeof "bottom" - 1))
iflags.wc_align_status = ALIGN_BOTTOM;
else {
config_error_add("Unknown %s parameter '%s'", fullname, op);
@@ -2808,18 +2804,18 @@ boolean tinitial, tfrom_file;
/* WINCAP
* align_message:[left|top|right|bottom] */
fullname = "align_message";
if (match_optname(opts, fullname, sizeof("align_message") - 1, TRUE)) {
if (match_optname(opts, fullname, sizeof "align_message" - 1, TRUE)) {
if (duplicate)
complain_about_duplicate(opts, 1);
op = string_for_opt(opts, negated);
if (op && !negated) {
if (!strncmpi(op, "left", sizeof("left") - 1))
if (!strncmpi(op, "left", sizeof "left" - 1))
iflags.wc_align_message = ALIGN_LEFT;
else if (!strncmpi(op, "top", sizeof("top") - 1))
else if (!strncmpi(op, "top", sizeof "top" - 1))
iflags.wc_align_message = ALIGN_TOP;
else if (!strncmpi(op, "right", sizeof("right") - 1))
else if (!strncmpi(op, "right", sizeof "right" - 1))
iflags.wc_align_message = ALIGN_RIGHT;
else if (!strncmpi(op, "bottom", sizeof("bottom") - 1))
else if (!strncmpi(op, "bottom", sizeof "bottom" - 1))
iflags.wc_align_message = ALIGN_BOTTOM;
else {
config_error_add("Unknown %s parameter '%s'", fullname, op);
@@ -2873,7 +2869,7 @@ boolean tinitial, tfrom_file;
pp = index(op, ' ');
if (pp)
*pp = '\0';
/* we aren't matching option names but match_optname
/* we aren't matching option names but match_optname()
does what we want once we've broken the space
delimited aggregate into separate tokens */
for (i = 0; i < SIZE(paranoia); ++i) {
@@ -2958,8 +2954,8 @@ boolean tinitial, tfrom_file;
/* types of objects to pick up automatically */
fullname = "pickup_types";
if (match_optname(opts, fullname, 8, TRUE)) {
char ocl[MAXOCLASSES + 1], tbuf[MAXOCLASSES + 1], qbuf[QBUFSZ],
abuf[BUFSZ] = DUMMY;
char ocl[MAXOCLASSES + 1], tbuf[MAXOCLASSES + 1],
qbuf[QBUFSZ], abuf[BUFSZ];
int oc_sym;
boolean badopt = FALSE, compat = (strlen(opts) <= 6), use_menu;
@@ -2985,6 +2981,7 @@ boolean tinitial, tfrom_file;
use_menu = FALSE;
Sprintf(qbuf, "New %s: [%s am] (%s)", fullname, ocl,
*tbuf ? tbuf : "all");
abuf[0] = '\0';
getlin(qbuf, abuf);
wasspace = (abuf[0] == ' '); /* before mungspaces */
op = mungspaces(abuf);
@@ -2994,6 +2991,8 @@ boolean tinitial, tfrom_file;
op = tbuf; /* restore */
else if (abuf[0] == 'm')
use_menu = TRUE;
/* note: abuf[0]=='a' is already handled via clearing the
the old value (above) as a default action */
}
if (use_menu) {
if (wizard && !index(ocl, VENOM_SYM))
@@ -3077,18 +3076,18 @@ boolean tinitial, tfrom_file;
}
/* WINCAP
* player_selection: dialog | prompts */
* player_selection: dialog | prompt/prompts/prompting */
fullname = "player_selection";
if (match_optname(opts, fullname, sizeof("player_selection") - 1, TRUE)) {
if (match_optname(opts, fullname, sizeof "player_selection" - 1, TRUE)) {
if (duplicate)
complain_about_duplicate(opts, 1);
op = string_for_opt(opts, negated);
if (op && !negated) {
if (!strncmpi(op, "dialog", sizeof("dialog") - 1))
if (!strncmpi(op, "dialog", sizeof "dialog" - 1)) {
iflags.wc_player_selection = VIA_DIALOG;
else if (!strncmpi(op, "prompt", sizeof("prompt") - 1))
} else if (!strncmpi(op, "prompt", sizeof "prompt" - 1)) {
iflags.wc_player_selection = VIA_PROMPTS;
else {
} else {
config_error_add("Unknown %s parameter '%s'", fullname, op);
return FALSE;
}
@@ -3110,11 +3109,13 @@ boolean tinitial, tfrom_file;
* end_disclose[NUM_DISCLOSURE_OPT];
* with option settings for the each of the following:
* iagvc [see disclosure_options in decl.c]:
* Legal setting values in that array are:
* Allowed setting values in that array are:
* DISCLOSE_PROMPT_DEFAULT_YES ask with default answer yes
* DISCLOSE_PROMPT_DEFAULT_NO ask with default answer no
* DISCLOSE_YES_WITHOUT_PROMPT always disclose and don't ask
* DISCLOSE_NO_WITHOUT_PROMPT never disclose and don't ask
* DISCLOSE_PROMPT_DEFAULT_SPECIAL for 'vanquished' only...
* DISCLOSE_SPECIAL_WITHOUT_PROMPT ...to set up sort order.
*
* Those setting values can be used in the option
* string as a prefix to get the desired behaviour.
@@ -3350,33 +3351,33 @@ boolean tinitial, tfrom_file;
* |ascii8x12|ascii16x12|ascii12x16|ascii10x18|fit_to_screen]
*/
fullname = "map_mode";
if (match_optname(opts, fullname, sizeof("map_mode") - 1, TRUE)) {
if (match_optname(opts, fullname, sizeof "map_mode" - 1, TRUE)) {
if (duplicate)
complain_about_duplicate(opts, 1);
op = string_for_opt(opts, negated);
if (op && !negated) {
if (!strncmpi(op, "tiles", sizeof("tiles") - 1))
if (!strncmpi(op, "tiles", sizeof "tiles" - 1))
iflags.wc_map_mode = MAP_MODE_TILES;
else if (!strncmpi(op, "ascii4x6", sizeof("ascii4x6") - 1))
else if (!strncmpi(op, "ascii4x6", sizeof "ascii4x6" - 1))
iflags.wc_map_mode = MAP_MODE_ASCII4x6;
else if (!strncmpi(op, "ascii6x8", sizeof("ascii6x8") - 1))
else if (!strncmpi(op, "ascii6x8", sizeof "ascii6x8" - 1))
iflags.wc_map_mode = MAP_MODE_ASCII6x8;
else if (!strncmpi(op, "ascii8x8", sizeof("ascii8x8") - 1))
else if (!strncmpi(op, "ascii8x8", sizeof "ascii8x8" - 1))
iflags.wc_map_mode = MAP_MODE_ASCII8x8;
else if (!strncmpi(op, "ascii16x8", sizeof("ascii16x8") - 1))
else if (!strncmpi(op, "ascii16x8", sizeof "ascii16x8" - 1))
iflags.wc_map_mode = MAP_MODE_ASCII16x8;
else if (!strncmpi(op, "ascii7x12", sizeof("ascii7x12") - 1))
else if (!strncmpi(op, "ascii7x12", sizeof "ascii7x12" - 1))
iflags.wc_map_mode = MAP_MODE_ASCII7x12;
else if (!strncmpi(op, "ascii8x12", sizeof("ascii8x12") - 1))
else if (!strncmpi(op, "ascii8x12", sizeof "ascii8x12" - 1))
iflags.wc_map_mode = MAP_MODE_ASCII8x12;
else if (!strncmpi(op, "ascii16x12", sizeof("ascii16x12") - 1))
else if (!strncmpi(op, "ascii16x12", sizeof "ascii16x12" - 1))
iflags.wc_map_mode = MAP_MODE_ASCII16x12;
else if (!strncmpi(op, "ascii12x16", sizeof("ascii12x16") - 1))
else if (!strncmpi(op, "ascii12x16", sizeof "ascii12x16" - 1))
iflags.wc_map_mode = MAP_MODE_ASCII12x16;
else if (!strncmpi(op, "ascii10x18", sizeof("ascii10x18") - 1))
else if (!strncmpi(op, "ascii10x18", sizeof "ascii10x18" - 1))
iflags.wc_map_mode = MAP_MODE_ASCII10x18;
else if (!strncmpi(op, "fit_to_screen",
sizeof("fit_to_screen") - 1))
sizeof "fit_to_screen" - 1))
iflags.wc_map_mode = MAP_MODE_ASCII_FIT_TO_SCREEN;
else {
config_error_add("Unknown %s parameter '%s'", fullname, op);
@@ -3443,7 +3444,7 @@ boolean tinitial, tfrom_file;
/* WINCAP
* tile_width:nn */
fullname = "tile_width";
if (match_optname(opts, fullname, sizeof("tile_width") - 1, TRUE)) {
if (match_optname(opts, fullname, sizeof "tile_width" - 1, TRUE)) {
if (duplicate)
complain_about_duplicate(opts, 1);
op = string_for_opt(opts, negated);
@@ -3458,7 +3459,7 @@ boolean tinitial, tfrom_file;
/* WINCAP
* tile_file:name */
fullname = "tile_file";
if (match_optname(opts, fullname, sizeof("tile_file") - 1, TRUE)) {
if (match_optname(opts, fullname, sizeof "tile_file" - 1, TRUE)) {
if (duplicate)
complain_about_duplicate(opts, 1);
if ((op = string_for_opt(opts, FALSE)) != 0) {
@@ -3472,7 +3473,7 @@ boolean tinitial, tfrom_file;
/* WINCAP
* tile_height:nn */
fullname = "tile_height";
if (match_optname(opts, fullname, sizeof("tile_height") - 1, TRUE)) {
if (match_optname(opts, fullname, sizeof "tile_height" - 1, TRUE)) {
if (duplicate)
complain_about_duplicate(opts, 1);
op = string_for_opt(opts, negated);
@@ -3488,7 +3489,7 @@ boolean tinitial, tfrom_file;
/* WINCAP
* vary_msgcount:nn */
fullname = "vary_msgcount";
if (match_optname(opts, fullname, sizeof("vary_msgcount") - 1, TRUE)) {
if (match_optname(opts, fullname, sizeof "vary_msgcount" - 1, TRUE)) {
if (duplicate)
complain_about_duplicate(opts, 1);
op = string_for_opt(opts, negated);
@@ -3511,7 +3512,8 @@ boolean tinitial, tfrom_file;
* OPTIONS=windowtype:Foo
* as the first non-comment line of the file.
* Making it first in NETHACKOPTIONS requires it to be at the _end_
* because option strings are processed from right to left.
* because comma-separated option strings are processed from right
* to left.
*/
fullname = "windowtype";
if (match_optname(opts, fullname, 3, TRUE)) {
@@ -3530,7 +3532,7 @@ boolean tinitial, tfrom_file;
choose_windows(buf);
} else {
nmcpy(g.chosen_windowtype, op, WINTYPELEN);
}
}
} else
return FALSE;
return retval;
@@ -3572,7 +3574,7 @@ boolean tinitial, tfrom_file;
/* WINCAP2
* term_cols:amount */
fullname = "term_cols";
if (match_optname(opts, fullname, sizeof("term_cols")-1, TRUE)) {
if (match_optname(opts, fullname, sizeof "term_cols" - 1, TRUE)) {
op = string_for_opt(opts, negated);
iflags.wc2_term_cols = atoi(op);
if (negated)
@@ -3583,7 +3585,7 @@ boolean tinitial, tfrom_file;
/* WINCAP2
* term_rows:amount */
fullname = "term_rows";
if (match_optname(opts, fullname, sizeof("term_rows")-1, TRUE)) {
if (match_optname(opts, fullname, sizeof "term_rows" - 1, TRUE)) {
op = string_for_opt(opts, negated);
iflags.wc2_term_rows = atoi(op);
if (negated)
@@ -3594,7 +3596,7 @@ boolean tinitial, tfrom_file;
/* WINCAP2
* petattr:string */
fullname = "petattr";
if (match_optname(opts, fullname, sizeof("petattr")-1, TRUE)) {
if (match_optname(opts, fullname, sizeof "petattr" - 1, TRUE)) {
op = string_for_opt(opts, negated);
if (op && !negated) {
#ifdef CURSES_GRAPHICS
@@ -3615,7 +3617,7 @@ boolean tinitial, tfrom_file;
/* WINCAP2
* windowborders:n */
fullname = "windowborders";
if (match_optname(opts, fullname, sizeof("windowborders")-1, TRUE)) {
if (match_optname(opts, fullname, sizeof "windowborders" - 1, TRUE)) {
op = string_for_opt(opts, negated);
if (negated && op)
bad_negation(fullname, TRUE);
@@ -3627,10 +3629,9 @@ boolean tinitial, tfrom_file;
else /* Value supplied */
iflags.wc2_windowborders = atoi(op);
if ((iflags.wc2_windowborders > 3)
|| (iflags.wc2_windowborders < 1)) {
|| (iflags.wc2_windowborders < 1)) {
iflags.wc2_windowborders = 0;
config_error_add(
"Badoption - windowborders %s.", opts);
config_error_add("Badoption - windowborders %s.", opts);
}
}
return retval;
@@ -3712,10 +3713,10 @@ boolean tinitial, tfrom_file;
escapes(op, op_buf);
c = *op_buf;
if (illegal_menu_cmd_key(c)) {
if (illegal_menu_cmd_key(c))
return FALSE;
} else
add_menu_cmd_alias(c, default_menu_cmd_info[i].cmd);
add_menu_cmd_alias(c, default_menu_cmd_info[i].cmd);
}
return retval;
}
@@ -3877,8 +3878,9 @@ boolean tinitial, tfrom_file;
#endif /* ?(MAC_GRAPHICS_ENV && BACKWARD_COMPAT) */
} /* "MACgraphics" */
/* OK, if we still haven't recognized the option, check the boolean
* options list
/*
* OK, if we still haven't recognized the option, check the boolean
* options list.
*/
for (i = 0; boolopt[i].name; i++) {
if (match_optname(opts, boolopt[i].name, 3, TRUE)) {
@@ -4111,8 +4113,8 @@ char from_ch, to_ch;
g.mapped_menu_cmds[g.n_menu_mapped] = from_ch;
g.mapped_menu_op[g.n_menu_mapped] = to_ch;
g.n_menu_mapped++;
g.mapped_menu_cmds[g.n_menu_mapped] = 0;
g.mapped_menu_op[g.n_menu_mapped] = 0;
g.mapped_menu_cmds[g.n_menu_mapped] = '\0';
g.mapped_menu_op[g.n_menu_mapped] = '\0';
}
}
@@ -4339,17 +4341,14 @@ doset() /* changing options via menu by Per Liboriussen */
and adjust the format string accordingly */
longest_name_len = 0;
for (pass = 0; pass <= 2; pass++)
for (i = 0; (name = ((pass == 0)
? boolopt[i].name
: (pass == 1)
? compopt[i].name
for (i = 0; (name = ((pass == 0) ? boolopt[i].name
: (pass == 1) ? compopt[i].name
: othropt[i].name)) != 0; i++) {
if (pass == 0 && !boolopt[i].addr)
continue;
optflags = (pass == 0) ? boolopt[i].optflags
: (pass == 1)
? compopt[i].optflags
: othropt[i].optflags;
: (pass == 1) ? compopt[i].optflags
: othropt[i].optflags;
if (optflags < startpass || optflags > endpass)
continue;
if ((is_wc_option(name) && !wc_supported(name))
@@ -4501,8 +4500,7 @@ doset() /* changing options via menu by Per Liboriussen */
preference_update(compopt[opt_indx].name);
}
}
free((genericptr_t) pick_list);
pick_list = (menu_item *) 0;
free((genericptr_t) pick_list), pick_list = (menu_item *) 0;
}
destroy_nhwindow(tmpwin);
@@ -4514,6 +4512,7 @@ doset() /* changing options via menu by Per Liboriussen */
return 0;
}
/* common to msg-types, menu-colors, autopickup-exceptions */
STATIC_OVL int
handle_add_list_remove(optname, numtotal)
const char *optname;
@@ -4764,24 +4763,24 @@ boolean setinitial, setfromfile;
start_menu(tmpwin);
any = g.zeroany;
any.a_char = GPCOORDS_COMPASS;
add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_COMPASS,
0, ATR_NONE, "compass ('east' or '3s' or '2n,4w')",
add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_COMPASS, 0, ATR_NONE,
"compass ('east' or '3s' or '2n,4w')",
(gp == GPCOORDS_COMPASS) ? MENU_SELECTED : MENU_UNSELECTED);
any.a_char = GPCOORDS_COMFULL;
add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_COMFULL, 0, ATR_NONE,
"full compass ('east' or '3south' or '2north,4west')",
(gp == GPCOORDS_COMFULL) ? MENU_SELECTED : MENU_UNSELECTED);
any.a_char = GPCOORDS_MAP;
add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_MAP,
0, ATR_NONE, "map <x,y>",
add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_MAP, 0, ATR_NONE,
"map <x,y>",
(gp == GPCOORDS_MAP) ? MENU_SELECTED : MENU_UNSELECTED);
any.a_char = GPCOORDS_SCREEN;
add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_SCREEN,
0, ATR_NONE, "screen [row,column]",
add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_SCREEN, 0, ATR_NONE,
"screen [row,column]",
(gp == GPCOORDS_SCREEN) ? MENU_SELECTED : MENU_UNSELECTED);
any.a_char = GPCOORDS_NONE;
add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_NONE,
0, ATR_NONE, "none (no coordinates displayed)",
add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_NONE, 0, ATR_NONE,
"none (no coordinates displayed)",
(gp == GPCOORDS_NONE) ? MENU_SELECTED : MENU_UNSELECTED);
any.a_long = 0L;
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
@@ -4789,7 +4788,7 @@ boolean setinitial, setfromfile;
1, 0, COLNO - 1, ROWNO - 1,
flags.verbose ? "; column 0 unused, off left edge" : "");
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
if (strcmp(windowprocs.name, "tty"))
if (strcmp(windowprocs.name, "tty")) /* only show for non-tty */
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
"screen: row is offset to accommodate tty interface's use of top line",
MENU_UNSELECTED);
@@ -4989,7 +4988,7 @@ boolean setinitial, setfromfile;
int opt_idx, nmt, mttyp;
char mtbuf[BUFSZ] = DUMMY;
msgtypes_again:
msgtypes_again:
nmt = msgtype_count();
opt_idx = handle_add_list_remove("message type", nmt);
if (opt_idx == 3) { /* done */
@@ -5051,11 +5050,11 @@ boolean setinitial, setfromfile;
int opt_idx, nmc, mcclr, mcattr;
char mcbuf[BUFSZ] = DUMMY;
menucolors_again:
menucolors_again:
nmc = count_menucolors();
opt_idx = handle_add_list_remove("menucolor", nmc);
if (opt_idx == 3) { /* done */
menucolors_done:
menucolors_done:
if (nmc > 0 && !iflags.use_menu_color)
pline(
"To have menu colors become active, toggle 'menucolors' option to True.");
@@ -5126,15 +5125,18 @@ boolean setinitial, setfromfile;
}
} else if (!strcmp("autopickup_exception", optname)) {
int opt_idx, pass, totalapes = 0, numapes[2] = { 0, 0 };
char apebuf[1 + BUFSZ] = DUMMY; /* so &apebuf[1] is BUFSZ long for getlin() */
char apebuf[1 + BUFSZ]; /* so &apebuf[1] is BUFSZ long for getlin() */
struct autopickup_exception *ape;
ape_again:
ape_again:
totalapes = count_ape_maps(&numapes[AP_LEAVE], &numapes[AP_GRAB]);
opt_idx = handle_add_list_remove("autopickup exception", totalapes);
if (opt_idx == 3) { /* done */
return TRUE;
} else if (opt_idx == 0) { /* add new */
/* EDIT_GETLIN: assume user doesn't user want previous
exception used as default input string for this one... */
apebuf[0] = apebuf[1] = '\0';
getlin("What new autopickup exception pattern?", &apebuf[1]);
mungspaces(&apebuf[1]); /* regularize whitespace */
if (apebuf[1] == '\033')
@@ -5206,7 +5208,6 @@ boolean setinitial, setfromfile;
g.symset[which_set].name = (char *) 0;
res = read_sym_file(which_set);
/* put symset name back */
g.symset[which_set].name = symset_name;
@@ -5685,9 +5686,10 @@ char *buf;
#ifdef CURSES_GRAPHICS
} else if (!strcmp(optname,"windowborders")) {
Sprintf(buf, "%s",
iflags.wc2_windowborders == 1 ? "1=on" :
iflags.wc2_windowborders == 2 ? "2=off" :
iflags.wc2_windowborders == 3 ? "3=auto" : defopt);
(iflags.wc2_windowborders == 1) ? "1=on"
: (iflags.wc2_windowborders == 2) ? "2=off"
: (iflags.wc2_windowborders == 3) ? "3=auto"
: defopt);
#endif
} else if (!strcmp(optname, "windowtype")) {
Sprintf(buf, "%s", windowprocs.name);
@@ -5712,10 +5714,9 @@ char *buf;
#endif
}
if (buf[0])
return buf;
else
return "unknown";
if (!buf[0])
Strcpy(buf, "unknown");
return buf;
}
int
@@ -5794,13 +5795,12 @@ STATIC_OVL void
remove_autopickup_exception(whichape)
struct autopickup_exception *whichape;
{
struct autopickup_exception *ape, *prev = 0;
struct autopickup_exception *ape, *freeape, *prev = 0;
int chain = whichape->grab ? AP_GRAB : AP_LEAVE;
for (ape = iflags.autopickup_exceptions[chain]; ape;) {
if (ape == whichape) {
struct autopickup_exception *freeape = ape;
freeape = ape;
ape = ape->next;
if (prev)
prev->next = ape;
@@ -5993,7 +5993,8 @@ const char *strval;
/* data for option_help() */
static const char *opt_intro[] = {
"", " NetHack Options Help:", "",
"",
" NetHack Options Help:", "",
#define CONFIG_SLOT 3 /* fill in next value at run-time */
(char *) 0,
#if !defined(MICRO) && !defined(MAC)
@@ -6003,7 +6004,8 @@ static const char *opt_intro[] = {
#ifdef VMS
"-- for example, $ DEFINE NETHACKOPTIONS \"noautopickup,fruit:kumquat\"",
#endif
"or press \"O\" while playing and use the menu.", "",
"or press \"O\" while playing and use the menu.",
"",
"Boolean options (which can be negated by prefixing them with '!' or \"no\"):",
(char *) 0
};
@@ -6011,7 +6013,8 @@ static const char *opt_intro[] = {
static const char *opt_epilog[] = {
"",
"Some of the options can be set only before the game is started; those",
"items will not be selectable in the 'O' command's menu.", (char *) 0
"items will not be selectable in the 'O' command's menu.",
(char *) 0
};
void
@@ -6108,11 +6111,11 @@ struct fruit *replace_fruit;
{
register int i;
register struct fruit *f;
int highest_fruit_id = 0;
int highest_fruit_id = 0, globpfx;
char buf[PL_FSIZ], altname[PL_FSIZ];
boolean user_specified = (str == g.pl_fruit);
/* if not user-specified, then it's a fruit name for a fruit on
* a bones level...
* a bones level or from orctown raider's loot...
*/
/* Note: every fruit has an id (kept in obj->spe) of at least 1;
@@ -6123,39 +6126,54 @@ struct fruit *replace_fruit;
/* force fruit to be singular; this handling is not
needed--or wanted--for fruits from bones because
they already received it in their original game */
they already received it in their original game;
str==pl_fruit but makesingular() creates a copy
so we need to copy that back into pl_fruit */
nmcpy(g.pl_fruit, makesingular(str), PL_FSIZ);
/* (assertion doesn't matter; we use 'g.pl_fruit' from here on out) */
/* assert( str == g.pl_fruit ); */
/* disallow naming after other foods (since it'd be impossible
* to tell the difference)
* to tell the difference); globs might have a size prefix which
* needs to be skipped in order to match the object type name
*/
globpfx = (!strncmp(g.pl_fruit, "small ", 6)
|| !strncmp(g.pl_fruit, "large ", 6)) ? 6
: (!strncmp(g.pl_fruit, "very large ", 11)) ? 11
: 0;
for (i = g.bases[FOOD_CLASS]; objects[i].oc_class == FOOD_CLASS; i++) {
if (!strcmp(OBJ_NAME(objects[i]), g.pl_fruit)) {
if (!strcmp(OBJ_NAME(objects[i]), g.pl_fruit)
|| (globpfx > 0
&& !strcmp(OBJ_NAME(objects[i]), &g.pl_fruit[globpfx]))) {
found = TRUE;
break;
}
}
{
if (!found) {
char *c;
for (c = g.pl_fruit; *c >= '0' && *c <= '9'; c++)
continue;
if (isspace((uchar) *c) || *c == 0)
if (!*c || isspace((uchar) *c))
numeric = TRUE;
}
if (found || numeric
|| !strncmp(str, "cursed ", 7)
|| !strncmp(str, "uncursed ", 9)
|| !strncmp(str, "blessed ", 8)
|| !strncmp(str, "partly eaten ", 13)
|| (!strncmp(str, "tin of ", 7)
&& (!strcmp(str + 7, "spinach")
|| name_to_mon(str + 7) >= LOW_PM))
|| !strcmp(str, "empty tin")
|| ((str_end_is(str, " corpse")
|| str_end_is(str, " egg"))
&& name_to_mon(str) >= LOW_PM)) {
/* these checks for applying food attributes to actual items
are case sensitive; "glob of foo" is caught by 'found'
if 'foo' is a valid glob; when not valid, allow it as-is */
|| !strncmp(g.pl_fruit, "cursed ", 7)
|| !strncmp(g.pl_fruit, "uncursed ", 9)
|| !strncmp(g.pl_fruit, "blessed ", 8)
|| !strncmp(g.pl_fruit, "partly eaten ", 13)
|| (!strncmp(g.pl_fruit, "tin of ", 7)
&& (!strcmp(g.pl_fruit + 7, "spinach")
|| name_to_mon(g.pl_fruit + 7) >= LOW_PM))
|| !strcmp(g.pl_fruit, "empty tin")
|| (!strcmp(g.pl_fruit, "glob")
|| (globpfx > 0 && !strcmp("glob", &g.pl_fruit[globpfx])))
|| ((str_end_is(g.pl_fruit, " corpse")
|| str_end_is(g.pl_fruit, " egg"))
&& name_to_mon(g.pl_fruit) >= LOW_PM)) {
Strcpy(buf, g.pl_fruit);
Strcpy(g.pl_fruit, "candied ");
nmcpy(g.pl_fruit + 8, buf, PL_FSIZ - 8);
@@ -6173,11 +6191,11 @@ struct fruit *replace_fruit;
/* replace_fruit is already part of the fruit chain;
update it in place rather than looking it up again */
f = replace_fruit;
copynchars(f->fname, str, PL_FSIZ - 1);
copynchars(f->fname, g.pl_fruit, PL_FSIZ - 1);
goto nonew;
}
} else {
/* not user_supplied, so assumed to be from bones */
/* not user_supplied, so assumed to be from bones (or orc gang) */
copynchars(altname, str, PL_FSIZ - 1);
sanitize_name(altname);
flags.made_fruit = TRUE; /* for safety. Any fruit name added from a
@@ -6682,5 +6700,4 @@ set_playmode()
#endif /* OPTION_LISTS_ONLY */
/*options.c*/

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 pager.c $NHDT-Date: 1546144745 2018/12/30 04:39:05 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.146 $ */
/* NetHack 3.6 pager.c $NHDT-Date: 1546656415 2019/01/05 02:46:55 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.147 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2018. */
/* NetHack may be freely redistributed. See license for details. */
@@ -117,7 +117,7 @@ char *outbuf;
} else if (mon->m_ap_type == M_AP_OBJECT
/* remembered glyph, not glyph_at() which is 'mon' */
&& glyph_is_object(glyph)) {
objfrommap:
objfrommap:
otmp = (struct obj *) 0;
fakeobj = object_from_map(glyph, x, y, &otmp);
Strcat(outbuf, (otmp && otmp->otyp != STRANGE_OBJECT)
@@ -1421,7 +1421,7 @@ boolean without_asking;
} else {
textp = suptext2;
gang = "";
}
}
datawin = create_nhwindow(NHW_MENU);
for (i = 0; textp[i]; i++) {
char buf[BUFSZ];

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 spell.c $NHDT-Date: 1542765363 2018/11/21 01:56:03 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.87 $ */
/* NetHack 3.6 spell.c $NHDT-Date: 1546565814 2019/01/04 01:36:54 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.88 $ */
/* Copyright (c) M. Stephenson 1988 */
/* NetHack may be freely redistributed. See license for details. */
@@ -923,6 +923,10 @@ boolean atme;
} else if (spellknow(spell) <= KEEN / 10) { /* 2000 turns left */
Your("recall of this spell is gradually fading.");
}
/*
* Note: dotele() also calculates energy use and checks nutrition
* and strength requirements; it any of these change, update it too.
*/
energy = (spellev(spell) * 5); /* 5 <= energy <= 35 */
if (u.uhunger <= 10 && spellid(spell) != SPE_DETECT_FOOD) {
@@ -1269,6 +1273,62 @@ throwspell()
return 1;
}
/* add/hide/remove/unhide teleport-away on behalf of dotelecmd() to give
more control to behavior of ^T when used in wizard mode */
int
tport_spell(what)
int what;
{
static struct tport_hideaway {
struct spell savespell;
int tport_indx;
} save_tport;
int i;
/* also defined in teleport.c */
#define NOOP_SPELL 0
#define HIDE_SPELL 1
#define ADD_SPELL 2
#define UNHIDESPELL 3
#define REMOVESPELL 4
for (i = 0; i < MAXSPELL; i++)
if (spellid(i) == SPE_TELEPORT_AWAY || spellid(i) == NO_SPELL)
break;
if (i == MAXSPELL) {
impossible("tport_spell: spellbook full");
/* wizard mode ^T is not able to honor player's menu choice */
} else if (spellid(i) == NO_SPELL) {
if (what == HIDE_SPELL || what == REMOVESPELL) {
save_tport.tport_indx = MAXSPELL;
} else if (what == UNHIDESPELL) {
/*assert( save_tport.savespell.sp_id == SPE_TELEPORT_AWAY );*/
spl_book[save_tport.tport_indx] = save_tport.savespell;
save_tport.tport_indx = MAXSPELL; /* burn bridge... */
} else if (what == ADD_SPELL) {
save_tport.savespell = spl_book[i];
save_tport.tport_indx = i;
spl_book[i].sp_id = SPE_TELEPORT_AWAY;
spl_book[i].sp_lev = objects[SPE_TELEPORT_AWAY].oc_level;
spl_book[i].sp_know = KEEN;
return REMOVESPELL; /* operation needed to reverse */
}
} else { /* spellid(i) == SPE_TELEPORT_AWAY */
if (what == ADD_SPELL || what == UNHIDESPELL) {
save_tport.tport_indx = MAXSPELL;
} else if (what == REMOVESPELL) {
/*assert( i == save_tport.tport_indx );*/
spl_book[i] = save_tport.savespell;
save_tport.tport_indx = MAXSPELL;
} else if (what == HIDE_SPELL) {
save_tport.savespell = spl_book[i];
save_tport.tport_indx = i;
spl_book[i].sp_id = NO_SPELL;
return UNHIDESPELL; /* operation needed to reverse */
}
}
return NOOP_SPELL;
}
/* forget a random selection of known spells due to amnesia;
they used to be lost entirely, as if never learned, but now we
just set the memory retention to zero so that they can't be cast */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 teleport.c $NHDT-Date: 1544401270 2018/12/10 00:21:10 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.81 $ */
/* NetHack 3.6 teleport.c $NHDT-Date: 1546655319 2019/01/05 02:28:39 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.83 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2011. */
/* NetHack may be freely redistributed. See license for details. */
@@ -493,17 +493,123 @@ struct obj *scroll;
return result;
}
/* ^T command; 'm ^T' == choose among several teleport modes */
int
dotelecmd()
{
return dotele((wizard) ? TRUE : FALSE);
long save_HTele, save_ETele;
int res, added, hidden;
boolean ignore_restrictions = FALSE;
/* also defined in spell.c */
#define NOOP_SPELL 0
#define HIDE_SPELL 1
#define ADD_SPELL 2
#define UNHIDESPELL 3
#define REMOVESPELL 4
/* normal mode; ignore 'm' prefix if it was given */
if (!wizard)
return dotele(FALSE);
added = hidden = NOOP_SPELL;
save_HTele = HTeleportation, save_ETele = ETeleportation;
if (!iflags.menu_requested) {
ignore_restrictions = TRUE;
} else {
static const struct tporttypes {
char menulet;
const char *menudesc;
} tports[] = {
/*
* Potential combinations:
* 1) attempt ^T without intrinsic, not know spell;
* 2) via intrinsic, not know spell, obey restrictions;
* 3) via intrinsic, not know spell, ignore restrictions;
* 4) via intrinsic, know spell, obey restrictions;
* 5) via intrinsic, know spell, ignore restrictions;
* 6) via spell, not have intrinsic, obey restrictions;
* 7) via spell, not have intrinsic, ignore restrictions;
* 8) force, obey other restrictions;
* 9) force, ignore restrictions.
* We only support the 1st (t), 2nd (n), 6th (s), and 9th (w).
*
* This ignores the fact that there is an experience level
* (or poly-form) requirement which might make normal ^T fail.
*/
{ 'n', "normal ^T on demand; no spell, obey restrictions" },
{ 's', "via spellcast; no intrinsic teleport" },
{ 't', "try ^T without having it; no spell" },
{ 'w', "debug mode; ignore restrictions" }, /* trad wizard mode */
};
menu_item *picks = (menu_item *) 0;
anything any;
winid win;
int i, tmode;
win = create_nhwindow(NHW_MENU);
start_menu(win);
any = zeroany;
for (i = 0; i < SIZE(tports); ++i) {
any.a_int = (int) tports[i].menulet;
add_menu(win, NO_GLYPH, &any, (char) any.a_int, 0, ATR_NONE,
tports[i].menudesc,
(tports[i].menulet == 'w') ? MENU_SELECTED
: MENU_UNSELECTED);
}
end_menu(win, "Which way do you want to teleport?");
i = select_menu(win, PICK_ONE, &picks);
destroy_nhwindow(win);
if (i > 0) {
tmode = picks[0].item.a_int;
/* if we got 2, use the one which wasn't preselected */
if (i > 1 && tmode == 'w')
tmode = picks[1].item.a_int;
free((genericptr_t) picks);
} else if (i == 0) {
/* preselected one was explicitly chosen and got toggled off */
tmode = 'w';
} else { /* ESC */
return 0;
}
switch (tmode) {
case 'n':
HTeleportation |= I_SPECIAL; /* confer intrinsic teleportation */
hidden = tport_spell(HIDE_SPELL); /* hide teleport-away */
break;
case 's':
HTeleportation = ETeleportation = 0L; /* suppress intrinsic */
added = tport_spell(ADD_SPELL); /* add teleport-away */
break;
case 't':
HTeleportation = ETeleportation = 0L; /* suppress intrinsic */
hidden = tport_spell(HIDE_SPELL); /* hide teleport-away */
break;
case 'w':
ignore_restrictions = TRUE;
break;
}
}
/* if dotele() can be fatal, final disclosure might lie about
intrinsic teleportation; we should be able to live with that
since the menu finagling is only applicable in wizard mode */
res = dotele(ignore_restrictions);
HTeleportation = save_HTele;
ETeleportation = save_ETele;
if (added != NOOP_SPELL || hidden != NOOP_SPELL)
/* can't both be non-NOOP so addition will yield the non-NOOP one */
(void) tport_spell(added + hidden - NOOP_SPELL);
return res;
}
int
dotele(break_the_rules)
boolean break_the_rules;
boolean break_the_rules; /* True: wizard mode ^T */
{
struct trap *trap;
const char *cantdoit;
boolean trap_once = FALSE;
trap = t_at(u.ux, u.uy);
@@ -514,9 +620,9 @@ boolean break_the_rules;
trap_once = trap->once; /* trap may get deleted, save this */
if (trap->once) {
pline("This is a vault teleport, usable once only.");
if (yn("Jump in?") == 'n')
if (yn("Jump in?") == 'n') {
trap = 0;
else {
} else {
deltrap(trap);
newsym(u.ux, u.uy);
}
@@ -531,58 +637,72 @@ boolean break_the_rules;
if (!Teleportation || (u.ulevel < (Role_if(PM_WIZARD) ? 8 : 12)
&& !can_teleport(g.youmonst.data))) {
/* Try to use teleport away spell. */
if (objects[SPE_TELEPORT_AWAY].oc_name_known && !Confusion)
for (sp_no = 0; sp_no < MAXSPELL; sp_no++)
if (g.spl_book[sp_no].sp_id == SPE_TELEPORT_AWAY) {
castit = TRUE;
break;
}
if (!break_the_rules) {
if (!castit) {
if (!Teleportation)
You("don't know that spell.");
else
You("are not able to teleport at will.");
return 0;
}
/* Try to use teleport away spell.
3.6.2: this used to require that you know the spellbook
(probably just intended as an optimization to skip the
lookup loop) but it is possible to know and cast a spell
after forgetting its book due to amnesia. */
for (sp_no = 0; sp_no < MAXSPELL; sp_no++)
if (g.spl_book[sp_no].sp_id == SPE_TELEPORT_AWAY)
break;
/* casting isn't inhibited by being Stunned (...it ought to be) */
castit = (sp_no < MAXSPELL && !Confusion);
if (!castit && !break_the_rules) {
You("%s.",
!Teleportation ? ((sp_no < MAXSPELL)
? "can't cast that spell"
: "don't know that spell")
: "are not able to teleport at will");
return 0;
}
}
if (u.uhunger <= 100 || ACURR(A_STR) < 6) {
if (!break_the_rules) {
You("lack the strength %s.",
castit ? "for a teleport spell" : "to teleport");
return 1;
}
cantdoit = 0;
/* 3.6.2: the magic numbers for hunger, strength, and energy
have been changed to match the ones used in spelleffects().
Also, failing these tests used to return 1 and use a move
even though casting failure due to these reasons doesn't.
[Note: this spellev() is different from the one in spell.c
but they both yield the same result.] */
#define spellev(spell_otyp) ((int) objects[spell_otyp].oc_level)
energy = 5 * spellev(SPE_TELEPORT_AWAY);
if (break_the_rules) {
if (!castit)
energy = 0;
/* spell will cost more if carrying the Amulet, but the
amount is rnd(2 * energy) so we can't know by how much;
average is twice the normal cost, but could be triple;
the extra energy is spent even if that results in not
having enough to cast (which also uses the move) */
else if (u.uen < energy)
u.uen = energy;
} else if (u.uhunger <= 10) {
cantdoit = "are too weak from hunger";
} else if (ACURR(A_STR) < 4) {
cantdoit = "lack the strength";
} else if (energy > u.uen) {
cantdoit = "lack the energy";
}
energy = objects[SPE_TELEPORT_AWAY].oc_level * 7 / 2 - 2;
if (u.uen <= energy) {
if (break_the_rules)
energy = u.uen;
else {
You("lack the energy %s.",
castit ? "for a teleport spell" : "to teleport");
return 1;
}
if (cantdoit) {
You("%s %s.", cantdoit,
castit ? "for a teleport spell" : "to teleport");
return 0;
} else if (check_capacity(
"Your concentration falters from carrying so much.")) {
return 1; /* this failure in spelleffects() also uses the move */
}
if (check_capacity(
"Your concentration falters from carrying so much."))
return 1;
if (castit) {
/* energy cost is deducted in spelleffects() */
exercise(A_WIS, TRUE);
if (spelleffects(sp_no, TRUE))
return 1;
else if (!break_the_rules)
return 0;
} else {
if (!break_the_rules) {
u.uen -= energy;
g.context.botl = 1;
}
/* bypassing spelleffects(); apply energy cost directly */
u.uen -= energy;
g.context.botl = 1;
}
}
@@ -593,7 +713,7 @@ boolean break_the_rules;
tele();
(void) next_to_u();
} else {
You1(shudder_for_moment);
You("%s", shudder_for_moment);
return 0;
}
if (!trap)