From: PatR Date: Sat, 16 Jul 2022 12:08:26 +0000 (-0700) Subject: github issue #819 - magic harp vs shopkeeper X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=231bd75b7f5ddc3ef0f745a75ea3566cc4055d99;p=nethack github issue #819 - magic harp vs shopkeeper Issue reported by youkan700: for shopkeepers, taming via magic harp behaved differently than taming via scroll or spell. Make magic harp's taming be the same as [non-cursed] scroll of taming and spell of charm monster: angry shopkeepers will be pacified (even though they can't be tamed). Also, add something I've been sitting on for ages: when taming magic hits an already tame monster, give that monster a chance to become tamer. Not significant for monsters that eat (unless being starved for some reason) but matters for ones who don't eat. For tameness N (which has a maximum of 20), if N is less than 10, have any taming yield a 10-N out of 10 chance to increase the tameness by 1. So the closer a pet is to becoming feral, the more likely for it to improve tameness a little. Closes #819 --- diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index 0e420632e..e4fcb8828 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -965,6 +965,8 @@ out of array bounds access attempt occurred when deciding whether to bounce if wand or spell zap reached edge of map if blind hero was challanged by a vault guard, it wasn't possible to see how to start following that guard out of the vault +make taming via magic harp be consistent with scroll of taming and charm + spell: an angry shopkeeper becomes pacified (but never tamed) Fixes to 3.7.0-x Problems that Were Exposed Via git Repository @@ -1731,6 +1733,7 @@ if built with DEBUG enabled and running in wizard mode, starting play with water on Plane of Water, and fumaroles on Plane of Fire be transparent add wizard mode #wizkill command to remove monster(s) from play some quest nemeses release a cloud of poisonous gas when they die +taming magic acting on an already tame creature might make it become tamer Platform- and/or Interface-Specific New Features diff --git a/src/dog.c b/src/dog.c index be1bb2d74..64b06b8c0 100644 --- a/src/dog.c +++ b/src/dog.c @@ -1012,8 +1012,23 @@ tamedog(struct monst *mtmp, struct obj *obj) return FALSE; } - if (mtmp->mtame || !mtmp->mcanmove - /* monsters with conflicting structures cannot be tamed */ + /* if already tame, taming magic might make it become tamer */ + if (mtmp->mtame) { + /* maximum tameness is 20, only reachable via eating */ + if (rnd(10) > mtmp->mtame) + mtmp->mtame++; + return FALSE; /* didn't just get tamed */ + } + /* pacify angry shopkeeper but don't tame him/her/it/them */ + if (mtmp->isshk) { + make_happy_shk(mtmp, FALSE); + return FALSE; + } + + if (!mtmp->mcanmove + /* monsters with conflicting structures cannot be tamed + [note: the various mextra structures don't actually conflict + with each other anymore] */ || mtmp->isshk || mtmp->isgd || mtmp->ispriest || mtmp->isminion || is_covetous(mtmp->data) || is_human(mtmp->data) || (is_demon(mtmp->data) && !is_demon(g.youmonst.data)) diff --git a/src/music.c b/src/music.c index 4dd444d32..e59470318 100644 --- a/src/music.c +++ b/src/music.c @@ -189,27 +189,24 @@ awaken_soldiers(struct monst* bugler /* monster that played instrument */) } } -/* Charm monsters in range. Note that they may resist the spell. - * If swallowed, range is reduced to 0. - */ +/* Charm monsters in range. Note that they may resist the spell. */ static void charm_monsters(int distance) { struct monst *mtmp, *mtmp2; - if (u.uswallow) { - if (!resist(u.ustuck, TOOL_CLASS, 0, NOTELL)) - (void) tamedog(u.ustuck, (struct obj *) 0); - } else { - for (mtmp = fmon; mtmp; mtmp = mtmp2) { - mtmp2 = mtmp->nmon; - if (DEADMONSTER(mtmp)) - continue; + if (u.uswallow) + distance = 0; /* only u.ustuck will be affected (u.usteed is Null + * since hero gets forcibly dismounted when engulfed) */ - if (distu(mtmp->mx, mtmp->my) <= distance) { - if (!resist(mtmp, TOOL_CLASS, 0, NOTELL)) - (void) tamedog(mtmp, (struct obj *) 0); - } + for (mtmp = fmon; mtmp; mtmp = mtmp2) { + mtmp2 = mtmp->nmon; + if (DEADMONSTER(mtmp)) + continue; + + if (distu(mtmp->mx, mtmp->my) <= distance) { + if (!resist(mtmp, TOOL_CLASS, 0, NOTELL)) + (void) tamedog(mtmp, (struct obj *) 0); } } } diff --git a/src/read.c b/src/read.c index f0bb880cc..3299ce2bd 100644 --- a/src/read.c +++ b/src/read.c @@ -1008,7 +1008,7 @@ forget(int howmuch) /* monster is hit by scroll of taming's effect */ static int -maybe_tame(struct monst* mtmp, struct obj* sobj) +maybe_tame(struct monst *mtmp, struct obj *sobj) { int was_tame = mtmp->mtame; unsigned was_peaceful = mtmp->mpeaceful; @@ -1018,9 +1018,9 @@ maybe_tame(struct monst* mtmp, struct obj* sobj) if (was_peaceful && !mtmp->mpeaceful) return -1; } else { - if (mtmp->isshk) - make_happy_shk(mtmp, FALSE); - else if (!resist(mtmp, sobj->oclass, 0, NOTELL)) + /* for a shopkeeper, tamedog() will call make_happy_shk() but + not tame the target, so call it even if taming gets resisted */ + if (!resist(mtmp, sobj->oclass, 0, NOTELL) || mtmp->isshk) (void) tamedog(mtmp, (struct obj *) 0); if ((!was_peaceful && mtmp->mpeaceful) || (!was_tame && mtmp->mtame)) return 1;