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.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
56
src/mon.c
56
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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user