Select an offensive item/action for a monster. Returns TRUE iff one is * found. */
| 1418 | * found. |
| 1419 | */ |
| 1420 | boolean |
| 1421 | find_offensive(struct monst *mtmp) |
| 1422 | { |
| 1423 | struct obj *obj, *mtmp_helmet; |
| 1424 | boolean reflection_skip; |
| 1425 | |
| 1426 | gm.m.offensive = (struct obj *) 0; |
| 1427 | gm.m.has_offense = 0; |
| 1428 | if (mtmp->mpeaceful || is_animal(mtmp->data) || mindless(mtmp->data) |
| 1429 | || nohands(mtmp->data)) |
| 1430 | return FALSE; |
| 1431 | if (u.uswallow) |
| 1432 | return FALSE; |
| 1433 | if (in_your_sanctuary(mtmp, 0, 0)) |
| 1434 | return FALSE; |
| 1435 | if (dmgtype(mtmp->data, AD_HEAL) |
| 1436 | && !uwep && !uarmu && !uarm && !uarmh |
| 1437 | && !uarms && !uarmg && !uarmc && !uarmf) |
| 1438 | return FALSE; |
| 1439 | /* all offensive items require orthogonal or diagonal targeting */ |
| 1440 | if (!lined_up(mtmp)) |
| 1441 | return FALSE; |
| 1442 | |
| 1443 | #define nomore(x) if (gm.m.has_offense == x) continue; |
| 1444 | reflection_skip = (m_seenres(mtmp, M_SEEN_REFL) != 0 |
| 1445 | || monnear(mtmp, mtmp->mux, mtmp->muy)); |
| 1446 | mtmp_helmet = which_armor(mtmp, W_ARMH); |
| 1447 | /* this picks the last viable item rather than prioritizing choices */ |
| 1448 | for (obj = mtmp->minvent; obj; obj = obj->nobj) { |
| 1449 | if (!reflection_skip) { |
| 1450 | nomore(MUSE_WAN_DEATH); |
| 1451 | if (obj->otyp == WAN_DEATH && obj->spe > 0 |
| 1452 | && !m_seenres(mtmp, M_SEEN_MAGR)) { |
| 1453 | gm.m.offensive = obj; |
| 1454 | gm.m.has_offense = MUSE_WAN_DEATH; |
| 1455 | } |
| 1456 | nomore(MUSE_WAN_SLEEP); |
| 1457 | if (obj->otyp == WAN_SLEEP && obj->spe > 0 && gm.multi >= 0 |
| 1458 | && !m_seenres(mtmp, M_SEEN_SLEEP)) { |
| 1459 | gm.m.offensive = obj; |
| 1460 | gm.m.has_offense = MUSE_WAN_SLEEP; |
| 1461 | } |
| 1462 | nomore(MUSE_WAN_FIRE); |
| 1463 | if (obj->otyp == WAN_FIRE && obj->spe > 0 |
| 1464 | && !m_seenres(mtmp, M_SEEN_FIRE)) { |
| 1465 | gm.m.offensive = obj; |
| 1466 | gm.m.has_offense = MUSE_WAN_FIRE; |
| 1467 | } |
| 1468 | nomore(MUSE_FIRE_HORN); |
| 1469 | if (obj->otyp == FIRE_HORN && obj->spe > 0 && can_blow(mtmp) |
| 1470 | && !m_seenres(mtmp, M_SEEN_FIRE)) { |
| 1471 | gm.m.offensive = obj; |
| 1472 | gm.m.has_offense = MUSE_FIRE_HORN; |
| 1473 | } |
| 1474 | nomore(MUSE_WAN_COLD); |
| 1475 | if (obj->otyp == WAN_COLD && obj->spe > 0 |
| 1476 | && !m_seenres(mtmp, M_SEEN_COLD)) { |
| 1477 | gm.m.offensive = obj; |
no test coverage detected