From 2224df66f0d21f93255fdbc082419bbe51dda045 Mon Sep 17 00:00:00 2001 From: "Derek S. Ray" Date: Sun, 21 Jun 2015 15:16:22 -0400 Subject: [PATCH] Slight improvement to handless pets' pickup changes Allow one item to be taken out of a pile, and leave framework in place for partial splits so that all monsters will take up to their capacity, rather than leaving the whole pile if it's too big to take all at once. --- include/extern.h | 2 +- src/dogmove.c | 18 ++++++++++------ src/mon.c | 56 +++++++++++++++++++++++++++++++----------------- src/monmove.c | 2 +- src/steal.c | 2 +- 5 files changed, 50 insertions(+), 30 deletions(-) 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: