diff --git a/include/mondata.h b/include/mondata.h index 229617782..cdb299007 100644 --- a/include/mondata.h +++ b/include/mondata.h @@ -193,10 +193,18 @@ (vegan(ptr) \ || ((ptr)->mlet == S_PUDDING && (ptr) != &mons[PM_BLACK_PUDDING])) +/* monkeys are tameable via bananas but not pacifiable via food, + otherwise their theft attack could be nullified too easily; + dogs and cats can be tamed by anything they like to eat and are + pacified by any other food; + horses can be tamed by always-veggy food or lichen corpses but + not tamed or pacified by other corpses or tins of veggy critters */ #define befriend_with_obj(ptr, obj) \ - (((obj)->oclass == FOOD_CLASS && is_domestic(ptr)) \ - || ((obj)->otyp == BANANA && \ - ((ptr) == &mons[PM_MONKEY] \ - || (ptr) == &mons[PM_APE]))) + (((ptr) == &mons[PM_MONKEY] || (ptr) == &mons[PM_APE]) \ + ? (obj)->otyp == BANANA \ + : (is_domestic(ptr) && (obj)->oclass == FOOD_CLASS \ + && ((ptr)->mlet != S_UNICORN \ + || objects[(obj)->otyp].oc_material == VEGGY \ + || ((obj)->otyp == CORPSE && (obj)->corpsenm == PM_LICHEN)))) #endif /* MONDATA_H */ diff --git a/src/dog.c b/src/dog.c index f2993751d..0d55baad8 100644 --- a/src/dog.c +++ b/src/dog.c @@ -814,8 +814,8 @@ register struct obj *obj; case CARROT: return herbi ? DOGFOOD : starving ? ACCFOOD : MANFOOD; case BANANA: - return (mptr->mlet == S_YETI) - ? DOGFOOD + return (mptr->mlet == S_YETI && herbi) + ? DOGFOOD /* for monkey and ape (tameable), sasquatch */ : (herbi || starving) ? ACCFOOD : MANFOOD; diff --git a/src/monst.c b/src/monst.c index 7839b06cc..b99e44531 100644 --- a/src/monst.c +++ b/src/monst.c @@ -1915,16 +1915,18 @@ struct permonst _mons2[] = { /* * Apelike beasts */ + /* tameable via banana; does not grow up into ape... + not flagged as domestic, so no guilt penalty for eating non-pet one */ MON("monkey", S_YETI, LVL(2, 12, 6, 0, 0), (G_GENO | 1), A(ATTK(AT_CLAW, AD_SITM, 0, 0), ATTK(AT_BITE, AD_PHYS, 1, 3), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(100, 50, MS_GROWL, MZ_SMALL), 0, 0, - M1_ANIMAL | M1_HUMANOID | M1_CARNIVORE, 0, M3_INFRAVISIBLE, CLR_GRAY), + M1_ANIMAL | M1_HUMANOID | M1_OMNIVORE, 0, M3_INFRAVISIBLE, CLR_GRAY), MON("ape", S_YETI, LVL(4, 12, 6, 0, 0), (G_GENO | G_SGROUP | 2), A(ATTK(AT_CLAW, AD_PHYS, 1, 3), ATTK(AT_CLAW, AD_PHYS, 1, 3), ATTK(AT_BITE, AD_PHYS, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK), SIZ(1100, 500, MS_GROWL, MZ_LARGE), 0, 0, - M1_ANIMAL | M1_HUMANOID | M1_CARNIVORE, M2_STRONG, M3_INFRAVISIBLE, + M1_ANIMAL | M1_HUMANOID | M1_OMNIVORE, M2_STRONG, M3_INFRAVISIBLE, CLR_BROWN), MON("owlbear", S_YETI, LVL(5, 12, 5, 0, 0), (G_GENO | 3), A(ATTK(AT_CLAW, AD_PHYS, 1, 6), ATTK(AT_CLAW, AD_PHYS, 1, 6), diff --git a/src/mthrowu.c b/src/mthrowu.c index bff417325..a448ba8e6 100644 --- a/src/mthrowu.c +++ b/src/mthrowu.c @@ -414,6 +414,24 @@ boolean verbose; /* give message(s) even when you can't see what happened */ return 0; } +#define MT_FLIGHTCHECK(pre) \ + (/* missile hits edge of screen */ \ + !isok(bhitpos.x + dx, bhitpos.y + dy) \ + /* missile hits the wall */ \ + || IS_ROCK(levl[bhitpos.x + dx][bhitpos.y + dy].typ) \ + /* missile hit closed door */ \ + || closed_door(bhitpos.x + dx, bhitpos.y + dy) \ + /* missile might hit iron bars */ \ + /* the random chance for small objects hitting bars is */ \ + /* skipped when reaching them at point blank range */ \ + || (levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS \ + && hits_bars(&singleobj, \ + bhitpos.x, bhitpos.y, \ + bhitpos.x + dx, bhitpos.y + dy, \ + ((pre) ? 0 : !rn2(5)), 0)) \ + /* Thrown objects "sink" */ \ + || (!(pre) && IS_SINK(levl[bhitpos.x][bhitpos.y].typ))) + void m_throw(mon, x, y, dx, dy, range, obj) struct monst *mon; /* launching monster */ @@ -471,17 +489,7 @@ struct obj *obj; /* missile (or stack providing it) */ } } - /* pre-check for doors, walls and boundaries. - Also need to pre-check for bars regardless of direction; - the random chance for small objects hitting bars is - skipped when reaching them at point blank range */ - if (!isok(bhitpos.x + dx, bhitpos.y + dy) - || IS_ROCK(levl[bhitpos.x + dx][bhitpos.y + dy].typ) - || closed_door(bhitpos.x + dx, bhitpos.y + dy) - || (levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS - && hits_bars(&singleobj, - bhitpos.x, bhitpos.y, - bhitpos.x + dx, bhitpos.y + dy, 0, 0))) { + if (MT_FLIGHTCHECK(TRUE)) { (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y); return; } @@ -611,20 +619,7 @@ struct obj *obj; /* missile (or stack providing it) */ } } if (!range /* reached end of path */ - /* missile hits edge of screen */ - || !isok(bhitpos.x + dx, bhitpos.y + dy) - /* missile hits the wall */ - || IS_ROCK(levl[bhitpos.x + dx][bhitpos.y + dy].typ) - /* missile hit closed door */ - || closed_door(bhitpos.x + dx, bhitpos.y + dy) - /* missile might hit iron bars */ - || (levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS - && hits_bars(&singleobj, - bhitpos.x, bhitpos.y, - bhitpos.x + dx, bhitpos.y + dy, - !rn2(5), 0)) - /* Thrown objects "sink" */ - || IS_SINK(levl[bhitpos.x][bhitpos.y].typ)) { + || MT_FLIGHTCHECK(FALSE)) { if (singleobj) { /* hits_bars might have destroyed it */ if (m_shot.n > 1 && (cansee(bhitpos.x, bhitpos.y) || (archer && canseemon(archer)))) @@ -648,6 +643,8 @@ struct obj *obj; /* missile (or stack providing it) */ } } +#undef MT_FLIGHTCHECK + /* Monster throws item at another monster */ int thrwmm(mtmp, mtarg)