/* This is the one we want to use when printing messages. */ int pronoun_gender(struct monst *mtmp) { if (is_neuter(mtmp->data) || !canclassifymon(mtmp)) return 2; return (humanoid(mtmp->data) || (mtmp->data->geno & G_UNIQ) || type_is_pname(mtmp->data)) ? (int)mtmp->female : 2; }
/* an object launched by someone/thing other than player attacks a monster; return 1 if the object has stopped moving (hit or its range used up) */ int ohitmon(struct monst *mtmp, /* accidental target */ struct obj *otmp, /* missile; might be destroyed by drop_throw */ int range, /* how much farther will object travel if it misses */ /* Use -1 to signify to keep going even after hit, unless it's gone (used for rolling_boulder_traps) */ boolean verbose) { /* give message(s) even when you can't see what happened */ int damage, tmp; boolean vis, ismimic; int objgone = 1; ismimic = mtmp->m_ap_type && mtmp->m_ap_type != M_AP_MONSTER; vis = cansee(bhitpos.x, bhitpos.y); tmp = 5 + find_mac(mtmp) + omon_adj(mtmp, otmp, FALSE); if (tmp < rnd(20)) { if (!ismimic) { if (vis) miss(distant_name(otmp, mshot_xname), mtmp); else if (verbose) pline("It is missed."); } if (!range) { /* Last position; object drops */ if (is_pole(otmp)) return 1; drop_throw(otmp, 0, mtmp->mx, mtmp->my); return 1; } } else if (otmp->oclass == POTION_CLASS) { if (ismimic) seemimic(mtmp); mtmp->msleeping = 0; if (vis) otmp->dknown = 1; potionhit(mtmp, otmp, FALSE); return 1; } else { damage = dmgval(otmp, mtmp); if (otmp->otyp == ACID_VENOM && resists_acid(mtmp)) damage = 0; if (otmp->otyp == VAMPIRE_BLOOD && resists_drli(mtmp)) damage = 0; if (ismimic) seemimic(mtmp); mtmp->msleeping = 0; if (vis) hit(distant_name(otmp, mshot_xname), mtmp, exclam(damage)); else if (verbose) pline("%s is hit%s", Monnam(mtmp), exclam(damage)); if (otmp->opoisoned && is_poisonable(otmp)) { if (resists_poison(mtmp)) { if (vis) pline("The poison doesn't seem to affect %s.", mon_nam(mtmp)); } else { if (rn2(30)) { damage += rnd(6); } else { if (vis) pline("The poison was deadly..."); damage = mtmp->mhp; } } } if (objects[otmp->otyp].oc_material == SILVER && hates_silver(mtmp->data)) { if (vis) pline("The silver sears %s flesh!", s_suffix(mon_nam(mtmp))); else if (verbose) pline("Its flesh is seared!"); } if (otmp->otyp == ACID_VENOM && cansee(mtmp->mx, mtmp->my)) { if (resists_acid(mtmp)) { if (vis || verbose) pline("%s is unaffected.", Monnam(mtmp)); damage = 0; } else { if (vis) pline("The acid burns %s!", mon_nam(mtmp)); else if (verbose) pline("It is burned!"); } } mtmp->mhp -= damage; if (mtmp->mhp < 1) { if (vis || verbose) pline("%s is %s!", Monnam(mtmp), (nonliving(mtmp->data) || !canclassifymon(mtmp)) ? "destroyed" : "killed"); /* don't blame hero for unknown rolling boulder trap */ if (!flags.mon_moving && (otmp->otyp != BOULDER || range >= 0 || otmp->otrapped)) xkilled(mtmp, 0); else mondied(mtmp); } if (can_blnd (NULL, mtmp, (uchar) (otmp->otyp == BLINDING_VENOM ? AT_SPIT : AT_WEAP), otmp)) { if (vis && mtmp->mcansee) pline("%s is blinded by %s.", Monnam(mtmp), the(xname(otmp))); mtmp->mcansee = 0; tmp = (int)mtmp->mblinded + rnd(25) + 20; if (tmp > 127) tmp = 127; mtmp->mblinded = tmp; } if (otmp->otyp == VAMPIRE_BLOOD) { if (!resists_drli(mtmp)) { int xtmp = dice(2, 6); if (vis) pline("%s suddenly seems weaker!", Monnam(mtmp)); mtmp->mhpmax -= xtmp; if ((mtmp->mhp -= xtmp) <= 0 || !mtmp->m_lev) { if (vis) pline("%s dies!", Monnam(mtmp)); xkilled(mtmp, 0); } else mtmp->m_lev--; } obfree(otmp, NULL); return 1; } if (is_pole(otmp)) return 1; objgone = drop_throw(otmp, 1, bhitpos.x, bhitpos.y); if (!objgone && range == -1) { /* special case */ obj_extract_self(otmp); /* free it for motion again */ return 0; } return 1; } return 0; }