Merge branch 'ais523-elbereth' into NetHack-3.6.0

This commit is contained in:
Alex Smith
2016-10-21 23:30:09 +01:00
20 changed files with 75 additions and 54 deletions
+2
View File
@@ -353,6 +353,8 @@ sometimes generate the random mazes with wide corridors, thick walls,
put throne room gold in the chest put throne room gold in the chest
wielding Trollsbane prevents trolls from reviving wielding Trollsbane prevents trolls from reviving
wielding Demonbane prevents demons summoning friends wielding Demonbane prevents demons summoning friends
Elbereth must now be on a square by itself to function
Elbereth now erodes based on attacks by the player, not monsters scared
Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository
+2 -2
View File
@@ -1355,8 +1355,8 @@ E void FDECL(mnexto, (struct monst *));
E void FDECL(maybe_mnexto, (struct monst *)); E void FDECL(maybe_mnexto, (struct monst *));
E boolean FDECL(mnearto, (struct monst *, XCHAR_P, XCHAR_P, BOOLEAN_P)); E boolean FDECL(mnearto, (struct monst *, XCHAR_P, XCHAR_P, BOOLEAN_P));
E void FDECL(m_respond, (struct monst *)); E void FDECL(m_respond, (struct monst *));
E void FDECL(setmangry, (struct monst *)); E void FDECL(setmangry, (struct monst *, boolean));
E void FDECL(wakeup, (struct monst *)); E void FDECL(wakeup, (struct monst *, boolean));
E void NDECL(wake_nearby); E void NDECL(wake_nearby);
E void FDECL(wake_nearto, (int, int, int)); E void FDECL(wake_nearto, (int, int, int));
E void FDECL(seemimic, (struct monst *)); E void FDECL(seemimic, (struct monst *));
+2 -2
View File
@@ -2695,7 +2695,7 @@ struct obj *obj;
pline1(msg_slipsfree); pline1(msg_slipsfree);
} }
if (mtmp) if (mtmp)
wakeup(mtmp); wakeup(mtmp, TRUE);
} else } else
pline1(msg_snap); pline1(msg_snap);
@@ -2789,7 +2789,7 @@ struct obj *obj;
} else { } else {
pline1(msg_slipsfree); pline1(msg_slipsfree);
} }
wakeup(mtmp); wakeup(mtmp, TRUE);
} else { } else {
if (mtmp->m_ap_type && !Protection_from_shape_changers if (mtmp->m_ap_type && !Protection_from_shape_changers
&& !sensemon(mtmp)) && !sensemon(mtmp))
+1 -1
View File
@@ -2008,7 +2008,7 @@ struct monst *mtmp;
} }
mtmp->mburied = TRUE; mtmp->mburied = TRUE;
wakeup(mtmp); /* at least give it a chance :-) */ wakeup(mtmp, FALSE); /* at least give it a chance :-) */
newsym(mtmp->mx, mtmp->my); newsym(mtmp->mx, mtmp->my);
} }
+3 -3
View File
@@ -156,7 +156,7 @@ xchar x, y;
int i, j; int i, j;
/* anger target even if wild miss will occur */ /* anger target even if wild miss will occur */
setmangry(mon); setmangry(mon, TRUE);
if (Levitation && !rn2(3) && verysmall(mon->data) if (Levitation && !rn2(3) && verysmall(mon->data)
&& !is_flyer(mon->data)) { && !is_flyer(mon->data)) {
@@ -298,7 +298,7 @@ register struct obj *gold;
if (!likes_gold(mtmp->data) && !mtmp->isshk && !mtmp->ispriest if (!likes_gold(mtmp->data) && !mtmp->isshk && !mtmp->ispriest
&& !mtmp->isgd && !is_mercenary(mtmp->data)) { && !mtmp->isgd && !is_mercenary(mtmp->data)) {
wakeup(mtmp); wakeup(mtmp, TRUE);
} else if (!mtmp->mcanmove) { } else if (!mtmp->mcanmove) {
/* too light to do real damage */ /* too light to do real damage */
if (canseemon(mtmp)) { if (canseemon(mtmp)) {
@@ -312,7 +312,7 @@ register struct obj *gold;
mtmp->msleeping = 0; mtmp->msleeping = 0;
finish_meating(mtmp); finish_meating(mtmp);
if (!mtmp->isgd && !rn2(4)) /* not always pleasing */ if (!mtmp->isgd && !rn2(4)) /* not always pleasing */
setmangry(mtmp); setmangry(mtmp, TRUE);
/* greedy monsters catch gold */ /* greedy monsters catch gold */
if (cansee(mtmp->mx, mtmp->my)) if (cansee(mtmp->mx, mtmp->my))
pline("%s catches the gold.", Monnam(mtmp)); pline("%s catches the gold.", Monnam(mtmp));
+7 -5
View File
@@ -608,7 +608,8 @@ int x, y;
if ((mon = m_at(x, y)) != 0) { if ((mon = m_at(x, y)) != 0) {
You("bump into %s.", a_monnam(mon)); You("bump into %s.", a_monnam(mon));
wakeup(mon); wakeup(mon, FALSE);
setmangry(mon, FALSE);
wake_nearto(x,y, 10); wake_nearto(x,y, 10);
return FALSE; return FALSE;
} }
@@ -1346,7 +1347,7 @@ boolean maybe_wakeup;
else else
miss(missile, mon); miss(missile, mon);
if (maybe_wakeup && !rn2(3)) if (maybe_wakeup && !rn2(3))
wakeup(mon); wakeup(mon, TRUE);
return; return;
} }
@@ -1448,7 +1449,8 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */
at leader... (kicked artifact is ok too; HMON_APPLIED could at leader... (kicked artifact is ok too; HMON_APPLIED could
occur if quest artifact polearm or grapnel ever gets added) */ occur if quest artifact polearm or grapnel ever gets added) */
if (hmode != HMON_APPLIED && quest_arti_hits_leader(obj, mon)) { if (hmode != HMON_APPLIED && quest_arti_hits_leader(obj, mon)) {
/* not wakeup(), which angers non-tame monsters */ /* AIS: changes to wakeup() means that it's now less inappropriate here
than it used to be, but the manual version works just as well */
mon->msleeping = 0; mon->msleeping = 0;
mon->mstrategy &= ~STRAT_WAITMASK; mon->mstrategy &= ~STRAT_WAITMASK;
@@ -1562,7 +1564,7 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */
} else { } else {
tmiss(obj, mon, TRUE); tmiss(obj, mon, TRUE);
if (hmode == HMON_APPLIED) if (hmode == HMON_APPLIED)
wakeup(mon); wakeup(mon, TRUE);
} }
} else if (otyp == HEAVY_IRON_BALL) { } else if (otyp == HEAVY_IRON_BALL) {
@@ -1610,7 +1612,7 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */
} }
} else if (guaranteed_hit) { } else if (guaranteed_hit) {
/* this assumes that guaranteed_hit is due to swallowing */ /* this assumes that guaranteed_hit is due to swallowing */
wakeup(mon); wakeup(mon, TRUE);
if (obj->otyp == CORPSE && touch_petrifies(&mons[obj->corpsenm])) { if (obj->otyp == CORPSE && touch_petrifies(&mons[obj->corpsenm])) {
if (is_animal(u.ustuck->data)) { if (is_animal(u.ustuck->data)) {
minstapetrify(u.ustuck, TRUE); minstapetrify(u.ustuck, TRUE);
+3 -3
View File
@@ -257,8 +257,7 @@ xchar x, y;
* Ignore headstones, in case the player names herself "Elbereth". * Ignore headstones, in case the player names herself "Elbereth".
* *
* If strict checking is requested, the word is only considered to be * If strict checking is requested, the word is only considered to be
* present if it is intact and is the first word in the engraving. * present if it is intact and is the entire content of the engraving.
* ("Elbereth burrito" matches; "o Elbereth" does not.)
*/ */
int int
sengr_at(s, x, y, strict) sengr_at(s, x, y, strict)
@@ -269,9 +268,10 @@ boolean strict;
register struct engr *ep = engr_at(x, y); register struct engr *ep = engr_at(x, y);
if (ep && ep->engr_type != HEADSTONE && ep->engr_time <= moves) { if (ep && ep->engr_type != HEADSTONE && ep->engr_time <= moves) {
return strict ? (strncmpi(ep->engr_txt, s, strlen(s)) == 0) return strict ? (fuzzymatch(ep->engr_txt, s, "", TRUE))
: (strstri(ep->engr_txt, s) != 0); : (strstri(ep->engr_txt, s) != 0);
} }
return FALSE; return FALSE;
} }
+1 -1
View File
@@ -433,7 +433,7 @@ int expltype;
monkilled(mtmp, "", (int) adtyp); monkilled(mtmp, "", (int) adtyp);
} else if (!context.mon_moving) { } else if (!context.mon_moving) {
/* all affected monsters, even if mdef is set */ /* all affected monsters, even if mdef is set */
setmangry(mtmp); setmangry(mtmp, TRUE);
} }
} }
+29 -4
View File
@@ -2583,10 +2583,33 @@ struct monst *mtmp;
} }
} }
/* Called whenever the player attacks mtmp; also called in other situations
where mtmp gets annoyed at the player. Handles mtmp getting annoyed at the
attack and any ramifications that might have. Useful also in situations where
mtmp was already hostile; it checks for situations where the player shouldn't
be attacking and any ramifications /that/ might have. */
void void
setmangry(mtmp) setmangry(mtmp, via_attack)
struct monst *mtmp; struct monst *mtmp;
boolean via_attack;
{ {
if (via_attack && sengr_at("Elbereth", u.ux, u.uy, TRUE)) {
You_feel("like a hypocrite.");
/* AIS: Yes, I know alignment penalties and bonuses aren't balanced at
the moment. This is about correct relative to other "small"
penalties; it should be fairly large, as attacking while standing on
an Elbereth means that you're requesting peace and then violating
your own request. I know 5 isn't actually large, but it's
intentionally larger than the 1s and 2s that are normally given for
this sort of thing. */
adjalign(-5);
if (!Blind)
pline("The engraving beneath you fades.");
del_engr_at(u.ux, u.uy);
}
/* AIS: Should this be in both places, or just in wakeup()? */
mtmp->mstrategy &= ~STRAT_WAITMASK; mtmp->mstrategy &= ~STRAT_WAITMASK;
if (!mtmp->mpeaceful) if (!mtmp->mpeaceful)
return; return;
@@ -2681,14 +2704,16 @@ struct monst *mtmp;
} }
/* wake up a monster, usually making it angry in the process */ /* wake up a monster, possibly making it angry in the process */
void void
wakeup(mtmp) wakeup(mtmp, via_attack)
register struct monst *mtmp; register struct monst *mtmp;
boolean via_attack;
{ {
mtmp->msleeping = 0; mtmp->msleeping = 0;
finish_meating(mtmp); finish_meating(mtmp);
setmangry(mtmp); if (via_attack)
setmangry(mtmp, TRUE);
if (mtmp->m_ap_type) { if (mtmp->m_ap_type) {
seemimic(mtmp); seemimic(mtmp);
} else if (context.forcefight && !context.mon_moving } else if (context.forcefight && !context.mon_moving
-6
View File
@@ -320,12 +320,6 @@ int *inrange, *nearby, *scared;
|| (!mtmp->mpeaceful && in_your_sanctuary(mtmp, 0, 0)))) { || (!mtmp->mpeaceful && in_your_sanctuary(mtmp, 0, 0)))) {
*scared = 1; *scared = 1;
monflee(mtmp, rnd(rn2(7) ? 10 : 100), TRUE, TRUE); monflee(mtmp, rnd(rn2(7) ? 10 : 100), TRUE, TRUE);
/* magical protection won't last forever, so there'll be a
* chance of the magic being used up regardless of type */
if (sawscary) {
wipe_engr_at(seescaryx, seescaryy, 1, TRUE);
}
} else } else
*scared = 0; *scared = 0;
} }
+1 -1
View File
@@ -263,7 +263,7 @@ int force;
for (x = start_x; x <= end_x; x++) for (x = start_x; x <= end_x; x++)
for (y = start_y; y <= end_y; y++) { for (y = start_y; y <= end_y; y++) {
if ((mtmp = m_at(x, y)) != 0) { if ((mtmp = m_at(x, y)) != 0) {
wakeup(mtmp); /* peaceful monster will become hostile */ wakeup(mtmp, TRUE); /* peaceful monster will become hostile */
if (mtmp->mundetected && is_hider(mtmp->data)) { if (mtmp->mundetected && is_hider(mtmp->data)) {
mtmp->mundetected = 0; mtmp->mundetected = 0;
if (cansee(x, y)) if (cansee(x, y))
+1 -1
View File
@@ -1310,8 +1310,8 @@ dogaze()
mon_nam(mtmp)); mon_nam(mtmp));
if (yn(qbuf) != 'y') if (yn(qbuf) != 'y')
continue; continue;
setmangry(mtmp);
} }
setmangry(mtmp, TRUE);
if (!mtmp->mcanmove || mtmp->mstun || mtmp->msleeping if (!mtmp->mcanmove || mtmp->mstun || mtmp->msleeping
|| !mtmp->mcansee || !haseyes(mtmp->data)) { || !mtmp->mcansee || !haseyes(mtmp->data)) {
looked--; looked--;
+1 -1
View File
@@ -1488,7 +1488,7 @@ boolean your_fault;
/* target might have been killed */ /* target might have been killed */
if (mon->mhp > 0) { if (mon->mhp > 0) {
if (angermon) if (angermon)
wakeup(mon); wakeup(mon, TRUE);
else else
mon->msleeping = 0; mon->msleeping = 0;
} }
+2 -1
View File
@@ -795,7 +795,8 @@ angry_priest()
if ((priest = findpriest(temple_occupied(u.urooms))) != 0) { if ((priest = findpriest(temple_occupied(u.urooms))) != 0) {
struct epri *eprip = EPRI(priest); struct epri *eprip = EPRI(priest);
wakeup(priest); wakeup(priest, FALSE);
setmangry(priest, FALSE);
/* /*
* If the altar has been destroyed or converted, let the * If the altar has been destroyed or converted, let the
* priest run loose. * priest run loose.
+1 -1
View File
@@ -901,7 +901,7 @@ struct obj *sobj;
unsigned was_peaceful = mtmp->mpeaceful; unsigned was_peaceful = mtmp->mpeaceful;
if (sobj->cursed) { if (sobj->cursed) {
setmangry(mtmp); setmangry(mtmp, FALSE);
if (was_peaceful && !mtmp->mpeaceful) if (was_peaceful && !mtmp->mpeaceful)
return -1; return -1;
} else { } else {
+1 -1
View File
@@ -974,7 +974,7 @@ genericptr_t p2;
if (cansee(mtmp->mx, mtmp->my)) if (cansee(mtmp->mx, mtmp->my))
pline("%s coughs!", Monnam(mtmp)); pline("%s coughs!", Monnam(mtmp));
if (heros_fault(reg)) if (heros_fault(reg))
setmangry(mtmp); setmangry(mtmp, TRUE);
if (haseyes(mtmp->data) && mtmp->mcansee) { if (haseyes(mtmp->data) && mtmp->mcansee) {
mtmp->mblinded = 1; mtmp->mblinded = 1;
mtmp->mcansee = 0; mtmp->mcansee = 0;
+2 -2
View File
@@ -2119,7 +2119,7 @@ register struct monst *mtmp;
Recognizing who made the trap isn't completely Recognizing who made the trap isn't completely
unreasonable; everybody has their own style. */ unreasonable; everybody has their own style. */
if (trap->madeby_u && rnl(5)) if (trap->madeby_u && rnl(5))
setmangry(mtmp); setmangry(mtmp, TRUE);
in_sight = canseemon(mtmp); in_sight = canseemon(mtmp);
see_it = cansee(mtmp->mx, mtmp->my); see_it = cansee(mtmp->mx, mtmp->my);
@@ -4541,7 +4541,7 @@ boolean *noticed; /* set to true iff hero notices the effect; */
or if you sense the monster who becomes trapped */ or if you sense the monster who becomes trapped */
*noticed = cansee(t->tx, t->ty) || canspotmon(mon); *noticed = cansee(t->tx, t->ty) || canspotmon(mon);
/* monster will be angered; mintrap doesn't handle that */ /* monster will be angered; mintrap doesn't handle that */
wakeup(mon); wakeup(mon, TRUE);
++force_mintrap; ++force_mintrap;
result = (mintrap(mon) != 0); result = (mintrap(mon) != 0);
--force_mintrap; --force_mintrap;
+12 -12
View File
@@ -145,7 +145,7 @@ struct obj *wep; /* uwep for attack(), null for kick_monster() */
if (!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data, AD_STCK)) if (!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data, AD_STCK))
u.ustuck = mtmp; u.ustuck = mtmp;
} }
wakeup(mtmp); /* always necessary; also un-mimics mimics */ wakeup(mtmp, TRUE); /* always necessary; also un-mimics mimics */
return TRUE; return TRUE;
} }
@@ -190,7 +190,7 @@ struct obj *wep; /* uwep for attack(), null for kick_monster() */
*/ */
if ((mtmp->mundetected || mtmp->m_ap_type) && sensemon(mtmp)) { if ((mtmp->mundetected || mtmp->m_ap_type) && sensemon(mtmp)) {
mtmp->mundetected = 0; mtmp->mundetected = 0;
wakeup(mtmp); wakeup(mtmp, TRUE);
} }
if (flags.confirm && mtmp->mpeaceful && !Confusion && !Hallucination if (flags.confirm && mtmp->mpeaceful && !Confusion && !Hallucination
@@ -573,7 +573,7 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
unconventional[0] = '\0'; unconventional[0] = '\0';
saved_oname[0] = '\0'; saved_oname[0] = '\0';
wakeup(mon); wakeup(mon, TRUE);
if (!obj) { /* attack with bare hands */ if (!obj) { /* attack with bare hands */
if (mdat == &mons[PM_SHADE]) if (mdat == &mons[PM_SHADE])
tmp = 0; tmp = 0;
@@ -894,7 +894,7 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
pline("%s %s over %s!", what, pline("%s %s over %s!", what,
vtense(what, "splash"), whom); vtense(what, "splash"), whom);
} }
setmangry(mon); setmangry(mon, TRUE);
mon->mcansee = 0; mon->mcansee = 0;
tmp = rn1(25, 21); tmp = rn1(25, 21);
if (((int) mon->mblinded + tmp) > 127) if (((int) mon->mblinded + tmp) > 127)
@@ -903,7 +903,7 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
mon->mblinded += tmp; mon->mblinded += tmp;
} else { } else {
pline(obj->otyp == CREAM_PIE ? "Splat!" : "Splash!"); pline(obj->otyp == CREAM_PIE ? "Splat!" : "Splash!");
setmangry(mon); setmangry(mon, TRUE);
} }
if (thrown) if (thrown)
obfree(obj, (struct obj *) 0); obfree(obj, (struct obj *) 0);
@@ -2097,7 +2097,7 @@ boolean wouldhavehit;
else else
You("miss it."); You("miss it.");
if (!mdef->msleeping && mdef->mcanmove) if (!mdef->msleeping && mdef->mcanmove)
wakeup(mdef); wakeup(mdef, TRUE);
} }
/* attack monster as a monster. */ /* attack monster as a monster. */
@@ -2178,7 +2178,7 @@ register struct monst *mon;
sum[i] = damageum(mon, mattk); sum[i] = damageum(mon, mattk);
break; break;
} }
wakeup(mon); wakeup(mon, TRUE);
/* maybe this check should be in damageum()? */ /* maybe this check should be in damageum()? */
if (mon->data == &mons[PM_SHADE] if (mon->data == &mons[PM_SHADE]
&& !(mattk->aatyp == AT_KICK && uarmf && !(mattk->aatyp == AT_KICK && uarmf
@@ -2212,7 +2212,7 @@ register struct monst *mon;
* already grabbed in a previous attack * already grabbed in a previous attack
*/ */
dhit = 1; dhit = 1;
wakeup(mon); wakeup(mon, TRUE);
if (mon->data == &mons[PM_SHADE]) if (mon->data == &mons[PM_SHADE])
Your("hug passes harmlessly through %s.", mon_nam(mon)); Your("hug passes harmlessly through %s.", mon_nam(mon));
else if (!sticks(mon->data) && !u.uswallow) { else if (!sticks(mon->data) && !u.uswallow) {
@@ -2230,7 +2230,7 @@ register struct monst *mon;
case AT_EXPL: /* automatic hit if next to */ case AT_EXPL: /* automatic hit if next to */
dhit = -1; dhit = -1;
wakeup(mon); wakeup(mon, TRUE);
sum[i] = explum(mon, mattk); sum[i] = explum(mon, mattk);
break; break;
@@ -2238,7 +2238,7 @@ register struct monst *mon;
tmp = find_roll_to_hit(mon, mattk->aatyp, (struct obj *) 0, tmp = find_roll_to_hit(mon, mattk->aatyp, (struct obj *) 0,
&attknum, &armorpenalty); &attknum, &armorpenalty);
if ((dhit = (tmp > rnd(20 + i)))) { if ((dhit = (tmp > rnd(20 + i)))) {
wakeup(mon); wakeup(mon, TRUE);
if (mon->data == &mons[PM_SHADE]) if (mon->data == &mons[PM_SHADE])
Your("attempt to surround %s is harmless.", mon_nam(mon)); Your("attempt to surround %s is harmless.", mon_nam(mon));
else { else {
@@ -2637,7 +2637,7 @@ struct monst *mtmp;
if (what) if (what)
pline(fmt, what); pline(fmt, what);
wakeup(mtmp); /* clears mimicking */ wakeup(mtmp, FALSE); /* clears mimicking */
/* if hero is blind, wakeup() won't display the monster even though /* if hero is blind, wakeup() won't display the monster even though
it's no longer concealed */ it's no longer concealed */
if (!canspotmon(mtmp) if (!canspotmon(mtmp)
@@ -2695,7 +2695,7 @@ struct obj *otmp; /* source of flash */
} }
if (mtmp->mhp > 0) { if (mtmp->mhp > 0) {
if (!context.mon_moving) if (!context.mon_moving)
setmangry(mtmp); setmangry(mtmp, TRUE);
if (tmp < 9 && !mtmp->isshk && rn2(4)) if (tmp < 9 && !mtmp->isshk && rn2(4))
monflee(mtmp, rn2(4) ? rnd(100) : 0, FALSE, TRUE); monflee(mtmp, rn2(4) ? rnd(100) : 0, FALSE, TRUE);
mtmp->mcansee = 0; mtmp->mcansee = 0;
+1 -1
View File
@@ -400,7 +400,7 @@ invault()
} }
mongone(guard); mongone(guard);
} else { } else {
setmangry(guard); setmangry(guard, FALSE);
if (Deaf) { if (Deaf) {
if (!Blind) if (!Blind)
pline("%s mouths something and looks very angry!", pline("%s mouths something and looks very angry!",
+3 -6
View File
@@ -426,7 +426,7 @@ struct obj *otmp;
} }
if (wake) { if (wake) {
if (mtmp->mhp > 0) { if (mtmp->mhp > 0) {
wakeup(mtmp); wakeup(mtmp, TRUE);
m_respond(mtmp); m_respond(mtmp);
if (mtmp->isshk && !*u.ushops) if (mtmp->isshk && !*u.ushops)
hot_pursuit(mtmp); hot_pursuit(mtmp);
@@ -4535,12 +4535,9 @@ short exploding_wand_typ;
You("%s of smoke.", !Blind ? "see a puff" : "smell a whiff"); You("%s of smoke.", !Blind ? "see a puff" : "smell a whiff");
} }
if ((mon = m_at(x, y)) != 0) { if ((mon = m_at(x, y)) != 0) {
/* Cannot use wakeup() which also angers the monster */ wakeup(mon, FALSE);
mon->msleeping = 0;
if (mon->m_ap_type)
seemimic(mon);
if (type >= 0) { if (type >= 0) {
setmangry(mon); setmangry(mon, TRUE);
if (mon->ispriest && *in_rooms(mon->mx, mon->my, TEMPLE)) if (mon->ispriest && *in_rooms(mon->mx, mon->my, TEMPLE))
ghod_hitsu(mon); ghod_hitsu(mon);
if (mon->isshk && !*u.ushops) if (mon->isshk && !*u.ushops)