From 54e2e71319f141a1c973236e9eba425802d72915 Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 26 Jun 2019 15:33:40 -0700 Subject: [PATCH 1/2] mpickobj sanity, ball&chain theft feedback Something I've had sitting around for quite a while. Add a sanity check to mpickobj(). (It will need tweaking if b&c are changed to be in engulfer's inventory.) Also, include more information in the feedback when a nymph steals attached iron ball: "Nymph removed your chain and stole a heavy iron ball". And don't set the avenge-ok flag if uball is the item stolen since thief was doing hero a favor, or for anything when the thief is under the influence of Conflict. --- src/steal.c | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/src/steal.c b/src/steal.c index c9f6db37e..59421e372 100644 --- a/src/steal.c +++ b/src/steal.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 steal.c $NHDT-Date: 1554580626 2019/04/06 19:57:06 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.72 $ */ +/* NetHack 3.6 steal.c $NHDT-Date: 1561588404 2019/06/26 22:33:24 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.73 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -173,7 +173,7 @@ stealarm(VOID_ARGS) break; } } -botm: + botm: stealoid = 0; return 0; } @@ -249,7 +249,7 @@ char *objnambuf; struct obj *otmp; int tmp, could_petrify, armordelay, olddelay, named = 0, retrycnt = 0; boolean monkey_business, /* true iff an animal is doing the thievery */ - was_doffing; + was_doffing, was_punished = Punished; if (objnambuf) *objnambuf = '\0'; @@ -264,7 +264,7 @@ char *objnambuf; (void) maybe_finished_meal(FALSE); if (!invent || (inv_cnt(FALSE) == 1 && uskin)) { - nothing_to_steal: + nothing_to_steal: /* Not even a thousand men in armor can strip a naked man. */ if (Blind) pline("Somebody tries to rob you, but finds nothing to steal."); @@ -285,7 +285,7 @@ char *objnambuf; goto gotobj; } -retry: + retry: tmp = 0; for (otmp = invent; otmp; otmp = otmp->nobj) if ((!uarm || otmp != uarmc) && otmp != uskin @@ -320,7 +320,7 @@ retry: else if (otmp == uarmu && uarm) otmp = uarm; -gotobj: + gotobj: if (otmp->o_id == stealoid) return 0; @@ -332,6 +332,7 @@ gotobj: /* animals can't overcome curse stickiness nor unlock chains */ if (monkey_business) { boolean ostuck; + /* is the player prevented from voluntarily giving up this item? (ignores loadstones; the !can_carry() check will catch those) */ if (otmp == uball) @@ -348,7 +349,7 @@ gotobj: if (ostuck || can_carry(mtmp, otmp) == 0) { static const char *const how[] = { "steal", "snatch", "grab", "take" }; - cant_take: + cant_take: pline("%s tries to %s %s%s but gives up.", Monnam(mtmp), how[rn2(SIZE(how))], (otmp->owornmask & W_ARMOR) ? "your " : "", @@ -443,23 +444,26 @@ gotobj: impossible("Tried to steal a strange worn thing. [%d]", otmp->oclass); } - } else if (otmp->owornmask) + } else if (otmp->owornmask) /* weapon or ball&chain */ remove_worn_item(otmp, TRUE); /* do this before removing it from inventory */ if (objnambuf) Strcpy(objnambuf, yname(otmp)); - /* set mavenge bit so knights won't suffer an - * alignment penalty during retaliation; - */ - mtmp->mavenge = 1; + /* usually set mavenge bit so knights won't suffer an alignment penalty + during retaliation; not applicable for removing attached iron ball */ + if (!Conflict && !(was_punished && !Punished)) + mtmp->mavenge = 1; if (otmp->unpaid) subfrombill(otmp, shop_keeper(*u.ushops)); freeinv(otmp); - pline("%s stole %s.", named ? "She" : Monnam(mtmp), doname(otmp)); - could_petrify = - (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm])); + /* if attached ball was taken, uball and uchain are now Null */ + pline("%s%s stole %s.", named ? "She" : Monnam(mtmp), + (was_punished && !Punished) ? " removed your chain and" : "", + doname(otmp)); + could_petrify = (otmp->otyp == CORPSE + && touch_petrifies(&mons[otmp->corpsenm])); (void) mpickobj(mtmp, otmp); /* may free otmp */ if (could_petrify && !(mtmp->misc_worn_check & W_ARMG)) { minstapetrify(mtmp, TRUE); @@ -477,6 +481,16 @@ register struct obj *otmp; int freed_otmp; boolean snuff_otmp = FALSE; + if (!otmp) { + impossible("monster (%s) taking or picking up nothing?", + mtmp->data->mname); + return 1; + } else if (otmp == uball || otmp == uchain) { + impossible("monster (%s) taking or picking up attached %s (%s)?", + mtmp->data->mname, + (otmp == uchain) ? "chain" : "ball", simpleonames(otmp)); + return 0; + } /* if monster is acquiring a thrown or kicked object, the throwing or kicking code shouldn't continue to track and place it */ if (otmp == thrownobj) From fa4f9bb8ae074836bdf1742bf0e37279a16306d0 Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 26 Jun 2019 15:37:17 -0700 Subject: [PATCH 2/2] coalescing partly eaten globs Another one which has been around for a while. When merging two globs, the result is partly eaten if either (or both) of them was partly eaten, not just when the one that's going to stick around as the combined glob already was. --- src/mkobj.c | 51 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/src/mkobj.c b/src/mkobj.c index 5f98fe34e..4a5e7f0dc 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mkobj.c $NHDT-Date: 1559670606 2019/06/04 17:50:06 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.150 $ */ +/* NetHack 3.6 mkobj.c $NHDT-Date: 1561588627 2019/06/26 22:37:07 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.151 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -873,6 +873,7 @@ boolean artif; break; } if (Is_pudding(otmp)) { + otmp->quan = 1L; /* for emphasis; glob quantity is always 1 */ otmp->globby = 1; otmp->known = otmp->dknown = 1; otmp->corpsenm = PM_GRAY_OOZE @@ -2826,11 +2827,10 @@ struct obj **obj1, **obj2; / (o1wt + o2wt)); otmp1->age = moves - agetmp; /* conv. relative back to absolute */ otmp1->owt += o2wt; - if (otmp1->oeaten) - otmp1->oeaten += o2wt; + if (otmp1->oeaten || otmp2->oeaten) + otmp1->oeaten = o1wt + o2wt; otmp1->quan = 1L; obj_extract_self(otmp2); - newsym(otmp2->ox, otmp2->oy); /* in case of floor */ dealloc_obj(otmp2); *obj2 = (struct obj *) 0; return otmp1; @@ -2853,23 +2853,44 @@ struct obj * obj_meld(obj1, obj2) struct obj **obj1, **obj2; { - struct obj *otmp1, *otmp2; + struct obj *otmp1, *otmp2, *result = 0; + int ox, oy; if (obj1 && obj2) { otmp1 = *obj1; otmp2 = *obj2; if (otmp1 && otmp2 && otmp1 != otmp2) { - if (!(otmp2->where == OBJ_FLOOR && otmp1->where == OBJ_FREE) && - (otmp1->owt > otmp2->owt - || (otmp1->owt == otmp2->owt && rn2(2)))) { - return obj_absorb(obj1, obj2); + ox = oy = 0; + /* + * FIXME? + * If one of the objects is free because it's being dropped, + * we should really finish a full drop and then absorb/meld + * if it survives the flooreffects(). Then lighter-melds-into- + * heavier will be true even when heavier is the one dropped. + * + * [Also, what about when one of the globs is on the shore + * and we drop the other into adjacent pool or vice versa?] + */ + if (!(otmp2->where == OBJ_FLOOR && otmp1->where == OBJ_FREE) + && (otmp1->owt > otmp2->owt + || (otmp1->owt == otmp2->owt && rn2(2)))) { + if (otmp2->where == OBJ_FLOOR) + ox = otmp2->ox, oy = otmp2->oy; + result = obj_absorb(obj1, obj2); + } else { + if (otmp1->where == OBJ_FLOOR) + ox = otmp1->ox, oy = otmp1->oy; + result = obj_absorb(obj2, obj1); } - return obj_absorb(obj2, obj1); + /* callers really ought to take care of this; glob melding is + a bookkeeping issue rather than a display one */ + if (ox && cansee(ox, oy)) + newsym(ox, oy); } + } else { + impossible("obj_meld: not called with two actual objects"); } - - impossible("obj_meld: not called with two actual objects"); - return (struct obj *) 0; + return result; } /* give a message if hero notices two globs merging [used to be in pline.c] */ @@ -2895,8 +2916,8 @@ struct obj *otmp2; * they'll be out of our view (minvent or container) * so don't actually show anything */ } else if (onfloor || inpack) { - boolean adj = ((otmp->ox != u.ux || otmp->oy != u.uy) && - (otmp2->ox != u.ux || otmp2->oy != u.uy)); + boolean adj = ((otmp->ox != u.ux || otmp->oy != u.uy) + && (otmp2->ox != u.ux || otmp2->oy != u.uy)); pline("The %s%s coalesce%s.", (onfloor && adj) ? "adjacent " : "",