diff --git a/include/extern.h b/include/extern.h index 277837afb..dc3e1ffcc 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1651,6 +1651,8 @@ extern boolean olfaction(struct permonst *); unsigned long cvt_adtyp_to_mseenres(uchar); extern void monstseesu(unsigned long); extern boolean resist_conflict(struct monst *); +extern boolean mon_knows_traps(struct monst *, int); +extern void mon_learns_traps(struct monst *, int); /* ### monmove.c ### */ diff --git a/include/trap.h b/include/trap.h index e54aa9052..028f7a8b7 100644 --- a/include/trap.h +++ b/include/trap.h @@ -54,6 +54,7 @@ struct trap { /* unconditional traps */ enum trap_types { + ALL_TRAPS = -1, /* mon_knows_traps(), mon_learns_traps() */ NO_TRAP = 0, ARROW_TRAP = 1, DART_TRAP = 2, diff --git a/src/makemon.c b/src/makemon.c index 9b9e6cc04..55470c21b 100644 --- a/src/makemon.c +++ b/src/makemon.c @@ -1252,13 +1252,15 @@ makemon( else mtmp->female = femaleok ? rn2(2) : 0; - if (In_sokoban(&u.uz) && !mindless(ptr)) /* know about traps here */ - mtmp->mtrapseen = (1L << (PIT - 1)) | (1L << (HOLE - 1)); + if (In_sokoban(&u.uz) && !mindless(ptr)) { /* know about traps here */ + mon_learns_traps(mtmp, PIT); + mon_learns_traps(mtmp, HOLE); + } if (Is_stronghold(&u.uz) && !mindless(ptr)) /* know about the trap doors */ - mtmp->mtrapseen = (1L << (TRAPDOOR - 1)); + mon_learns_traps(mtmp, TRAPDOOR); /* quest leader and nemesis both know about all trap types */ if (ptr->msound == MS_LEADER || ptr->msound == MS_NEMESIS) - mtmp->mtrapseen = ~0; + mon_learns_traps(mtmp, ALL_TRAPS); place_monster(mtmp, x, y); mtmp->mcansee = mtmp->mcanmove = TRUE; diff --git a/src/mon.c b/src/mon.c index 94e292d7c..7f426134d 100644 --- a/src/mon.c +++ b/src/mon.c @@ -2075,7 +2075,7 @@ mfndpos( && !is_whirly(mdat) && !unsolid(mdat))) && (ttmp->ttyp != ANTI_MAGIC || !resists_magm(mon))) { if (!(flag & ALLOW_TRAPS)) { - if (mon->mtrapseen & (1L << (ttmp->ttyp - 1))) + if (mon_knows_traps(mon, ttmp->ttyp)) continue; } info[cnt] |= ALLOW_TRAPS; diff --git a/src/mondata.c b/src/mondata.c index e66bfed72..9f71f2eb5 100644 --- a/src/mondata.c +++ b/src/mondata.c @@ -1372,4 +1372,28 @@ resist_conflict(struct monst* mtmp) return (rnd(20) > resist_chance); } +/* does monster mtmp know traps of type ttyp */ +boolean +mon_knows_traps(struct monst *mtmp, int ttyp) +{ + if (ttyp == ALL_TRAPS) + return (boolean)(mtmp->mtrapseen); + else if (ttyp == NO_TRAP) + return !(boolean)(mtmp->mtrapseen); + else + return ((mtmp->mtrapseen & (1L << (ttyp - 1))) != 0); +} + +/* monster mtmp learns all traps of type ttyp */ +void +mon_learns_traps(struct monst *mtmp, int ttyp) +{ + if (ttyp == ALL_TRAPS) + mtmp->mtrapseen = ~0L; + else if (ttyp == NO_TRAP) + mtmp->mtrapseen = 0L; + else + mtmp->mtrapseen |= (1L << (ttyp - 1)); +} + /*mondata.c*/ diff --git a/src/monmove.c b/src/monmove.c index cd41829ec..65a769d2d 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -45,7 +45,7 @@ mb_trapped(struct monst *mtmp, boolean canseeit) return TRUE; /* will get here if lifesaved */ } - mtmp->mtrapseen |= (1 << (TRAPPED_DOOR - 1)); + mon_learns_traps(mtmp, TRAPPED_DOOR); return FALSE; } @@ -1945,7 +1945,7 @@ undesirable_disp( /* Monsters avoid a trap if they've seen that type before */ } else if (trap && rn2(40) - && (mtmp->mtrapseen & (1 << (trap->ttyp - 1))) != 0) { + && mon_knows_traps(mtmp, trap->ttyp)) { return TRUE; } diff --git a/src/muse.c b/src/muse.c index 9b0fa86fe..3edd10bbb 100644 --- a/src/muse.c +++ b/src/muse.c @@ -595,7 +595,7 @@ find_defensive(struct monst* mtmp, boolean tryescape) * about teleport traps. */ if (!noteleport_level(mtmp) - || !(mtmp->mtrapseen & (1 << (TELEP_TRAP - 1)))) { + || !mon_knows_traps(mtmp, TELEP_TRAP)) { g.m.defensive = obj; g.m.has_defense = (mon_has_amulet(mtmp)) ? MUSE_WAN_TELEPORTATION @@ -609,7 +609,7 @@ find_defensive(struct monst* mtmp, boolean tryescape) && !mtmp->isgd && !mtmp->ispriest))) { /* see WAN_TELEPORTATION case above */ if (!noteleport_level(mtmp) - || !(mtmp->mtrapseen & (1 << (TELEP_TRAP - 1)))) { + || !mon_knows_traps(mtmp, TELEP_TRAP)) { g.m.defensive = obj; g.m.has_defense = MUSE_SCR_TELEPORTATION; } @@ -722,7 +722,7 @@ use_defensive(struct monst* mtmp) makeknown(how); /* monster learns that teleportation isn't useful here */ if (noteleport_level(mtmp)) - mtmp->mtrapseen |= (1 << (TELEP_TRAP - 1)); + mon_learns_traps(mtmp, TELEP_TRAP); return 2; } if ((mon_has_amulet(mtmp) || On_W_tower_level(&u.uz)) && !rn2(3)) { @@ -741,7 +741,7 @@ use_defensive(struct monst* mtmp) mbhit(mtmp, rn1(8, 6), mbhitm, bhito, otmp); /* monster learns that teleportation isn't useful here */ if (noteleport_level(mtmp)) - mtmp->mtrapseen |= (1 << (TELEP_TRAP - 1)); + mon_learns_traps(mtmp, TELEP_TRAP); g.m_using = FALSE; return 2; case MUSE_SCR_TELEPORTATION: { @@ -1350,7 +1350,7 @@ find_offensive(struct monst* mtmp) && !Teleport_control /* same hack as MUSE_WAN_TELEPORTATION_SELF */ && (!noteleport_level(mtmp) - || !(mtmp->mtrapseen & (1 << (TELEP_TRAP - 1)))) + || !mon_knows_traps(mtmp, TELEP_TRAP)) /* do try to move hero to a more vulnerable spot */ && (onscary(u.ux, u.uy, mtmp) || (hero_behind_chokepoint(mtmp) && mon_has_friends(mtmp)) diff --git a/src/priest.c b/src/priest.c index baf69feb2..bd0a38d7d 100644 --- a/src/priest.c +++ b/src/priest.c @@ -245,7 +245,7 @@ priestini( EPRI(priest)->shrpos.x = sx; EPRI(priest)->shrpos.y = sy; assign_level(&(EPRI(priest)->shrlevel), lvl); - priest->mtrapseen = ~0; /* traps are known */ + mon_learns_traps(priest, ALL_TRAPS); /* traps are known */ priest->mpeaceful = 1; priest->ispriest = 1; priest->isminion = 0; @@ -691,7 +691,7 @@ mk_roamer(struct permonst *ptr, aligntyp alignment, coordxy x, coordxy y, EMIN(roamer)->renegade = (coaligned && !peaceful); roamer->ispriest = 0; roamer->isminion = 1; - roamer->mtrapseen = ~0; /* traps are known */ + mon_learns_traps(roamer, ALL_TRAPS); /* traps are known */ roamer->mpeaceful = peaceful; roamer->msleeping = 0; set_malign(roamer); /* peaceful may have changed */ diff --git a/src/shknam.c b/src/shknam.c index 0a157e74c..76c6f2f85 100644 --- a/src/shknam.c +++ b/src/shknam.c @@ -641,7 +641,7 @@ shkinit(const struct shclass* shp, struct mkroom* sroom) shk->isshk = shk->mpeaceful = 1; set_malign(shk); shk->msleeping = 0; - shk->mtrapseen = ~0; /* we know all the traps already */ + mon_learns_traps(shk, ALL_TRAPS); /* we know all the traps already */ eshkp->shoproom = (schar) ((sroom - g.rooms) + ROOMOFFSET); sroom->resident = shk; eshkp->shoptype = sroom->rtype; diff --git a/src/trap.c b/src/trap.c index ede15c763..ac611492b 100644 --- a/src/trap.c +++ b/src/trap.c @@ -2552,7 +2552,7 @@ dotrap(struct trap *trap, unsigned trflags) } if (u.usteed) - u.usteed->mtrapseen |= (1 << (ttype - 1)); + mon_learns_traps(u.usteed, ttype); /* * Note: @@ -3255,7 +3255,7 @@ mintrap(struct monst *mtmp, unsigned mintrapflags) boolean forcetrap = ((mintrapflags & FORCETRAP) != 0); boolean forcebungle = (mintrapflags & FORCEBUNGLE) != 0; /* monster has seen such a trap before */ - boolean already_seen = ((mtmp->mtrapseen & (1 << (tt - 1))) != 0 + boolean already_seen = (mon_knows_traps(mtmp, tt) || (tt == HOLE && !mindless(mptr))); if (mtmp == u.usteed) { @@ -3270,7 +3270,7 @@ mintrap(struct monst *mtmp, unsigned mintrapflags) return Trap_Effect_Finished; } - mtmp->mtrapseen |= (1 << (tt - 1)); + mon_learns_traps(mtmp, tt); /* Monster is aggravated by being trapped by you. Recognizing who made the trap isn't completely