diff --git a/src/mkobj.c b/src/mkobj.c index 1cdf8426f..c6168568e 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 = g.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 " : "", diff --git a/src/steal.c b/src/steal.c index 8cf91bd6d..9ad0d3141 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 (!g.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 = g.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 == g.thrownobj)