diff --git a/include/extern.h b/include/extern.h index a412da87c..5827888e2 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1291,7 +1291,7 @@ E void FDECL(mpickgold, (struct monst *)); E boolean FDECL(mpickstuff, (struct monst *, const char *)); E int FDECL(curr_mon_load, (struct monst *)); E int FDECL(max_mon_load, (struct monst *)); -E boolean FDECL(can_carry, (struct monst *, struct obj *)); +E int FDECL(can_carry, (struct monst *, struct obj *)); E int FDECL(mfndpos, (struct monst *, coord *, long *, long)); E boolean FDECL(monnear, (struct monst *, int, int)); E void NDECL(dmonsfree); diff --git a/src/dogmove.c b/src/dogmove.c index e70b3ea77..082ef6ac7 100644 --- a/src/dogmove.c +++ b/src/dogmove.c @@ -398,8 +398,8 @@ register struct monst *mtmp; register struct edog *edog; int udist; { - register int omx, omy; - struct obj *obj; + register int omx, omy, carryamt = 0; + struct obj *obj, *otmp; if (mtmp->msleeping || !mtmp->mcanmove) return (0); @@ -433,16 +433,20 @@ int udist; && could_reach_item(mtmp, obj->ox, obj->oy)) return dog_eat(mtmp, obj, omx, omy, FALSE); - if (can_carry(mtmp, obj) && !obj->cursed + carryamt = can_carry(mtmp, obj); + if (carryamt > 0 && !obj->cursed && could_reach_item(mtmp, obj->ox, obj->oy)) { if (rn2(20) < edog->apport + 3) { if (rn2(udist) || !rn2(edog->apport)) { + otmp = obj; + if (carryamt != obj->quan) + otmp = splitobj(obj, carryamt); if (cansee(omx, omy) && flags.verbose) pline("%s picks up %s.", Monnam(mtmp), - distant_name(obj, doname)); - obj_extract_self(obj); + distant_name(otmp, doname)); + obj_extract_self(otmp); newsym(omx, omy); - (void) mpickobj(mtmp, obj); + (void) mpickobj(mtmp, otmp); if (attacktype(mtmp->data, AT_WEAP) && mtmp->weapon_check == NEED_WEAPON) { mtmp->weapon_check = NEED_HTH_WEAPON; @@ -531,7 +535,7 @@ int after, udist, whappr; && !dog_has_minvent && (!levl[omx][omy].lit || levl[u.ux][u.uy].lit) && (otyp == MANFOOD || m_cansee(mtmp, nx, ny)) - && edog->apport > rn2(8) && can_carry(mtmp, obj)) { + && edog->apport > rn2(8) && can_carry(mtmp, obj) > 0) { gx = nx; gy = ny; gtyp = APPORT; diff --git a/src/mon.c b/src/mon.c index 8daf72ddc..348a24876 100644 --- a/src/mon.c +++ b/src/mon.c @@ -922,7 +922,8 @@ mpickstuff(mtmp, str) register struct monst *mtmp; register const char *str; { - register struct obj *otmp, *otmp2; + register struct obj *otmp, *otmp2, *otmp3; + int carryamt = 0; /* prevent shopkeepers from leaving the door of their shop */ if (mtmp->isshk && inhishop(mtmp)) @@ -942,17 +943,23 @@ register const char *str; continue; if (!touch_artifact(otmp, mtmp)) continue; - if (!can_carry(mtmp, otmp)) + carryamt = can_carry(mtmp, otmp); + if (carryamt == 0) continue; if (is_pool(mtmp->mx, mtmp->my)) continue; + /* handle cases where the critter can only get some */ + otmp3 = otmp; + if (carryamt != otmp->quan) { + otmp3 = splitobj(otmp, carryamt); + } if (cansee(mtmp->mx, mtmp->my) && flags.verbose) pline("%s picks up %s.", Monnam(mtmp), (distu(mtmp->mx, mtmp->my) <= 5) - ? doname(otmp) - : distant_name(otmp, doname)); - obj_extract_self(otmp); /* remove from floor */ - (void) mpickobj(mtmp, otmp); /* may merge and free otmp */ + ? doname(otmp3) + : distant_name(otmp3, doname)); + obj_extract_self(otmp3); /* remove from floor */ + (void) mpickobj(mtmp, otmp3); /* may merge and free otmp3 */ m_dowear(mtmp, FALSE); newsym(mtmp->mx, mtmp->my); return TRUE; /* pick only one object */ @@ -1006,8 +1013,17 @@ register struct monst *mtmp; return (int) maxload; } -/* for restricting monsters' object-pickup */ -boolean +/* for restricting monsters' object-pickup. + * + * to support the new pet behavior, this now returns the max # of objects + * that a given monster could pick up from a pile. frequently this will be + * otmp->quan, but special cases for 'only one' now exist so. + * + * this will probably cause very amusing behavior with pets and gold coins. + * + * TODO: allow picking up 2-N objects from a pile of N based on weight + */ +int can_carry(mtmp, otmp) struct monst *mtmp; struct obj *otmp; @@ -1018,16 +1034,16 @@ struct obj *otmp; boolean glomper = FALSE; if (notake(mdat)) - return FALSE; /* can't carry anything */ + return 0; /* can't carry anything */ if (otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm]) && !(mtmp->misc_worn_check & W_ARMG) && !resists_ston(mtmp)) - return FALSE; + return 0; if (otyp == CORPSE && is_rider(&mons[otmp->corpsenm])) - return FALSE; + return 0; if (objects[otyp].oc_material == SILVER && mon_hates_silver(mtmp) && (otyp != BELL_OF_OPENING || !is_covetous(mdat))) - return FALSE; + return 0; /* monsters without hands can't pick up multiple objects at once * unless they have an engulfing attack @@ -1040,33 +1056,33 @@ struct obj *otmp; if ((mtmp->data->mflags1 & M1_NOHANDS) && !glomper && (!(mtmp->data->mlet == S_DRAGON && otmp->oclass == COIN_CLASS))) { - return FALSE; + return 1; } } /* Steeds don't pick up stuff (to avoid shop abuse) */ if (mtmp == u.usteed) - return (FALSE); + return 0; if (mtmp->isshk) - return (TRUE); /* no limit */ + return otmp->quan; /* no limit */ if (mtmp->mpeaceful && !mtmp->mtame) - return (FALSE); + return 0; /* otherwise players might find themselves obligated to violate * their alignment if the monster takes something they need */ /* special--boulder throwers carry unlimited amounts of boulders */ if (throws_rocks(mdat) && otyp == BOULDER) - return (TRUE); + return otmp->quan; /* nymphs deal in stolen merchandise, but not boulders or statues */ if (mdat->mlet == S_NYMPH) - return (boolean)(otmp->oclass != ROCK_CLASS); + return otmp->oclass == ROCK_CLASS ? 0 : otmp->quan; if (curr_mon_load(mtmp) + newload > max_mon_load(mtmp)) - return FALSE; + return 0; - return (TRUE); + return otmp->quan; } /* return number of acceptable neighbour positions */ diff --git a/src/monmove.c b/src/monmove.c index afe84d569..2caef728b 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -961,7 +961,7 @@ not_special: && !(otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm])))) && touch_artifact(otmp, mtmp)) { - if (can_carry(mtmp, otmp) + if (can_carry(mtmp, otmp) > 0 && (throws_rocks(ptr) || !sobj_at(BOULDER, xx, yy)) && (!is_unicorn(ptr) diff --git a/src/steal.c b/src/steal.c index cde21fc11..d609650c4 100644 --- a/src/steal.c +++ b/src/steal.c @@ -345,7 +345,7 @@ gotobj: (otmp == uright && welded(uwep)) || (otmp == uleft && welded(uwep) && bimanual(uwep))); - if (ostuck || !can_carry(mtmp, otmp)) { + if (ostuck || !can_carry(mtmp, otmp) > 0) { static const char *const how[] = { "steal", "snatch", "grab", "take" }; cant_take: