Mitre of Holiness and Tsurugi of Muramasa convey Protection when worn/wielded
effectiveness of magic cancellation by worn armor has been reduced
Protection improves the effectiveness of magic cancellation
+if an angry shopkeeper chased the hero to a different level and then got paid
+ off, he'd dismiss kops on that other level but not on his shop level
Platform- and/or Interface-Specific Fixes
E void FDECL(obfree, (struct obj *,struct obj *));
E void FDECL(home_shk, (struct monst *,BOOLEAN_P));
E void FDECL(make_happy_shk, (struct monst *,BOOLEAN_P));
+E void FDECL(make_happy_shoppers, (BOOLEAN_P));
E void FDECL(hot_pursuit, (struct monst *));
E void FDECL(make_angry_shk, (struct monst *,XCHAR_P,XCHAR_P));
E int NDECL(dopay);
/* NetHack 3.5 mextra.h $Date$ $Revision$ */
-/* SCCS Id: @(#)mextra.h 3.5 2009/01/30 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
schar unused; /* to force alignment for stupid compilers */
boolean following; /* following customer since he owes us sth */
boolean surcharge; /* angry shk inflates prices */
+ boolean dismiss_kops; /* pacified shk sends kops away */
coord shk; /* usual position shopkeeper */
coord shd; /* position shop door */
d_level shoplevel; /* level (& dungeon) of his shop */
/* NetHack 3.5 dog.c $Date$ $Revision$ */
-/* SCCS Id: @(#)dog.c 3.5 2008/10/20 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
losedogs()
{
register struct monst *mtmp, *mtmp0 = 0, *mtmp2;
+ int dismissKops = 0;
+ /*
+ * First, scan migrating_mons for shopkeepers who want to dismiss Kops,
+ * and scan mydogs for shopkeepers who want to retain kops.
+ * Second, dismiss kops if warranted, making more room for arrival.
+ * Third, place monsters accompanying the hero.
+ * Last, place migrating monsters coming to this level.
+ *
+ * Hero might eventually be displaced (due to the third step, but
+ * occuring later), which is the main reason to do the second step
+ * sooner (in turn necessitating the first step, rather than combining
+ * the list scans with monster placement).
+ */
+
+ /* check for returning shk(s) */
+ for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon) {
+ if (mtmp->mux != u.uz.dnum || mtmp->muy != u.uz.dlevel) continue;
+ if (mtmp->isshk) {
+ if (ESHK(mtmp)->dismiss_kops) {
+ if (dismissKops == 0) dismissKops = 1;
+ ESHK(mtmp)->dismiss_kops = FALSE; /* reset */
+ } else if (!mtmp->mpeaceful) {
+ /* an unpacified shk is returning; don't dismiss kops
+ even if another pacified one is willing to do so */
+ dismissKops = -1;
+ /* [keep looping; later monsters might need ESHK reset] */
+ }
+ }
+ }
+ /* make the same check for mydogs */
+ for (mtmp = mydogs; mtmp && dismissKops >= 0; mtmp = mtmp->nmon) {
+ if (mtmp->isshk) {
+ /* hostile shk might accompany hero [ESHK(mtmp)->dismiss_kops
+ can't be set here; it's only used for migrating_mons] */
+ if (!mtmp->mpeaceful) dismissKops = -1;
+ }
+ }
+
+ /* when a hostile shopkeeper chases hero to another level
+ and then gets paid off there, get rid of summoned kops
+ here now that he has returned to his shop level */
+ if (dismissKops > 0) make_happy_shoppers(TRUE);
+
+ /* place pets and/or any other monsters who accompany hero */
while ((mtmp = mydogs) != 0) {
mydogs = mtmp->nmon;
mon_arrive(mtmp, TRUE);
}
+ /* time for migrating monsters to arrive */
for(mtmp = migrating_mons; mtmp; mtmp = mtmp2) {
mtmp2 = mtmp->nmon;
if (mtmp->mux == u.uz.dnum && mtmp->muy == u.uz.dlevel) {
/* arrive near shop's door */
migrate_to_level(shkp, ledger_no(&eshkp->shoplevel),
MIGR_APPROX_XY, &eshkp->shd);
+ /* dismiss kops on that level when shk arrives */
+ eshkp->dismiss_kops = TRUE;
}
if (vanished)
pline("Satisfied, %s suddenly disappears!", shk_nam);
} else if(wasmad)
pline("%s calms down.", Monnam(shkp));
- if(!angry_shk_exists()) {
+ make_happy_shoppers(silentkops);
+}
+
+/* called by make_happy_shk() and also by losedogs() for migrating shk */
+void
+make_happy_shoppers(silentkops)
+boolean silentkops;
+{
+ if (!angry_shk_exists()) {
#ifdef KOPS
kops_gone(silentkops);
#endif
/* NetHack 3.5 shknam.c $Date$ $Revision$ */
-/* SCCS Id: @(#)shknam.c 3.5 2007/09/14 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
neweshk(mtmp)
struct monst *mtmp;
{
- if (!mtmp->mextra) mtmp->mextra = newmextra();
- if (!ESHK(mtmp)) {
+ if (!mtmp->mextra)
+ mtmp->mextra = newmextra();
+ if (!ESHK(mtmp))
ESHK(mtmp) = (struct eshk *)alloc(sizeof(struct eshk));
- (void) memset((genericptr_t) ESHK(mtmp), 0, sizeof(struct eshk));
- }
+ (void) memset((genericptr_t)ESHK(mtmp), 0, sizeof (struct eshk));
+ ESHK(mtmp)->bill_p = (struct bill_x *)0;
}
void
{
register int sh, sx, sy;
struct monst *shk;
+ struct eshk *eshkp;
/* place the shopkeeper in the given room */
sh = sroom->fdoor;
/* now initialize the shopkeeper monster structure */
if(!(shk = makemon(&mons[PM_SHOPKEEPER], sx, sy, MM_ESHK)))
return(-1);
+ eshkp = ESHK(shk); /* makemon(...,MM_ESHK) allocates this */
shk->isshk = shk->mpeaceful = 1;
set_malign(shk);
shk->msleeping = 0;
shk->mtrapseen = ~0; /* we know all the traps already */
- ESHK(shk)->shoproom = (schar)((sroom - rooms) + ROOMOFFSET);
+ eshkp->shoproom = (schar)((sroom - rooms) + ROOMOFFSET);
sroom->resident = shk;
- ESHK(shk)->shoptype = sroom->rtype;
- assign_level(&(ESHK(shk)->shoplevel), &u.uz);
- ESHK(shk)->shd = doors[sh];
- ESHK(shk)->shk.x = sx;
- ESHK(shk)->shk.y = sy;
- ESHK(shk)->robbed = 0L;
- ESHK(shk)->credit = 0L;
- ESHK(shk)->debit = 0L;
- ESHK(shk)->loan = 0L;
- ESHK(shk)->visitct = 0;
- ESHK(shk)->following = 0;
- ESHK(shk)->billct = 0;
+ eshkp->shoptype = sroom->rtype;
+ assign_level(&eshkp->shoplevel, &u.uz);
+ eshkp->shd = doors[sh];
+ eshkp->shk.x = sx;
+ eshkp->shk.y = sy;
+ eshkp->robbed = eshkp->credit = eshkp->debit = eshkp->loan = 0L;
+ eshkp->following = eshkp->surcharge = eshkp->dismiss_kops = FALSE;
+ eshkp->billct = eshkp->visitct = 0;
+ eshkp->bill_p = (struct bill_x *)0;
+ eshkp->customer[0] = '\0';
#ifndef GOLDOBJ
shk->mgold = 1000L + 30L*(long)rnd(100); /* initial capital */
#else