Merge branch 'NetHack-3.6.2'

This commit is contained in:
nhmall
2018-09-26 17:39:20 -04:00
38 changed files with 591 additions and 219 deletions
+6 -4
View File
@@ -215,10 +215,12 @@ necessary updates to the community at large.
The official NetHack web site is maintained by Ken Lorber at
http://www.nethack.org/.
On behalf of the NetHack community, thank you very much once again to
M. Drew Streib, Pasi Kallinen and Robin Bandy for providing public
NetHack servers at nethack.alt.org and devnull.net and/or for hosting annual
NetHack tournaments.
On behalf of the NetHack community, thank you very much once again to
M. Drew Streib and Pasi Kallinen for providing a public NetHack server
at nethack.alt.org. Thanks to Keith Simpson and Andy Thomson for
hardfought.org. Thanks to all those unnamed dungeoneers who invest their
time and effort into annual NetHack tournaments such as Junehack
and in days past, devnull.net (gone for now, but not forgotten).
- - - - - - - - - -
+1 -1
View File
@@ -4593,7 +4593,7 @@ The official NetHack web site is maintained by \fBKen Lorber\fP at http://www.ne
SPECIAL THANKS
.pg
On behalf of the NetHack community, thank you very much once
again to \fBM. Drew Streib\fP, \fBPasi Kallinen\fP for providing a
again to \fBM. Drew Streib\fP and \fBPasi Kallinen\fP for providing a
public NetHack server at nethack.alt.org. Thanks to \fBKeith Simpson\fP
and \fBAndy Thomson\fP for hardfought.org. Thanks to all those
unnamed dungeoneers who invest their time and effort into annual
+1 -1
View File
@@ -5377,7 +5377,7 @@ http:{\tt /}{\tt /}www.nethack.org{\tt /}.
\subsection*{Special Thanks}
\nd On behalf of the {\it NetHack\/} community, thank you very much once
again to {\it M. Drew Streib}, {\it Pasi Kallinen} for providing a
again to {\it M. Drew Streib} and {\it Pasi Kallinen} for providing a
public NetHack server at nethack.alt.org. Thanks to {\it Keith Simpson}
and {\it Andy Thomson} for hardfought.org. Thanks to all those
unnamed dungeoneers who invest their time and effort into annual
+30 -1
View File
@@ -128,6 +128,30 @@ cancelled shapeshifter hit by polymorph magic will become uncancelled
polymorph zap which creates a new long worm (or retains an old one via wizard
mode monpolycontrol) can hit that worm multiple times (tail segments)
wishing for "orange" could yield orange or orange colored gem/potion/spellbook
a sleeping or paralyzed mon would be frightened by its reflection when
applying a mirror
prevent leash showing unseen monster as "attached to it"
gremlins seemed impervious to Sunsword's light yet a flash from a camera
caused them to cry out in pain
when objects migrate (fall down stairs) and invisible hero (w/o see invisible,
no-autopickup) descends, stairs get shown instead of object(s) on them
drum of earthquake was causing deafness but oddly enough only when used up
known bear trap was being forgotten about by a player polymorphed into a
flying monster if the player unsuccessfully tried to #untrap it and
moved onto the trap square as a result
no leash-related message is given when a leashed pet yellow light explodes
shop messages refer to shk by name even when shk is not visible but some
used pronoun "it" or "its" in same sentence; ditto for vault guards
poly'd hero and monsters could eat through iron bars in areas where walls
were flagged as non-diggable
Samurai seeing items at a distance could have them be described by their
ordinary names rather than by their Japanese names
wizard mode ^T shouldn't have been diminishing player power but it was
and hilite_status:power settings really drew attention to that
fix missing space in "would flyif you weren't levitating"
a wand of polymorph lost its magical ability for the turn just because the
player using it to engrave happened to be blind, which didn't make
a much sense
Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository
@@ -136,11 +160,16 @@ fix access violation when --debug:xxxx has no other args after it
setting the inverse attribute for gold had the space before "$:"
getting highlighted along with the gold field
sortloot segfaulted when filtering a subset of items (seen with 'A' command)
orctown: prevent Bad fruit #0 and some minor tuning
make long extended commands list be more navigable
simplify #wizidentify; don't rely on having bold menu entries
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
values so that comparisons are correct
orctown: prevent Bad fruit #0 and some minor tuning
tty: fix an out of bounds error in tty_status_update() for BL_HUNGER case
X11: its use of genl_status_update exposed a negative index use that could
lead to a segfault
Platform- and/or Interface-Specific Fixes
+14
View File
@@ -776,6 +776,20 @@ to support:
| hitpointbar | WC2_HITPOINTBAR | wc2_hitpointbar |boolean |
+--------------------+--------------------+--------------------+--------+
more wincap2 for STATUS_HILITES support and control
+--------------------------------- +---------------------------+
| To inform the game engine | |
| that the window port is equipped | bit to set in wincap mask |
| to receive the following in its | |
| x_status_update() routine | |
|----------------------------------+---------------------------+
| BL_FLUSH to render buffered | WC2_FLUSH_STATUS |
| field changes now | |
|----------------------------------+---------------------------+
| BL_RESET to indicate that all | WC2_RESET_STATUS |
| fields should be redone | |
+----------------------------------+---------------------------+
align_message -- where to place message window (top, bottom, left, right)
align_status -- where to place status display (top, bottom, left, right).
ascii_map -- port should display an ascii map if it can.
+4 -2
View File
@@ -1441,6 +1441,7 @@ FDECL(can_blnd, (struct monst *, struct monst *, UCHAR_P, struct obj *));
E boolean FDECL(ranged_attk, (struct permonst *));
E boolean FDECL(hates_silver, (struct permonst *));
E boolean FDECL(mon_hates_silver, (struct monst *));
E boolean FDECL(mon_hates_light, (struct monst *));
E boolean FDECL(passes_bars, (struct permonst *));
E boolean FDECL(can_blow, (struct monst *));
E boolean FDECL(can_chant, (struct monst *));
@@ -1460,7 +1461,7 @@ E int FDECL(monsndx, (struct permonst *));
E int FDECL(name_to_mon, (const char *));
E int FDECL(name_to_monclass, (const char *, int *));
E int FDECL(gender, (struct monst *));
E int FDECL(pronoun_gender, (struct monst *));
E int FDECL(pronoun_gender, (struct monst *, BOOLEAN_P));
E boolean FDECL(levl_follower, (struct monst *));
E int FDECL(little_to_big, (int));
E int FDECL(big_to_little, (int));
@@ -2361,7 +2362,8 @@ E boolean FDECL(safe_teleds, (BOOLEAN_P));
E boolean FDECL(teleport_pet, (struct monst *, BOOLEAN_P));
E void NDECL(tele);
E boolean FDECL(scrolltele, (struct obj *));
E int NDECL(dotele);
E int NDECL(dotelecmd);
E int FDECL(dotele, (BOOLEAN_P));
E void NDECL(level_tele);
E void FDECL(domagicportal, (struct trap *));
E void FDECL(tele_trap, (struct trap *));
+2
View File
@@ -175,6 +175,8 @@
#define is_vampire(ptr) ((ptr)->mlet == S_VAMPIRE)
#define hates_light(ptr) ((ptr) == &mons[PM_GREMLIN])
/* used to vary a few messages */
#define weirdnonliving(ptr) (is_golem(ptr) || (ptr)->mlet == S_VORTEX)
#define nonliving(ptr) \
+1 -1
View File
@@ -381,7 +381,7 @@ extern struct symsetentry symset[NUM_GRAPHICS]; /* from drawing.c */
#define DB_UNDER 28 /* mask for underneath */
/*
* Wall information.
* Wall information. Nondiggable also applies to iron bars.
*/
#define WM_MASK 0x07 /* wall mode (bottom three bits) */
#define W_NONDIGGABLE 0x08
+3 -1
View File
@@ -214,7 +214,9 @@ extern
#define WC2_HITPOINTBAR 0x0040L /* 07 show bar representing hit points */
#define WC2_FLUSH_STATUS 0x0080L /* 08 call status_update(BL_FLUSH)
after updating status window fields */
/* 24 free bits */
#define WC2_RESET_STATUS 0x0100L /* 09 call status_update(BL_RESET) to indicate
draw everything */
/* 23 free bits */
#define ALIGN_LEFT 1
#define ALIGN_RIGHT 2
+9 -3
View File
@@ -236,12 +236,18 @@ struct Gender {
increment to 3 if you allow neuter roles */
extern const struct Gender genders[]; /* table of available genders */
/* pronouns for the hero */
#define uhe() (genders[flags.female ? 1 : 0].he)
#define uhim() (genders[flags.female ? 1 : 0].him)
#define uhis() (genders[flags.female ? 1 : 0].his)
#define mhe(mtmp) (genders[pronoun_gender(mtmp)].he)
#define mhim(mtmp) (genders[pronoun_gender(mtmp)].him)
#define mhis(mtmp) (genders[pronoun_gender(mtmp)].his)
/* corresponding pronouns for monsters; yields "it" when mtmp can't be seen */
#define mhe(mtmp) (genders[pronoun_gender(mtmp, FALSE)].he)
#define mhim(mtmp) (genders[pronoun_gender(mtmp, FALSE)].him)
#define mhis(mtmp) (genders[pronoun_gender(mtmp, FALSE)].his)
/* override "it" if reason is lack of visibility rather than neuter species */
#define noit_mhe(mtmp) (genders[pronoun_gender(mtmp, TRUE)].he)
#define noit_mhim(mtmp) (genders[pronoun_gender(mtmp, TRUE)].him)
#define noit_mhis(mtmp) (genders[pronoun_gender(mtmp, TRUE)].his)
/*** Unified structure specifying alignment information ***/
struct Align {
+17 -9
View File
@@ -215,12 +215,9 @@ int rx, ry, *resp;
/* (most corpses don't retain the monster's sex, so
we're usually forced to use generic pronoun here) */
if (mtmp) {
mptr = &mons[mtmp->mnum];
/* can't use mhe() here; it calls pronoun_gender() which
expects monster to be on the map (visibility check) */
if ((humanoid(mptr) || (mptr->geno & G_UNIQ)
|| type_is_pname(mptr)) && !is_neuter(mptr))
gndr = (int) mtmp->female;
mptr = mtmp->data = &mons[mtmp->mnum];
/* TRUE: override visibility check--it's not on the map */
gndr = pronoun_gender(mtmp, TRUE);
} else {
mptr = &mons[corpse->corpsenm];
if (is_female(mptr))
@@ -956,9 +953,20 @@ struct obj *obj;
(void) rloc(mtmp, TRUE);
} else if (!is_unicorn(mtmp->data) && !humanoid(mtmp->data)
&& (!mtmp->minvis || perceives(mtmp->data)) && rn2(5)) {
if (vis)
pline("%s is frightened by its reflection.", Monnam(mtmp));
monflee(mtmp, d(2, 4), FALSE, FALSE);
boolean do_react = TRUE;
if (mtmp->mfrozen) {
if (vis)
You("discern no obvious reaction from %s.", mon_nam(mtmp));
else
You_feel("a bit silly gesturing the mirror in that direction.");
do_react = FALSE;
}
if (do_react) {
if (vis)
pline("%s is frightened by its reflection.", Monnam(mtmp));
monflee(mtmp, d(2, 4), FALSE, FALSE);
}
} else if (!Blind) {
if (mtmp->minvis && !See_invisible)
;
+2 -1
View File
@@ -810,7 +810,8 @@ boolean *valsetlist;
* the display, call status_update() with BL_FLUSH.
*
*/
if (context.botlx)
if (context.botlx &&
(windowprocs.wincap2 & WC2_RESET_STATUS) != 0L)
status_update(BL_RESET, (genericptr_t) 0, 0, 0,
NO_COLOR, &cond_hilites[0]);
else if ((windowprocs.wincap2 & WC2_FLUSH_STATUS) != 0L)
+151 -35
View File
@@ -116,7 +116,7 @@ extern int NDECL(dosit); /**/
extern int NDECL(dotalk); /**/
extern int NDECL(docast); /**/
extern int NDECL(dovspell); /**/
extern int NDECL(dotele); /**/
extern int NDECL(dotelecmd); /**/
extern int NDECL(dountrap); /**/
extern int NDECL(doversion); /**/
extern int NDECL(doextversion); /**/
@@ -361,39 +361,158 @@ doextcmd(VOID_ARGS)
return retval;
}
/* here after #? - now list all full-word commands */
/* here after #? - now list all full-word commands and provid
some navigation capability through the long list */
int
doextlist(VOID_ARGS)
{
register const struct ext_func_tab *efp;
char buf[BUFSZ];
winid datawin;
char ch = cmd_from_func(doextcmd);
char buf[BUFSZ], searchbuf[BUFSZ], promptbuf[QBUFSZ];
winid menuwin;
anything any;
menu_item *selected;
int n, pass;
int menumode = 0, menushown[2], onelist = 0;
boolean redisplay = TRUE, search = FALSE;
static const char *headings[] = { "Extended commands",
"Debugging Extended Commands" };
datawin = create_nhwindow(NHW_TEXT);
putstr(datawin, 0, "");
putstr(datawin, 0, " Extended Commands List");
putstr(datawin, 0, "");
if (ch) {
Sprintf(buf, " Press '%s', then type:",
visctrl(ch));
putstr(datawin, 0, buf);
putstr(datawin, 0, "");
}
searchbuf[0] = '\0';
menuwin = create_nhwindow(NHW_MENU);
for (efp = extcmdlist; efp->ef_txt; efp++) {
if (!wizard && (efp->flags & WIZMODECMD))
continue;
Sprintf(buf, " %-15s %c %s.",
efp->ef_txt,
(efp->flags & AUTOCOMPLETE) ? '*' : ' ',
efp->ef_desc);
putstr(datawin, 0, buf);
while (redisplay) {
redisplay = FALSE;
any = zeroany;
start_menu(menuwin);
add_menu(menuwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
"Extended Commands List", MENU_UNSELECTED);
add_menu(menuwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
"", MENU_UNSELECTED);
Strcpy(buf, menumode ? "Show" : "Hide");
Strcat(buf, " commands that don't autocomplete");
if (!menumode)
Strcat(buf, " (those not marked with [A])");
any.a_int = 1;
add_menu(menuwin, NO_GLYPH, &any, 'a', 0, ATR_NONE, buf,
MENU_UNSELECTED);
if (!*searchbuf) {
any.a_int = 2;
add_menu(menuwin, NO_GLYPH, &any, 's', 0, ATR_NONE,
"Search extended commands", MENU_UNSELECTED);
} else {
Strcpy(buf, "Show all, clear search");
if (strlen(buf) + strlen(searchbuf) + strlen(" (\"\")") < QBUFSZ)
Sprintf(eos(buf), " (\"%s\")", searchbuf);
any.a_int = 3;
add_menu(menuwin, NO_GLYPH, &any, 's', 0, ATR_NONE,
buf, MENU_UNSELECTED);
}
if (wizard) {
any.a_int = 4;
add_menu(menuwin, NO_GLYPH, &any, 'z', 0, ATR_NONE,
onelist ? "Show debugging commands in separate section"
: "Show all alphabetically, including debugging commands",
MENU_UNSELECTED);
}
any = zeroany;
add_menu(menuwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
"", MENU_UNSELECTED);
menushown[0] = menushown[1] = 0;
n = 0;
for (pass = 0; pass <= 1; ++pass) {
/* skip second pass if not in wizard mode or wizard mode
commands are being integrated into a single list */
if (pass == 1 && (onelist || !wizard))
break;
for (efp = extcmdlist; efp->ef_txt; efp++) {
int wizc;
/* if hiding non-autocomplete commands, skip such */
if (menumode == 1 && (efp->flags & AUTOCOMPLETE) == 0)
continue;
/* if searching, skip this command if it doesn't match */
if (*searchbuf
&& !strstri(efp->ef_txt, searchbuf)
&& !strstri(efp->ef_desc, searchbuf))
continue;
/* skip wizard mode commands if not in wizard mode;
when showing two sections, skip wizard mode commands
in pass==0 and skip other commands in pass==1 */
wizc = (efp->flags & WIZMODECMD) != 0;
if (wizc && !wizard)
continue;
if (!onelist && pass != wizc)
continue;
/* We're about to show an item, have we shown the menu yet?
Doing menu in inner loop like this on demand avoids a
heading with no subordinate entries on the search
results menu. */
if (!menushown[pass]) {
Strcpy(buf, headings[pass]);
add_menu(menuwin, NO_GLYPH, &any, 0, 0,
iflags.menu_headings, buf, MENU_UNSELECTED);
menushown[pass] = 1;
}
Sprintf(buf, " %-14s %-3s %s",
efp->ef_txt,
(efp->flags & AUTOCOMPLETE) ? "[A]" : " ",
efp->ef_desc);
add_menu(menuwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
buf, MENU_UNSELECTED);
++n;
}
if (n)
add_menu(menuwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
"", MENU_UNSELECTED);
}
if (*searchbuf && !n)
add_menu(menuwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
"no matches", MENU_UNSELECTED);
end_menu(menuwin, (char *) 0);
n = select_menu(menuwin, PICK_ONE, &selected);
if (n > 0) {
switch (selected[0].item.a_int) {
case 1: /* 'a': toggle show/hide non-autocomplete */
menumode = 1 - menumode; /* toggle 0 -> 1, 1 -> 0 */
redisplay = TRUE;
break;
case 2: /* 's' when not searching yet: enable search */
search = TRUE;
break;
case 3: /* 's' when already searching: disable search */
search = FALSE;
searchbuf[0] = '\0';
redisplay = TRUE;
break;
case 4: /* 'z': toggle showing wizard mode commands separately */
search = FALSE;
searchbuf[0] = '\0';
onelist = 1 - onelist; /* toggle 0 -> 1, 1 -> 0 */
redisplay = TRUE;
break;
}
free((genericptr_t) selected);
} else {
search = FALSE;
searchbuf[0] = '\0';
}
if (search) {
Strcpy(promptbuf, "Extended command list search phrase");
Strcat(promptbuf, "?");
getlin(promptbuf, searchbuf);
(void) mungspaces(searchbuf);
if (searchbuf[0] == '\033')
searchbuf[0] = '\0';
if (*searchbuf)
redisplay = TRUE;
search = FALSE;
}
}
putstr(datawin, 0, "");
putstr(datawin, 0, " Commands marked with a * will be autocompleted.");
display_nhwindow(datawin, FALSE);
destroy_nhwindow(datawin);
destroy_nhwindow(menuwin);
return 0;
}
@@ -644,14 +763,11 @@ wiz_identify(VOID_ARGS)
/* command remapping might leave #wizidentify as the only way
to invoke us, in which case cmd_from_func() will yield NUL;
it won't matter to display_inventory()/display_pickinv()
if ^I invokes some other command--what matters is that it
is never an inventory letter */
if ^I invokes some other command--what matters is that
display_pickinv() and xname() see override_ID as nonzero */
if (!iflags.override_ID)
iflags.override_ID = C('I');
/* C('I') == ^I == default keystroke for wiz_identify;
it doesn't matter whether the command has been remapped */
if (display_inventory((char *) 0, TRUE) == C('I'))
identify_pack(0, FALSE);
(void) display_inventory((char *) 0, FALSE);
iflags.override_ID = 0;
} else
pline("Unavailable command '%s'.",
@@ -2352,7 +2468,7 @@ int final;
if (Flying)
enl_msg(You_, "would fly", "would have flown",
Levitation
? "if you weren't levitating"
? " if you weren't levitating"
: (save_BFly == FROMOUTSIDE)
? if_surroundings_permitted
/* both surroundings and [latent] levitation */
@@ -3017,7 +3133,7 @@ struct ext_func_tab extcmdlist[] = {
{ 'x', "swap", "swap wielded and secondary weapons", doswapweapon },
{ 'T', "takeoff", "take off one piece of armor", dotakeoff },
{ 'A', "takeoffall", "remove all armor", doddoremarm },
{ C('t'), "teleport", "teleport around the level", dotele, IFBURIED },
{ C('t'), "teleport", "teleport around the level", dotelecmd, IFBURIED },
{ '\0', "terrain", "show map without obstructions",
doterrain, IFBURIED | AUTOCOMPLETE },
{ '\0', "therecmdmenu",
+1 -1
View File
@@ -2086,7 +2086,7 @@ escape_tomb()
if ((Teleportation || can_teleport(youmonst.data))
&& (Teleport_control || rn2(3) < Luck+2)) {
You("attempt a teleport spell.");
(void) dotele(); /* calls unearth_you() */
(void) dotele(FALSE); /* calls unearth_you() */
} else if (u.uburied) { /* still buried after 'port attempt */
boolean good;
+2
View File
@@ -1658,6 +1658,8 @@ boolean near_hero;
stackobj(otmp);
if (!noscatter)
(void) scatter(nx, ny, rnd(2), 0, otmp);
else
newsym(nx, ny);
} else { /* random location */
/* set dummy coordinates because there's no
current position for rloco() to update */
+1 -5
View File
@@ -664,12 +664,8 @@ int x, y;
mon->mundetected = 0; /* wakeup() will handle mimic */
mnam = a_monnam(mon); /* after unhiding */
pronoun = mhim(mon);
pronoun = noit_mhim(mon);
if (!strcmp(mnam, "it")) {
/* mhim() uses pronoun_gender() which forces neuter if monster
can't be seen; we want him/her for humanoid sensed by touch */
if (!strcmp(pronoun, "it") && humanoid(mon->data))
pronoun = genders[mon->female].him;
mnam = !strcmp(pronoun, "it") ? "something" : "someone";
}
if (!glyph_is_monster(glyph) && !glyph_is_invisible(glyph))
+42 -2
View File
@@ -7,6 +7,7 @@
#include "lev.h"
STATIC_VAR NEARDATA struct engr *head_engr;
STATIC_DCL const char *NDECL(blengr);
char *
random_engraving(outbuf)
@@ -472,6 +473,7 @@ doengrave()
boolean teleengr = FALSE; /* TRUE if we move the old engraving */
boolean zapwand = FALSE; /* TRUE if we remove a wand charge */
xchar type = DUST; /* Type of engraving made */
xchar oetype = 0; /* will be set to type of current engraving */
char buf[BUFSZ]; /* Buffer for final/poly engraving text */
char ebuf[BUFSZ]; /* Buffer for initial engraving text */
char fbuf[BUFSZ]; /* Buffer for "your fingers" */
@@ -494,6 +496,8 @@ doengrave()
ebuf[0] = (char) 0;
post_engr_text[0] = (char) 0;
maxelen = BUFSZ - 1;
if (oep)
oetype = oep->engr_type;
if (is_demon(youmonst.data) || youmonst.data->mlet == S_VAMPIRE)
type = ENGR_BLOOD;
@@ -676,9 +680,17 @@ doengrave()
if (!Blind) {
type = (xchar) 0; /* random */
(void) random_engraving(buf);
} else {
/* keep the same type so that feels don't
change and only the text is altered,
but you won't know anyway because
you're a _blind writer_ */
if (oetype)
type = oetype;
xcrypt(blengr(), buf);
}
dengr = TRUE;
}
}
break;
case WAN_NOTHING:
case WAN_UNDEAD_TURNING:
@@ -890,7 +902,8 @@ doengrave()
/* Something has changed the engraving here */
if (*buf) {
make_engr_at(u.ux, u.uy, buf, moves, type);
pline_The("engraving now reads: \"%s\".", buf);
if (!Blind)
pline_The("engraving now reads: \"%s\".", buf);
ptext = FALSE;
}
if (zapwand && (otmp->spe < 0)) {
@@ -1286,4 +1299,31 @@ const char *str;
return;
}
static const char blind_writing[][21] = {
{0x44, 0x66, 0x6d, 0x69, 0x62, 0x65, 0x22, 0x45, 0x7b, 0x71,
0x65, 0x6d, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{0x51, 0x67, 0x60, 0x7a, 0x7f, 0x21, 0x40, 0x71, 0x6b, 0x71,
0x6f, 0x67, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x49, 0x6d, 0x73, 0x69, 0x62, 0x65, 0x22, 0x4c, 0x61, 0x7c,
0x6d, 0x67, 0x24, 0x42, 0x7f, 0x69, 0x6c, 0x77, 0x67, 0x7e, 0x00},
{0x4b, 0x6d, 0x6c, 0x66, 0x30, 0x4c, 0x6b, 0x68, 0x7c, 0x7f,
0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x51, 0x67, 0x70, 0x7a, 0x7f, 0x6f, 0x67, 0x68, 0x64, 0x71,
0x21, 0x4f, 0x6b, 0x6d, 0x7e, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x4c, 0x63, 0x76, 0x61, 0x71, 0x21, 0x48, 0x6b, 0x7b, 0x75,
0x67, 0x63, 0x24, 0x45, 0x65, 0x6b, 0x6b, 0x65, 0x00, 0x00, 0x00},
{0x4c, 0x67, 0x68, 0x6b, 0x78, 0x68, 0x6d, 0x76, 0x7a, 0x75,
0x21, 0x4f, 0x71, 0x7a, 0x75, 0x6f, 0x77, 0x00, 0x00, 0x00, 0x00},
{0x44, 0x66, 0x6d, 0x7c, 0x78, 0x21, 0x50, 0x65, 0x66, 0x65,
0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x44, 0x66, 0x73, 0x69, 0x62, 0x65, 0x22, 0x56, 0x7d, 0x63,
0x69, 0x76, 0x6b, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
};
STATIC_OVL const char *
blengr(VOID_ARGS)
{
return blind_writing[rn2(SIZE(blind_writing))];
}
/*engrave.c*/
+1
View File
@@ -657,6 +657,7 @@ struct obj *obj; /* only scatter this obj */
(void) break_statue(otmp);
place_object(otmp, sx, sy); /* put fragments on floor */
}
newsym(sx, sy); /* in case it's beyond radius of 'farthest' */
used_up = TRUE;
/* 1 in 10 chance of destruction of obj; glass, egg destruction */
+6 -3
View File
@@ -364,8 +364,8 @@ moverock()
/*
* still_chewing()
*
* Chew on a wall, door, or boulder. Returns TRUE if still eating, FALSE
* when done.
* Chew on a wall, door, or boulder. [What about statues?]
* Returns TRUE if still eating, FALSE when done.
*/
STATIC_OVL int
still_chewing(x, y)
@@ -379,7 +379,10 @@ xchar x, y;
(void) memset((genericptr_t) &context.digging, 0,
sizeof (struct dig_info));
if (!boulder && IS_ROCK(lev->typ) && !may_dig(x, y)) {
if (!boulder
&& ((IS_ROCK(lev->typ) && !may_dig(x, y))
/* may_dig() checks W_NONDIGGABLE but doesn't handle iron bars */
|| (lev->typ == IRONBARS && (lev->wall_info & W_NONDIGGABLE)))) {
You("hurt your teeth on the %s.",
(lev->typ == IRONBARS)
? "bars"
+22 -22
View File
@@ -2593,24 +2593,27 @@ long *out_cnt;
char prompt[QBUFSZ];
unid_cnt = count_unidentified(invent);
add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE,
"Debug Identify",
MENU_UNSELECTED);
Sprintf(prompt, "Debug Identify"); /* 'title' rather than 'prompt' */
if (unid_cnt)
Sprintf(eos(prompt),
" -- unidentified or partially identified item%s",
plur(unid_cnt));
add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, prompt, MENU_UNSELECTED);
if (!unid_cnt) {
add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE,
"(all items are permanently identified already)",
MENU_UNSELECTED);
} else {
any.a_obj = &wizid_fakeobj;
Sprintf(prompt, "select %s to permanently identify",
(unid_cnt == 1) ? "it": "any or all of them");
/* wiz_identify stuffed the wiz_identify command character (^I)
into iflags.override_ID for our use as an accelerator;
it could be ambiguous as a selector but the only time it
is wanted is in case where no item is being selected */
Sprintf(prompt,
"Select %sthe %d bolded item%s to permanently identify (%s for all)",
(unid_cnt == 1) ? "": "any of ", unid_cnt,
(unid_cnt > 1) ? "s" : "",
visctrl(iflags.override_ID));
it could be ambiguous if player has assigned a letter to
the #wizidentify command */
if (unid_cnt > 1)
Sprintf(eos(prompt), " (%s for all)",
visctrl(iflags.override_ID));
add_menu(win, NO_GLYPH, &any, '_', iflags.override_ID, ATR_NONE,
prompt, MENU_UNSELECTED);
wizid = TRUE;
@@ -2630,6 +2633,8 @@ nextclass:
if (lets && !index(lets, otmp->invlet))
continue;
if (!flags.sortpack || otmp->oclass == *invlet) {
if (wizid && !not_fully_identified(otmp))
continue;
any = zeroany; /* all bits zero */
ilet = otmp->invlet;
if (flags.sortpack && !classcount) {
@@ -2643,9 +2648,7 @@ nextclass:
any.a_obj = otmp;
else
any.a_char = ilet;
add_menu(win, obj_to_glyph(otmp), &any, ilet, 0,
(wizid && not_fully_identified(otmp)) ?
ATR_BOLD : ATR_NONE,
add_menu(win, obj_to_glyph(otmp), &any, ilet, 0, ATR_NONE,
doname(otmp), MENU_UNSELECTED);
}
}
@@ -2678,21 +2681,18 @@ nextclass:
}
end_menu(win, query && *query ? query : (char *) 0);
n = select_menu(win, wizid ? PICK_ANY :
want_reply ? PICK_ONE : PICK_NONE, &selected);
n = select_menu(win,
wizid ? PICK_ANY : want_reply ? PICK_ONE : PICK_NONE,
&selected);
if (n > 0) {
if (wizid) {
int i = n;
int i;
ret = '\0';
while (--i >= 0) {
for (i = 0; i < n; ++i) {
otmp = selected[i].item.a_obj;
if (otmp == &wizid_fakeobj) {
/* C('I') == ^I == default keystroke for wiz_identify;
it is guaranteed not to be in use as an inventory letter
(wiz_identify might be remapped to an ordinary letter,
making iflags.override_ID ambiguous as a return value) */
ret = C('I');
identify_pack(0, FALSE);
} else {
if (not_fully_identified(otmp))
(void) identify(otmp);
+11 -3
View File
@@ -45,9 +45,10 @@ mon_nam_too(outbuf, mon, other_mon)
char *outbuf;
struct monst *mon, *other_mon;
{
Strcpy(outbuf, mon_nam(mon));
if (mon == other_mon)
switch (pronoun_gender(mon)) {
if (mon != other_mon)
Strcpy(outbuf, mon_nam(mon));
else
switch (pronoun_gender(mon, FALSE)) {
case 0:
Strcpy(outbuf, "himself");
break;
@@ -779,10 +780,17 @@ struct attack *mattk;
/* Kill off aggressor if it didn't die. */
if (!(result & MM_AGR_DIED)) {
boolean was_leashed = (magr->mleashed);
mondead(magr);
if (!DEADMONSTER(magr))
return result; /* life saved */
result |= MM_AGR_DIED;
/* mondead() -> m_detach() -> m_unleash() always suppresses
the m_unleash() slack message, so deliver it here instead */
if (was_leashed)
Your("leash falls slack.");
}
if (magr->mtame) /* give this one even if it was visible */
You(brief_feeling, "melancholy");
+1 -1
View File
@@ -2613,7 +2613,7 @@ struct monst *mon;
;
} else if (rn2(20) < ACURR(A_CHA)) {
pline("%s demands that you pay %s, but you refuse...",
noit_Monnam(mon), Blind ? (fem ? "her" : "him") : mhim(mon));
noit_Monnam(mon), noit_mhim(mon));
} else if (u.umonnum == PM_LEPRECHAUN) {
pline("%s tries to take your money, but fails...", noit_Monnam(mon));
} else {
+5 -1
View File
@@ -1320,7 +1320,11 @@ nexttry: /* eels prefer the water, but if there is no water nearby,
&& !((IS_TREE(ntyp) ? treeok : rockok) && may_dig(nx, ny)))
continue;
/* KMH -- Added iron bars */
if (ntyp == IRONBARS && !(flag & ALLOW_BARS))
if (ntyp == IRONBARS
&& (!(flag & ALLOW_BARS)
|| ((levl[nx][ny].wall_info & W_NONDIGGABLE)
&& (dmgtype(mdat, AD_RUST)
|| dmgtype(mdat, AD_CORR)))))
continue;
if (IS_DOOR(ntyp) && !(amorphous(mdat) || can_fog(mon))
&& (((levl[nx][ny].doormask & D_CLOSED) && !(flag & OPENDOOR))
+13 -2
View File
@@ -312,6 +312,14 @@ register struct permonst *ptr;
|| (ptr->mlet == S_IMP && ptr != &mons[PM_TENGU]));
}
/* True if specific monster is especially affected by light-emitting weapons */
boolean
mon_hates_light(mon)
struct monst *mon;
{
return (boolean) (hates_light(mon->data));
}
/* True iff the type of monster pass through iron bars */
boolean
passes_bars(mptr)
@@ -892,10 +900,13 @@ register struct monst *mtmp;
/* Like gender(), but lower animals and such are still "it".
This is the one we want to use when printing messages. */
int
pronoun_gender(mtmp)
pronoun_gender(mtmp, override_vis)
register struct monst *mtmp;
boolean override_vis; /* if True then 'no it' unless neuter */
{
if (is_neuter(mtmp->data) || !canspotmon(mtmp))
if (!override_vis && !canspotmon(mtmp))
return 2;
if (is_neuter(mtmp->data))
return 2;
return (humanoid(mtmp->data) || (mtmp->data->geno & G_UNIQ)
|| type_is_pname(mtmp->data)) ? (int) mtmp->female : 2;
+22 -4
View File
@@ -255,6 +255,14 @@ struct monst *mon;
}
}
#define flees_light(mon) ((mon)->data == &mons[PM_GREMLIN] && \
(uwep && artifact_light(uwep) && uwep->lamplit))
/* we could include this in the above macro, but probably overkill/overhead */
/* (!((which_armor((mon), W_ARMC) != 0) && ((which_armor((mon), W_ARMH) != 0))) && */
/* monster begins fleeing for the specified time, 0 means untimed flee
* if first, only adds fleetime if monster isn't already fleeing
* if fleemsg, prints a message about new flight, otherwise, caller should */
@@ -289,9 +297,15 @@ boolean fleemsg;
/* unfortunately we can't distinguish between temporary
sleep and temporary paralysis, so both conditions
receive the same alternate message */
if (!mtmp->mcanmove || !mtmp->data->mmove)
if (!mtmp->mcanmove || !mtmp->data->mmove) {
pline("%s seems to flinch.", Adjmonnam(mtmp, "immobile"));
else
} else if (flees_light(mtmp)) {
if (rn2(10) || Deaf)
pline("%s flees from the painful light of %s.",
Monnam(mtmp), bare_artifactname(uwep));
else
verbalize("Bright light!");
} else
pline("%s turns to flee.", Monnam(mtmp));
}
mtmp->mflee = 1;
@@ -306,7 +320,7 @@ register struct monst *mtmp;
int *inrange, *nearby, *scared;
{
int seescaryx, seescaryy;
boolean sawscary = FALSE;
boolean sawscary = FALSE, bravegremlin = (rn2(5) == 0);
*inrange = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy)
<= (BOLT_LIM * BOLT_LIM));
@@ -329,6 +343,7 @@ int *inrange, *nearby, *scared;
sawscary = onscary(seescaryx, seescaryy, mtmp);
if (*nearby && (sawscary
|| (flees_light(mtmp) && !bravegremlin)
|| (!mtmp->mpeaceful && in_your_sanctuary(mtmp, 0, 0)))) {
*scared = 1;
monflee(mtmp, rnd(rn2(7) ? 10 : 100), TRUE, TRUE);
@@ -336,6 +351,8 @@ int *inrange, *nearby, *scared;
*scared = 0;
}
#undef flees_light
/* perform a special one-time action for a monster; returns -1 if nothing
special happened, 0 if monster uses up its turn, 1 if monster is killed */
STATIC_OVL int
@@ -1371,7 +1388,8 @@ postmov:
add_damage(mtmp->mx, mtmp->my, 0L);
}
} else if (levl[mtmp->mx][mtmp->my].typ == IRONBARS) {
if (may_dig(mtmp->mx, mtmp->my)
/* 3.6.2: was using may_dig() but it doesn't handle bars */
if (!(levl[mtmp->mx][mtmp->my].wall_info & W_NONDIGGABLE)
&& (dmgtype(ptr, AD_RUST) || dmgtype(ptr, AD_CORR))) {
if (canseemon(mtmp))
pline("%s eats through the iron bars.", Monnam(mtmp));
+22 -5
View File
@@ -445,6 +445,11 @@ generic_lvl_desc()
return "dungeon";
}
const char *beats[] = {
"stepper", "one drop", "slow two", "triple stroke roll",
"double shuffle", "half-time shuffle", "second line", "train"
};
/*
* The player is trying to extract something from his/her instrument.
*/
@@ -454,6 +459,7 @@ struct obj *instr;
{
int damage, mode, do_spec = !(Stunned || Confusion);
struct obj itmp;
boolean mundane = FALSE;
itmp = *instr;
itmp.oextra = (struct oextra *) 0; /* ok on this copy as instr maintains
@@ -462,8 +468,10 @@ struct obj *instr;
/* if won't yield special effect, make sound of mundane counterpart */
if (!do_spec || instr->spe <= 0)
while (objects[itmp.otyp].oc_magic)
while (objects[itmp.otyp].oc_magic) {
itmp.otyp -= 1;
mundane = TRUE;
}
#ifdef MAC
mac_speaker(&itmp, "C");
#endif
@@ -579,6 +587,10 @@ struct obj *instr;
exercise(A_DEX, TRUE);
break;
case DRUM_OF_EARTHQUAKE: /* create several pits */
/* a drum of earthquake does cause not cause deafness
while still magically functional, nor afterwards
when it invokes the LEATHER_DRUM case instead and
mundane is flagged */
consume_obj_charge(instr, TRUE);
You("produce a heavy, thunderous rolling!");
@@ -589,10 +601,15 @@ struct obj *instr;
makeknown(DRUM_OF_EARTHQUAKE);
break;
case LEATHER_DRUM: /* Awaken monsters */
You("beat a deafening row!");
awaken_monsters(u.ulevel * 40);
incr_itimeout(&HDeaf, rn1(20, 30));
exercise(A_WIS, FALSE);
if (!mundane) {
You("beat a deafening row!");
incr_itimeout(&HDeaf, rn1(20, 30));
exercise(A_WIS, FALSE);
} else
You("%s %s.",
rn2(2) ? "butcher" : rn2(2) ? "manage" : "pull off",
an(beats[rn2(SIZE(beats))]));
awaken_monsters(u.ulevel * (mundane ? 5 : 40));
context.botl = TRUE;
break;
default:
+32 -20
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 objnam.c $NHDT-Date: 1537313446 2018/09/18 23:30:46 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.208 $ */
/* NetHack 3.6 objnam.c $NHDT-Date: 1537659941 2018/09/22 23:45:41 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.212 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2011. */
/* NetHack may be freely redistributed. See license for details. */
@@ -12,7 +12,7 @@
STATIC_DCL char *FDECL(strprepend, (char *, const char *));
STATIC_DCL short FDECL(rnd_otyp_by_wpnskill, (SCHAR_P));
STATIC_DCL short FDECL(rnd_otyp_by_namedesc, (char *, CHAR_P));
STATIC_DCL short FDECL(rnd_otyp_by_namedesc, (const char *, CHAR_P, int));
STATIC_DCL boolean FDECL(wishymatch, (const char *, const char *, BOOLEAN_P));
STATIC_DCL char *NDECL(nextobuf);
STATIC_DCL void FDECL(releaseobuf, (char *));
@@ -403,7 +403,7 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
register struct objclass *ocl = &objects[typ];
int nn = ocl->oc_name_known, omndx = obj->corpsenm;
const char *actualn = OBJ_NAME(*ocl);
const char *dn = OBJ_DESCR(*ocl) ? OBJ_DESCR(*ocl) : actualn;
const char *dn = OBJ_DESCR(*ocl);
const char *un = ocl->oc_uname;
boolean pluralize = (obj->quan != 1L) && !(cxn_flags & CXN_SINGULAR);
boolean known, dknown, bknown;
@@ -411,6 +411,10 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
buf = nextobuf() + PREFIX; /* leave room for "17 -3 " */
if (Role_if(PM_SAMURAI) && Japanese_item_name(typ))
actualn = Japanese_item_name(typ);
/* 3.6.2: this used to be part of 'dn's initialization, but it
needs to come after possibly overriding 'actualn' */
if (!dn)
dn = actualn;
buf[0] = '\0';
/*
@@ -1052,7 +1056,7 @@ unsigned doname_flags;
obj->leashmon = 0;
} else {
Sprintf(eos(bp), " (attached to %s)",
a_monnam(mlsh));
noit_mon_nam(mlsh));
}
break;
}
@@ -2693,6 +2697,7 @@ schar skill;
{
int i, n = 0;
short otyp = STRANGE_OBJECT;
for (i = bases[WEAPON_CLASS];
i < NUM_OBJECTS && objects[i].oc_class == WEAPON_CLASS; i++)
if (objects[i].oc_skill == skill) {
@@ -2711,20 +2716,29 @@ schar skill;
}
STATIC_OVL short
rnd_otyp_by_namedesc(name, oclass)
char *name;
rnd_otyp_by_namedesc(name, oclass, xtra_prob)
const char *name;
char oclass;
int xtra_prob; /* to force 0% random generation items to also be considered */
{
int i, n = 0;
short validobjs[NUM_OBJECTS];
register const char *zn;
long maxprob = 0;
int prob, maxprob = 0;
if (!name)
if (!name || !*name)
return STRANGE_OBJECT;
memset((genericptr_t) validobjs, 0, sizeof validobjs);
/* FIXME:
* When this spans classes (the !oclass case), the item
* probabilities are not very useful because they don't take
* the class generation probability into account. [If 10%
* of spellbooks were blank and 1% of scrolls were blank,
* "blank" would have 10/11 chance to yield a blook even though
* scrolls are supposed to be much more common than books.]
*/
for (i = oclass ? bases[(int) oclass] : STRANGE_OBJECT + 1;
i < NUM_OBJECTS && (!oclass || objects[i].oc_class == oclass);
++i) {
@@ -2737,17 +2751,15 @@ char oclass;
|| ((zn = objects[i].oc_uname) != 0
&& wishymatch(name, zn, FALSE))) {
validobjs[n++] = (short) i;
maxprob += (objects[i].oc_prob + 1);
maxprob += (objects[i].oc_prob + xtra_prob);
}
}
if (n > 0 && maxprob) {
long prob = rn2(maxprob);
i = 0;
while (i < n - 1
&& (prob -= (objects[validobjs[i]].oc_prob + 1)) >= 0)
i++;
prob = rn2(maxprob);
for (i = 0; i < n - 1; i++)
if ((prob -= (objects[validobjs[i]].oc_prob + xtra_prob)) < 0)
break;
return validobjs[i];
}
return STRANGE_OBJECT;
@@ -2757,7 +2769,7 @@ int
shiny_obj(oclass)
char oclass;
{
return (int) rnd_otyp_by_namedesc("shiny", oclass);
return (int) rnd_otyp_by_namedesc("shiny", oclass, 0);
}
/*
@@ -3390,10 +3402,10 @@ srch:
}
}
if (((typ = rnd_otyp_by_namedesc(actualn, oclass)) != STRANGE_OBJECT)
|| ((typ = rnd_otyp_by_namedesc(dn, oclass)) != STRANGE_OBJECT)
|| ((typ = rnd_otyp_by_namedesc(un, oclass)) != STRANGE_OBJECT)
|| ((typ = rnd_otyp_by_namedesc(origbp, oclass)) != STRANGE_OBJECT))
if (((typ = rnd_otyp_by_namedesc(actualn, oclass, 1)) != STRANGE_OBJECT)
|| ((typ = rnd_otyp_by_namedesc(dn, oclass, 1)) != STRANGE_OBJECT)
|| ((typ = rnd_otyp_by_namedesc(un, oclass, 1)) != STRANGE_OBJECT)
|| ((typ = rnd_otyp_by_namedesc(origbp, oclass, 1)) != STRANGE_OBJECT))
goto typfnd;
typ = 0;
+64 -66
View File
@@ -435,9 +435,9 @@ boolean newlev;
plname);
else
pline("%s %s that you need to pay before leaving%s",
Shknam(shkp),
NOTANGRY(shkp) ? "points out" : "makes it clear",
NOTANGRY(shkp) ? "." : "!");
Shknam(shkp),
NOTANGRY(shkp) ? "points out" : "makes it clear",
NOTANGRY(shkp) ? "." : "!");
return;
}
@@ -580,12 +580,12 @@ char *enterstring;
return; /* no dialog */
if (Invis) {
pline("%s senses your presence.", shkname(shkp));
pline("%s senses your presence.", Shknam(shkp));
if (!Deaf && !muteshk(shkp))
verbalize("Invisible customers are not welcome!");
else
pline("%s stands firm as if %s knows you are there.",
Shknam(shkp), mhe(shkp));
Shknam(shkp), noit_mhe(shkp));
return;
}
@@ -594,21 +594,18 @@ char *enterstring;
if (ANGRY(shkp)) {
if (!Deaf && !muteshk(shkp))
verbalize("So, %s, you dare return to %s %s?!", plname,
s_suffix(shkname(shkp)), shtypes[rt - SHOPBASE].name);
s_suffix(shkname(shkp)), shtypes[rt - SHOPBASE].name);
else
pline("%s seems %s over your return to %s %s!",
Shknam(shkp),
angrytexts[rn2(SIZE(angrytexts))],
mhis(shkp),
shtypes[rt - SHOPBASE].name);
Shknam(shkp), angrytexts[rn2(SIZE(angrytexts))],
noit_mhis(shkp), shtypes[rt - SHOPBASE].name);
} else if (eshkp->robbed) {
if (!Deaf)
pline("%s mutters imprecations against shoplifters.",
shkname(shkp));
Shknam(shkp));
else
pline("%s is combing through %s inventory list.",
Shknam(shkp),
mhis(shkp));
Shknam(shkp), noit_mhis(shkp));
} else {
if (!Deaf && !muteshk(shkp))
verbalize("%s, %s! Welcome%s to %s %s!", Hello(shkp), plname,
@@ -655,20 +652,20 @@ char *enterstring;
tool, plur(cnt));
else
pline("%s %s to let you in with your %s%s.",
Shknam(shkp),
NOTANGRY(shkp) ? "is hesitant" : "refuses",
tool, plur(cnt));
Shknam(shkp),
NOTANGRY(shkp) ? "is hesitant" : "refuses",
tool, plur(cnt));
should_block = TRUE;
} else if (u.usteed) {
if (!Deaf && !muteshk(shkp))
verbalize(NOTANGRY(shkp) ? "Will you please leave %s outside?"
: "Leave %s outside.",
y_monnam(u.usteed));
y_monnam(u.usteed));
else
pline("%s %s to let you in while you're riding %s.",
Shknam(shkp),
NOTANGRY(shkp) ? "doesn't want" : "refuses",
y_monnam(u.usteed));
Shknam(shkp),
NOTANGRY(shkp) ? "doesn't want" : "refuses",
y_monnam(u.usteed));
should_block = TRUE;
} else {
should_block =
@@ -1343,7 +1340,7 @@ proceed:
} else {
if (umoney > ltmp) {
You("give %s the %ld gold piece%s %s asked for.",
shkname(shkp), ltmp, plur(ltmp), mhe(shkp));
shkname(shkp), ltmp, plur(ltmp), noit_mhe(shkp));
pay(ltmp, shkp);
} else {
You("give %s all your%s gold.", shkname(shkp),
@@ -1353,7 +1350,8 @@ proceed:
pline("But you have hidden gold!");
}
if ((umoney < ltmp / 2L) || (umoney < ltmp && stashed_gold))
pline("Unfortunately, %s doesn't look satisfied.", mhe(shkp));
pline("Unfortunately, %s doesn't look satisfied.",
noit_mhe(shkp));
else
make_happy_shk(shkp, FALSE);
}
@@ -1373,13 +1371,14 @@ proceed:
if (!umoney)
pline(no_money, stashed_gold ? " seem to" : "");
else
pline(not_enough_money, mhim(shkp));
pline(not_enough_money, noit_mhim(shkp));
return 1;
}
pline("But since %s shop has been robbed recently,", mhis(shkp));
pline("But since %s shop has been robbed recently,",
noit_mhis(shkp));
pline("you %scompensate %s for %s losses.",
(umoney < ltmp) ? "partially " : "", shkname(shkp),
mhis(shkp));
noit_mhis(shkp));
pay(umoney < ltmp ? umoney : ltmp, shkp);
make_happy_shk(shkp, FALSE);
} else {
@@ -1390,11 +1389,14 @@ proceed:
if (!umoney)
pline(no_money, stashed_gold ? " seem to" : "");
else
pline(not_enough_money, mhim(shkp));
pline(not_enough_money, noit_mhim(shkp));
return 1;
}
You("try to appease %s by giving %s 1000 gold pieces.",
x_monnam(shkp, ARTICLE_THE, "angry", 0, FALSE), mhim(shkp));
canspotmon(shkp)
? x_monnam(shkp, ARTICLE_THE, "angry", 0, FALSE)
: shkname(shkp),
noit_mhim(shkp));
pay(1000L, shkp);
if (strncmp(eshkp->customer, plname, PL_NSIZ) || rn2(3))
make_happy_shk(shkp, FALSE);
@@ -1538,13 +1540,13 @@ proceed:
}
if (!ANGRY(shkp) && paid) {
if (!Deaf && !muteshk(shkp))
verbalize("Thank you for shopping in %s %s!", s_suffix(shkname(shkp)),
shtypes[eshkp->shoptype - SHOPBASE].name);
verbalize("Thank you for shopping in %s %s!",
s_suffix(shkname(shkp)),
shtypes[eshkp->shoptype - SHOPBASE].name);
else
pline("%s nods appreciatively at you for shopping in %s %s!",
Shknam(shkp),
mhis(shkp),
shtypes[eshkp->shoptype - SHOPBASE].name);
Shknam(shkp), noit_mhis(shkp),
shtypes[eshkp->shoptype - SHOPBASE].name);
}
return 1;
}
@@ -1778,7 +1780,7 @@ int croaked;
if (cansee(shkp->mx, shkp->my) && croaked) {
takes[0] = '\0';
if (has_head(shkp->data) && !rn2(2))
Sprintf(takes, ", shakes %s %s,", mhis(shkp),
Sprintf(takes, ", shakes %s %s,", noit_mhis(shkp),
mbodypart(shkp, HEAD));
pline("%s %slooks at your corpse%s and %s.", Shknam(shkp),
(!shkp->mcanmove || shkp->msleeping) ? "wakes up, " : "",
@@ -1797,7 +1799,7 @@ int croaked;
taken = (invent != 0);
if (taken)
pline("%s gratefully inherits all your possessions.",
shkname(shkp));
Shknam(shkp));
set_repo_loc(shkp);
goto clear;
}
@@ -1828,7 +1830,7 @@ int croaked;
if (umoney > 0)
money2mon(shkp, umoney);
context.botl = 1;
pline("%s %s all your possessions.", shkname(shkp), takes);
pline("%s %s all your possessions.", Shknam(shkp), takes);
taken = TRUE;
/* where to put player's invent (after disclosure) */
set_repo_loc(shkp);
@@ -1838,7 +1840,7 @@ int croaked;
pline("%s %s the %ld %s %sowed %s.", Shknam(shkp),
takes, loss, currency(loss),
strncmp(eshkp->customer, plname, PL_NSIZ) ? "" : "you ",
mhim(shkp));
noit_mhim(shkp));
/* shopkeeper has now been paid in full */
pacify_shk(shkp);
eshkp->following = 0;
@@ -2218,9 +2220,8 @@ boolean quietly;
verbalize("I won't stock that. Take it out of here!");
else
pline("%s shakes %s %s in refusal.",
Shknam(shkp),
mhis(shkp),
mbodypart(shkp, HEAD));
Shknam(shkp), noit_mhis(shkp),
mbodypart(shkp, HEAD));
}
}
return TRUE;
@@ -3010,7 +3011,7 @@ xchar x, y;
if (sell_how == SELL_NORMAL || auto_credit) {
c = sell_response = 'y';
} else if (sell_response != 'n') {
pline("%s cannot pay you at present.", shkname(shkp));
pline("%s cannot pay you at present.", Shknam(shkp));
Sprintf(qbuf, "Will you accept %ld %s in credit for ", tmpcr,
currency(tmpcr));
c = ynaq(safe_qbuf(qbuf, qbuf, "?", obj, doname, thesimpleoname,
@@ -3079,7 +3080,7 @@ xchar x, y;
"... your items in the <bag>. Sell them?"
*/
Sprintf(qbuf, "%s offers%s %ld gold piece%s for %s%s ",
shkname(shkp), short_funds ? " only" : "", offer,
Shknam(shkp), short_funds ? " only" : "", offer,
plur(offer),
(cltmp && !ltmp)
? ((yourc == 1L) ? "your item in " : "your items in ")
@@ -3650,8 +3651,7 @@ struct monst *shkp;
Hello(shkp), plname);
else
pline("%s holds out %s upturned %s.",
Shknam(shkp),
mhis(shkp),
Shknam(shkp), noit_mhis(shkp),
mbodypart(shkp, HAND));
followmsg = moves;
if (!rn2(9)) {
@@ -3805,7 +3805,7 @@ register int fall;
*/
if (lang == 2)
pline("%s curses %s inability to grab your backpack!",
shkname(shkp), mhim(shkp));
Shknam(shkp), noit_mhim(shkp));
rile_shk(shkp);
return;
#endif
@@ -3816,16 +3816,16 @@ register int fall;
if (distu(shkp->mx, shkp->my) > 2) {
if (lang == 2)
pline("%s curses you in anger and frustration!",
shkname(shkp));
Shknam(shkp));
else if (lang == 1)
growl(shkp);
rile_shk(shkp);
return;
} else
pline("%s %s, and %s your backpack!", shkname(shkp),
pline("%s %s, and %s your backpack!", Shknam(shkp),
makeplural(locomotion(shkp->data, "leap")), grabs);
} else
pline("%s %s your backpack!", shkname(shkp), grabs);
pline("%s %s your backpack!", Shknam(shkp), grabs);
for (obj = invent; obj; obj = obj2) {
obj2 = obj->nobj;
@@ -3957,7 +3957,7 @@ boolean cant_mollify;
if (uinshp) {
if (um_dist(shkp->mx, shkp->my, 1)
&& !um_dist(shkp->mx, shkp->my, 3)) {
pline("%s leaps towards you!", shkname(shkp));
pline("%s leaps towards you!", Shknam(shkp));
mnexto(shkp);
}
pursue = um_dist(shkp->mx, shkp->my, 1);
@@ -4004,16 +4004,16 @@ boolean cant_mollify;
else
pline("%s is %s that you decided to %s %s %s!",
Shknam(shkp), angrytexts[rn2(SIZE(angrytexts))],
dmgstr, mhis(shkp), dugwall ? "shop" : "door");
dmgstr, noit_mhis(shkp), dugwall ? "shop" : "door");
} else {
if (!Deaf) {
pline("%s shouts:", shkname(shkp));
pline("%s shouts:", Shknam(shkp));
verbalize("Who dared %s my %s?", dmgstr,
dugwall ? "shop" : "door");
} else {
pline("%s is %s that someone decided to %s %s %s!",
Shknam(shkp), angrytexts[rn2(SIZE(angrytexts))],
dmgstr, mhis(shkp), dugwall ? "shop" : "door");
dmgstr, noit_mhis(shkp), dugwall ? "shop" : "door");
}
}
hot_pursuit(shkp);
@@ -4039,10 +4039,8 @@ boolean cant_mollify;
verbalize("Oh, yes! You'll pay!");
else
pline("%s lunges %s %s toward your %s!",
Shknam(shkp),
mhis(shkp),
mbodypart(shkp, HAND),
body_part(NECK));
Shknam(shkp), noit_mhis(shkp),
mbodypart(shkp, HAND), body_part(NECK));
} else
growl(shkp);
hot_pursuit(shkp);
@@ -4221,9 +4219,9 @@ struct monst *shkp;
eshk = ESHK(shkp);
if (ANGRY(shkp)) {
pline("%s %s how much %s dislikes %s customers.",
shkname(shkp),
Shknam(shkp),
(!Deaf && !muteshk(shkp)) ? "mentions" : "indicates",
mhe(shkp), eshk->robbed ? "non-paying" : "rude");
noit_mhe(shkp), eshk->robbed ? "non-paying" : "rude");
} else if (eshk->following) {
if (strncmp(eshk->customer, plname, PL_NSIZ)) {
if (!Deaf && !muteshk(shkp))
@@ -4242,35 +4240,35 @@ struct monst *shkp;
register long total = addupbill(shkp) + eshk->debit;
pline("%s %s that your bill comes to %ld %s.",
shkname(shkp),
Shknam(shkp),
(!Deaf && !muteshk(shkp)) ? "says" : "indicates",
total, currency(total));
} else if (eshk->debit) {
pline("%s %s that you owe %s %ld %s.",
shkname(shkp),
Shknam(shkp),
(!Deaf && !muteshk(shkp)) ? "reminds you" : "indicates",
mhim(shkp), eshk->debit, currency(eshk->debit));
noit_mhim(shkp), eshk->debit, currency(eshk->debit));
} else if (eshk->credit) {
pline("%s encourages you to use your %ld %s of credit.",
shkname(shkp), eshk->credit, currency(eshk->credit));
Shknam(shkp), eshk->credit, currency(eshk->credit));
} else if (eshk->robbed) {
pline("%s %s about a recent robbery.",
Shknam(shkp),
(!Deaf && !muteshk(shkp)) ? "complains" : "indicates concern");
} else if ((shkmoney = money_cnt(shkp->minvent)) < 50L) {
pline("%s %s that business is bad.",
shkname(shkp),
Shknam(shkp),
(!Deaf && !muteshk(shkp)) ? "complains" : "indicates");
} else if (shkmoney > 4000) {
pline("%s %s that business is good.",
shkname(shkp),
Shknam(shkp),
(!Deaf && !muteshk(shkp)) ? "says" : "indicates");
} else if (is_izchak(shkp, FALSE)) {
if (!Deaf && !muteshk(shkp))
pline(Izchak_speaks[rn2(SIZE(Izchak_speaks))], shkname(shkp));
} else {
if (!Deaf && !muteshk(shkp))
pline("%s talks about the problem of shoplifters.", shkname(shkp));
pline("%s talks about the problem of shoplifters.", Shknam(shkp));
}
}
@@ -4472,7 +4470,7 @@ register xchar x, y;
&& ESHK(shkp)->shd.y == y
&& shkp->mcanmove && !shkp->msleeping
&& (ESHK(shkp)->debit || ESHK(shkp)->billct || ESHK(shkp)->robbed)) {
pline("%s%s blocks your way!", shkname(shkp),
pline("%s%s blocks your way!", Shknam(shkp),
Invis ? " senses your motion and" : "");
return TRUE;
}
@@ -4509,7 +4507,7 @@ register xchar x, y;
&& (x == sx - 1 || x == sx + 1 || y == sy - 1 || y == sy + 1)
&& (Invis || carrying(PICK_AXE) || carrying(DWARVISH_MATTOCK)
|| u.usteed)) {
pline("%s%s blocks your way!", shkname(shkp),
pline("%s%s blocks your way!", Shknam(shkp),
Invis ? " senses your motion and" : "");
return TRUE;
}
+15 -4
View File
@@ -621,6 +621,7 @@ schar filling;
schar lit;
{
int x, y;
for (x = 2; x <= x_maze_max; x++)
for (y = 0; y <= y_maze_max; y++) {
SET_TYPLIT(x, y, filling, lit);
@@ -636,11 +637,21 @@ xchar x1, y1, x2, y2;
int prop;
{
register xchar x, y;
struct rm *lev;
for (y = max(y1, 0); y <= min(y2, ROWNO - 1); y++)
for (x = max(x1, 0); x <= min(x2, COLNO - 1); x++)
if (IS_STWALL(levl[x][y].typ) || IS_TREE(levl[x][y].typ))
levl[x][y].wall_info |= prop;
x1 = max(x1, 1);
x2 = min(x2, COLNO - 1);
y1 = max(y1, 0);
y2 = min(y2, ROWNO - 1);
for (y = y1; y <= y2; y++)
for (x = x1; x <= x2; x++) {
lev = &levl[x][y];
if (IS_STWALL(lev->typ) || IS_TREE(lev->typ)
/* 3.6.2: made iron bars eligible to be flagged nondiggable
(checked by chewing(hack.c) and zap_over_floor(zap.c)) */
|| lev->typ == IRONBARS)
lev->wall_info |= prop;
}
}
STATIC_OVL void
+16 -7
View File
@@ -492,7 +492,14 @@ struct obj *scroll;
}
int
dotele()
dotelecmd()
{
return dotele((wizard) ? TRUE : FALSE);
}
int
dotele(break_the_rules)
boolean break_the_rules;
{
struct trap *trap;
boolean trap_once = FALSE;
@@ -529,7 +536,7 @@ dotele()
castit = TRUE;
break;
}
if (!wizard) {
if (!break_the_rules) {
if (!castit) {
if (!Teleportation)
You("don't know that spell.");
@@ -541,7 +548,7 @@ dotele()
}
if (u.uhunger <= 100 || ACURR(A_STR) < 6) {
if (!wizard) {
if (!break_the_rules) {
You("lack the strength %s.",
castit ? "for a teleport spell" : "to teleport");
return 1;
@@ -550,7 +557,7 @@ dotele()
energy = objects[SPE_TELEPORT_AWAY].oc_level * 7 / 2 - 2;
if (u.uen <= energy) {
if (wizard)
if (break_the_rules)
energy = u.uen;
else {
You("lack the energy %s.",
@@ -567,11 +574,13 @@ dotele()
exercise(A_WIS, TRUE);
if (spelleffects(sp_no, TRUE))
return 1;
else if (!wizard)
else if (!break_the_rules)
return 0;
} else {
u.uen -= energy;
context.botl = 1;
if (!break_the_rules) {
u.uen -= energy;
context.botl = 1;
}
}
}
+11 -1
View File
@@ -3693,7 +3693,7 @@ drown()
&& (Teleport_control || rn2(3) < Luck + 2)) {
You("attempt a teleport spell."); /* utcsri!carroll */
if (!level.flags.noteleport) {
(void) dotele();
(void) dotele(FALSE);
if (!is_pool(u.ux, u.uy))
return TRUE;
} else
@@ -3991,6 +3991,16 @@ boolean force_failure;
}
} else if (under_u) {
dotrap(ttmp, 0);
} else if (ttype == BEAR_TRAP && (Levitation || Flying)) {
/* There was a report of oddities of the trap
vanishing from view due to tseen being cleared
(which was deliberate to work around a check_here()
issue). Since you won't actually end up in the trap
during the #untrap operation anyway due to
Levitation and Flying checks further along,
just avoid the whole "vanishing trap" scenario
by failing the #untrap operation right here. */
You("couldn't reach it from your vantage point.");
} else {
move_into_trap(ttmp);
}
+30 -1
View File
@@ -658,6 +658,7 @@ int dieroll;
boolean ispoisoned = FALSE, needpoismsg = FALSE, poiskilled = FALSE,
unpoisonmsg = FALSE;
boolean silvermsg = FALSE, silverobj = FALSE;
boolean lightobj = FALSE;
boolean valid_weapon_attack = FALSE;
boolean unarmed = !uwep && !uarm && !uarms;
boolean hand_to_hand = (thrown == HMON_MELEE
@@ -699,7 +700,10 @@ int dieroll;
}
}
} else {
Strcpy(saved_oname, cxname(obj));
if (!(artifact_light(obj) && obj->lamplit))
Strcpy(saved_oname, cxname(obj));
else
Strcpy(saved_oname, bare_artifactname(obj));
if (obj->oclass == WEAPON_CLASS || is_weptool(obj)
|| obj->oclass == GEM_CLASS) {
/* is it not a melee weapon? */
@@ -803,6 +807,8 @@ int dieroll;
silvermsg = TRUE;
silverobj = TRUE;
}
if (artifact_light(obj) && obj->lamplit && mon_hates_light(mon))
lightobj = TRUE;
if (u.usteed && !thrown && tmp > 0
&& weapon_type(obj) == P_LANCE && mon != u.ustuck) {
jousting = joust(mon, obj);
@@ -1251,6 +1257,29 @@ int dieroll;
whom = strcat(s_suffix(whom), " flesh");
pline(fmt, whom);
}
if (lightobj) {
const char *fmt;
char *whom = mon_nam(mon);
char emitlightobjbuf[BUFSZ];
if (canspotmon(mon)) {
if (saved_oname[0]) {
Sprintf(emitlightobjbuf,
"%s radiance penetrates deep into",
s_suffix(saved_oname));
Strcat(emitlightobjbuf, " %s!");
fmt = emitlightobjbuf;
} else
fmt = "The light sears %s!";
} else {
*whom = highc(*whom); /* "it" -> "It" */
fmt = "%s is seared!";
}
/* note: s_suffix returns a modifiable buffer */
if (!noncorporeal(mdat) && !amorphous(mdat))
whom = strcat(s_suffix(whom), " flesh");
pline(fmt, whom);
}
/* if a "no longer poisoned" message is coming, it will be last;
obj->opoisoned was cleared above and any message referring to
"poisoned <obj>" has now been given; we want just "<obj>" for
+4 -3
View File
@@ -452,7 +452,8 @@ invault()
if (!Blind)
pline(
"%s holds out %s palm and beckons with %s other hand.",
noit_Monnam(guard), mhis(guard), mhis(guard));
noit_Monnam(guard), noit_mhis(guard),
noit_mhis(guard));
} else {
verbalize(
"Most likely all your gold was stolen from this vault.");
@@ -707,7 +708,7 @@ register struct monst *grd;
if (Deaf) {
if (!Blind)
pline("%s holds out %s palm demandingly!",
noit_Monnam(grd), mhis(grd));
noit_Monnam(grd), noit_mhis(grd));
} else {
verbalize("Drop all your gold, scoundrel!");
}
@@ -716,7 +717,7 @@ register struct monst *grd;
if (Deaf) {
if (!Blind)
pline("%s rubs %s hands with enraged delight!",
noit_Monnam(grd), mhis(grd));
noit_Monnam(grd), noit_mhis(grd));
} else {
verbalize("So be it, rogue!");
}
+2
View File
@@ -329,6 +329,8 @@ struct monst *mon;
bonus += rnd(4);
if (objects[otyp].oc_material == SILVER && mon_hates_silver(mon))
bonus += rnd(20);
if (artifact_light(otmp) && otmp->lamplit && hates_light(ptr))
bonus += rnd(8);
/* if the weapon is going to get a double damage bonus, adjust
this bonus so that effectively it's added after the doubling */
+11 -2
View File
@@ -930,7 +930,7 @@ unsigned long *colormasks UNUSED;
is buffered so final BL_FLUSH is needed to produce output) */
windowprocs.wincap2 |= WC2_FLUSH_STATUS;
if (idx != BL_FLUSH) {
if (idx >= 0) {
if (!status_activefields[idx])
return;
switch (idx) {
@@ -972,11 +972,20 @@ unsigned long *colormasks UNUSED;
break;
}
return; /* processed one field other than BL_FLUSH */
} /* (idx != BL_FLUSH) */
} /* (idx >= 0, thus not BL_FLUSH, BL_RESET, BL_CHARACTERISTICS) */
/* does BL_RESET require any specific code to ensure all fields ? */
if (!(idx == BL_FLUSH || idx == BL_RESET))
return;
/* We've received BL_FLUSH; time to output the gathered data */
nb = newbot1;
*nb = '\0';
/* BL_FLUSH is the only pseudo-index value we need to check for
in the loop below because it is the only entry used to pad the
end of the fieldorder array. We could stop on any
negative (illegal) index, but this should be fine */
for (i = 0; (idx1 = fieldorder[0][i]) != BL_FLUSH; ++i) {
if (status_activefields[idx1])
Strcpy(nb = eos(nb), status_vals[idx1]);
+4 -1
View File
@@ -100,7 +100,10 @@ struct window_procs X11_procs = {
"X11",
(WC_COLOR | WC_HILITE_PET | WC_ASCII_MAP | WC_TILED_MAP
| WC_PLAYER_SELECTION | WC_PERM_INVENT | WC_MOUSE_SUPPORT),
0L, /* WC2 flag mask */
#if defined(STATUS_HILITES)
WC2_FLUSH_STATUS | WC2_RESET_STATUS |
#endif
0L,
X11_init_nhwindows,
X11_player_selection, X11_askname, X11_get_nh_event, X11_exit_nhwindows,
X11_suspend_nhwindows, X11_resume_nhwindows, X11_create_nhwindow,
+11 -5
View File
@@ -67,6 +67,7 @@ struct window_procs tty_procs = {
#endif
#if defined(STATUS_HILITES)
| WC2_HILITE_STATUS | WC2_HITPOINTBAR | WC2_FLUSH_STATUS
| WC2_RESET_STATUS
#endif
| WC2_DARKGRAY),
tty_init_nhwindows, tty_player_selection, tty_askname, tty_get_nh_event,
@@ -3665,6 +3666,9 @@ unsigned long *colormasks;
char *fval = (char *) 0;
boolean reset_state = NO_RESET;
if ((fldidx < BL_RESET) || (fldidx >= MAXBLSTATS))
return;
if ((fldidx >= 0 && fldidx < MAXBLSTATS) && !status_activefields[fldidx])
return;
@@ -3726,11 +3730,13 @@ unsigned long *colormasks;
case BL_HUNGER:
/* The core sends trailing blanks for some fields.
Let's suppress the trailing blanks */
lastchar = eos(status_vals[fldidx]);
lastchar--;
while (*lastchar == ' ' && lastchar >= status_vals[fldidx]) {
*lastchar-- = '\0';
tty_status[NOW][fldidx].lth--;
if (tty_status[NOW][fldidx].lth > 0) {
lastchar = eos(status_vals[fldidx]);
lastchar--;
while (lastchar >= status_vals[fldidx] && *lastchar == ' ') {
*lastchar-- = '\0';
tty_status[NOW][fldidx].lth--;
}
}
break;
case BL_TITLE:
+1 -1
View File
@@ -88,7 +88,7 @@ struct window_procs mswin_procs = {
| WC_VARY_MSGCOUNT | WC_WINDOWCOLORS | WC_PLAYER_SELECTION
| WC_SPLASH_SCREEN | WC_POPUP_DIALOG | WC_MOUSE_SUPPORT,
#ifdef STATUS_HILITES
WC2_HITPOINTBAR | WC2_FLUSH_STATUS | WC2_HILITE_STATUS |
WC2_HITPOINTBAR | WC2_FLUSH_STATUS | WC2_RESET_STATUS | WC2_HILITE_STATUS |
#endif
0L, mswin_init_nhwindows, mswin_player_selection, mswin_askname,
mswin_get_nh_event, mswin_exit_nhwindows, mswin_suspend_nhwindows,