1 /* SCCS Id: @(#)mondata.h 3.4 2003/01/08 */ 2 /* Copyright (c) 1989 Mike Threepoint */ 3 /* NetHack may be freely redistributed. See license for details. */ 4 5 #ifndef MONDATA_H 6 #define MONDATA_H 7 8 #define verysmall(ptr) ((ptr)->msize < MZ_SMALL) 9 #define bigmonst(ptr) ((ptr)->msize >= MZ_LARGE) 10 #define hugemonst(ptr) ((ptr)->msize >= MZ_HUGE) 11 12 #define pm_resistance(ptr,typ) (((ptr)->mresists & (typ)) != 0) 13 14 #define resists_fire(mon) (((mon)->mintrinsics & MR_FIRE) != 0) 15 #define resists_cold(mon) (((mon)->mintrinsics & MR_COLD) != 0) 16 #define resists_sleep(mon) (((mon)->mintrinsics & MR_SLEEP) != 0) 17 #define resists_disint(mon) (((mon)->mintrinsics & MR_DISINT) != 0) 18 #define resists_elec(mon) (((mon)->mintrinsics & MR_ELEC) != 0) 19 #define resists_poison(mon) (((mon)->mintrinsics & MR_POISON) != 0) 20 #define resists_acid(mon) (((mon)->mintrinsics & MR_ACID) != 0) 21 #define resists_ston(mon) (((mon)->mintrinsics & MR_STONE) != 0) 22 23 #define is_lminion(mon) (is_minion((mon)->data) && \ 24 (mon)->data->maligntyp >= A_COALIGNED && \ 25 ((mon)->data != &mons[PM_ANGEL] || \ 26 EPRI(mon)->shralign > 0)) 27 28 #define is_flyer(ptr) (((ptr)->mflags1 & M1_FLY) != 0L) 29 #define is_floater(ptr) ((ptr)->mlet == S_EYE) 30 #define is_clinger(ptr) (((ptr)->mflags1 & M1_CLING) != 0L) 31 #define is_swimmer(ptr) (((ptr)->mflags1 & M1_SWIM) != 0L) 32 #define breathless(ptr) (((ptr)->mflags1 & M1_BREATHLESS) != 0L) 33 #define amphibious(ptr) (((ptr)->mflags1 & (M1_AMPHIBIOUS | M1_BREATHLESS)) != 0L) 34 #define passes_walls(ptr) (((ptr)->mflags1 & M1_WALLWALK) != 0L) 35 #define amorphous(ptr) (((ptr)->mflags1 & M1_AMORPHOUS) != 0L) 36 #define noncorporeal(ptr) ((ptr)->mlet == S_GHOST) 37 #define tunnels(ptr) (((ptr)->mflags1 & M1_TUNNEL) != 0L) 38 #define needspick(ptr) (((ptr)->mflags1 & M1_NEEDPICK) != 0L) 39 #define hides_under(ptr) (((ptr)->mflags1 & M1_CONCEAL) != 0L) 40 #define is_hider(ptr) (((ptr)->mflags1 & M1_HIDE) != 0L) 41 #define haseyes(ptr) (((ptr)->mflags1 & M1_NOEYES) == 0L) 42 #define eyecount(ptr) (!haseyes(ptr) ? 0 : \ 43 ((ptr) == &mons[PM_CYCLOPS] || \ 44 (ptr) == &mons[PM_FLOATING_EYE]) ? 1 : 2) 45 #define nohands(ptr) (((ptr)->mflags1 & M1_NOHANDS) != 0L) 46 #define nolimbs(ptr) (((ptr)->mflags1 & M1_NOLIMBS) == M1_NOLIMBS) 47 #define notake(ptr) (((ptr)->mflags1 & M1_NOTAKE) != 0L) 48 #define has_head(ptr) (((ptr)->mflags1 & M1_NOHEAD) == 0L) 49 #define has_horns(ptr) (num_horns(ptr) > 0) 50 #define is_whirly(ptr) ((ptr)->mlet == S_VORTEX || \ 51 (ptr) == &mons[PM_AIR_ELEMENTAL]) 52 #define flaming(ptr) ((ptr) == &mons[PM_FIRE_VORTEX] || \ 53 (ptr) == &mons[PM_FLAMING_SPHERE] || \ 54 (ptr) == &mons[PM_FIRE_ELEMENTAL] || \ 55 (ptr) == &mons[PM_SALAMANDER]) 56 #define is_silent(ptr) ((ptr)->msound == MS_SILENT) 57 #define unsolid(ptr) (((ptr)->mflags1 & M1_UNSOLID) != 0L) 58 #define mindless(ptr) (((ptr)->mflags1 & M1_MINDLESS) != 0L) 59 #define humanoid(ptr) (((ptr)->mflags1 & M1_HUMANOID) != 0L) 60 #define is_animal(ptr) (((ptr)->mflags1 & M1_ANIMAL) != 0L) 61 #define slithy(ptr) (((ptr)->mflags1 & M1_SLITHY) != 0L) 62 #define is_wooden(ptr) ((ptr) == &mons[PM_WOOD_GOLEM]) 63 #define thick_skinned(ptr) (((ptr)->mflags1 & M1_THICK_HIDE) != 0L) 64 #define lays_eggs(ptr) (((ptr)->mflags1 & M1_OVIPAROUS) != 0L) 65 #define regenerates(ptr) (((ptr)->mflags1 & M1_REGEN) != 0L) 66 #define noregen(ptr) (((ptr)->mflags3 & M3_NOREGEN) != 0L) 67 #define perceives(ptr) (((ptr)->mflags1 & M1_SEE_INVIS) != 0L) 68 #define can_teleport(ptr) (((ptr)->mflags1 & M1_TPORT) != 0L) 69 #define control_teleport(ptr) (((ptr)->mflags1 & M1_TPORT_CNTRL) != 0L) 70 #define telepathic(ptr) ((ptr) == &mons[PM_FLOATING_EYE] || \ 71 (ptr) == &mons[PM_MIND_FLAYER] || \ 72 (ptr) == &mons[PM_MASTER_MIND_FLAYER]) 73 #define is_armed(ptr) attacktype(ptr, AT_WEAP) 74 #define acidic(ptr) (((ptr)->mflags1 & M1_ACID) != 0L) 75 #define poisonous(ptr) (((ptr)->mflags1 & M1_POIS) != 0L) 76 #define carnivorous(ptr) (((ptr)->mflags1 & M1_CARNIVORE) != 0L) 77 #define herbivorous(ptr) (((ptr)->mflags1 & M1_HERBIVORE) != 0L) 78 #define metallivorous(ptr) (((ptr)->mflags1 & M1_METALLIVORE) != 0L) 79 #define polyok(ptr) (((ptr)->mflags2 & M2_NOPOLY) == 0L) 80 #define is_undead(ptr) (((ptr)->mflags2 & M2_UNDEAD) != 0L) 81 #define is_were(ptr) (((ptr)->mflags2 & M2_WERE) != 0L) 82 #define is_vampire(ptr) ((ptr)->mlet == S_VAMPIRE || \ 83 ((ptr)->mflags2 & M2_VAMPIRE) != 0) 84 /** feeds on blood */ 85 #define is_vampiric(ptr) ((is_vampire(ptr)) || \ 86 (ptr) == &mons[PM_VAMPIRE_BAT]) 87 #define is_elf(ptr) (((ptr)->mflags2 & M2_ELF) != 0L) 88 #define is_dwarf(ptr) (((ptr)->mflags2 & M2_DWARF) != 0L) 89 #define is_gnome(ptr) (((ptr)->mflags2 & M2_GNOME) != 0L) 90 #define is_orc(ptr) (((ptr)->mflags2 & M2_ORC) != 0L) 91 #define is_human(ptr) (((ptr)->mflags2 & M2_HUMAN) != 0L) 92 #define your_race(ptr) (((ptr)->mflags2 & urace.selfmask) != 0L) 93 #define is_bat(ptr) ((ptr) == &mons[PM_BAT] || \ 94 (ptr) == &mons[PM_GIANT_BAT] || \ 95 (ptr) == &mons[PM_VAMPIRE_BAT]) 96 #ifdef CONVICT 97 # define is_rat(ptr) ((ptr) == &mons[PM_SEWER_RAT] || \ 98 (ptr) == &mons[PM_GIANT_RAT] || \ 99 (ptr) == &mons[PM_RABID_RAT] || \ 100 (ptr) == &mons[PM_ENORMOUS_RAT]) 101 #else /* CONVICT */ 102 # define is_rat(ptr) ((ptr) == &mons[PM_SEWER_RAT] || \ 103 (ptr) == &mons[PM_GIANT_RAT] || \ 104 (ptr) == &mons[PM_RABID_RAT]) 105 #endif /* CONVICT */ 106 #define is_bird(ptr) ((ptr)->mlet == S_BAT && !is_bat(ptr)) 107 #define is_giant(ptr) (((ptr)->mflags2 & M2_GIANT) != 0L) 108 #define is_golem(ptr) ((ptr)->mlet == S_GOLEM) 109 #define is_statue(ptr) ((ptr)->mlet == S_STATUE) 110 #define is_domestic(ptr) (((ptr)->mflags2 & M2_DOMESTIC) != 0L) 111 #define is_demon(ptr) (((ptr)->mflags2 & M2_DEMON) != 0L) 112 #define is_mercenary(ptr) (((ptr)->mflags2 & M2_MERC) != 0L) 113 #define is_male(ptr) (((ptr)->mflags2 & M2_MALE) != 0L) 114 #define is_female(ptr) (((ptr)->mflags2 & M2_FEMALE) != 0L) 115 #define is_neuter(ptr) (((ptr)->mflags2 & M2_NEUTER) != 0L) 116 #define is_wanderer(ptr) (((ptr)->mflags2 & M2_WANDER) != 0L) 117 #define always_hostile(ptr) (((ptr)->mflags2 & M2_HOSTILE) != 0L) 118 #define always_peaceful(ptr) (((ptr)->mflags2 & M2_PEACEFUL) != 0L) 119 #define race_hostile(ptr) (((ptr)->mflags2 & urace.hatemask) != 0L) 120 #define race_peaceful(ptr) (((ptr)->mflags2 & urace.lovemask) != 0L) 121 #define extra_nasty(ptr) (((ptr)->mflags2 & M2_NASTY) != 0L) 122 #define strongmonst(ptr) (((ptr)->mflags2 & M2_STRONG) != 0L) 123 #define can_breathe(ptr) attacktype(ptr, AT_BREA) 124 #define cantwield(ptr) (nohands(ptr) || verysmall(ptr)) 125 #define could_twoweap(ptr) ((ptr)->mattk[1].aatyp == AT_WEAP) 126 #define cantweararm(ptr) (breakarm(ptr) || sliparm(ptr)) 127 #define throws_rocks(ptr) (((ptr)->mflags2 & M2_ROCKTHROW) != 0L) 128 #define type_is_pname(ptr) (((ptr)->mflags2 & M2_PNAME) != 0L) 129 #define is_lord(ptr) (((ptr)->mflags2 & M2_LORD) != 0L) 130 #define is_prince(ptr) (((ptr)->mflags2 & M2_PRINCE) != 0L) 131 #define is_ndemon(ptr) (is_demon(ptr) && \ 132 (((ptr)->mflags2 & (M2_LORD|M2_PRINCE)) == 0L)) 133 #define is_dlord(ptr) (is_demon(ptr) && is_lord(ptr)) 134 #define is_dprince(ptr) (is_demon(ptr) && is_prince(ptr)) 135 #define is_minion(ptr) ((ptr)->mflags2 & M2_MINION) 136 #define likes_gold(ptr) (((ptr)->mflags2 & M2_GREEDY) != 0L) 137 #define likes_gems(ptr) (((ptr)->mflags2 & M2_JEWELS) != 0L) 138 #define likes_objs(ptr) (((ptr)->mflags2 & M2_COLLECT) != 0L || \ 139 is_armed(ptr)) 140 #define likes_magic(ptr) (((ptr)->mflags2 & M2_MAGIC) != 0L) 141 #define webmaker(ptr) ((ptr) == &mons[PM_CAVE_SPIDER] || \ 142 (ptr) == &mons[PM_GIANT_SPIDER]) 143 #define is_unicorn(ptr) ((ptr)->mlet == S_UNICORN && likes_gems(ptr)) 144 #define is_longworm(ptr) (((ptr) == &mons[PM_BABY_LONG_WORM]) || \ 145 ((ptr) == &mons[PM_LONG_WORM]) || \ 146 ((ptr) == &mons[PM_LONG_WORM_TAIL])) 147 #define is_covetous(ptr) ((ptr->mflags3 & M3_COVETOUS)) 148 #define infravision(ptr) ((ptr->mflags3 & M3_INFRAVISION)) 149 #define infravisible(ptr) ((ptr->mflags3 & M3_INFRAVISIBLE)) 150 #define is_mplayer(ptr) (((ptr) >= &mons[PM_ARCHEOLOGIST]) && \ 151 ((ptr) <= &mons[PM_WIZARD])) 152 #define is_rider(ptr) ((ptr) == &mons[PM_DEATH] || \ 153 (ptr) == &mons[PM_FAMINE] || \ 154 (ptr) == &mons[PM_PESTILENCE]) 155 #define is_guardian(ptr) (((ptr) == &mons[PM_VLAD_THE_IMPALER]) || \ 156 ((ptr) == &mons[PM_WIZARD_OF_YENDOR]) || \ 157 (ptr->msound == MS_NEMESIS) || \ 158 ((ptr) == &mons[PM_HIGH_PRIEST] && Is_sanctum(&u.uz))) 159 #define is_placeholder(ptr) ((ptr) == &mons[PM_ORC] || \ 160 (ptr) == &mons[PM_GIANT] || \ 161 (ptr) == &mons[PM_ELF] || \ 162 (ptr) == &mons[PM_HUMAN]) 163 /* return TRUE if the monster tends to revive */ 164 #define is_reviver(ptr) (is_rider(ptr) || (ptr)->mlet == S_TROLL) 165 166 167 #ifdef PM_BEHOLDER 168 #define is_eye(ptr) (((ptr) == &mons[PM_FLOATING_EYE]) || \ 169 ((ptr) == &mons[PM_EVIL_EYE]) || \ 170 ((ptr) == &mons[PM_BEHOLDER])) 171 #else 172 #define is_eye(ptr) (((ptr) == &mons[PM_FLOATING_EYE]) || \ 173 ((ptr) == &mons[PM_EVIL_EYE])) 174 #endif 175 176 /* this returns the light's range, or 0 if none; if we add more light emitting 177 monsters, we'll likely have to add a new light range field to mons[] */ 178 #define emits_light(ptr) (((ptr)->mlet == S_LIGHT || \ 179 (ptr) == &mons[PM_FLAMING_SPHERE] || \ 180 (ptr) == &mons[PM_SHOCKING_SPHERE] || \ 181 (ptr) == &mons[PM_WAX_GOLEM] || \ 182 (ptr) == &mons[PM_BLAZING_FERN] || \ 183 (ptr) == &mons[PM_BLAZING_FERN_SPROUT] || \ 184 (ptr) == &mons[PM_BLAZING_FERN_SPORE] || \ 185 (!strcmp((ptr)->mname, "glowing dragon")) || \ 186 (!strcmp((ptr)->mname, "baby glowing dragon")) || \ 187 (ptr) == &mons[PM_FIRE_VORTEX]) ? 1 : \ 188 ((ptr) == &mons[PM_FIRE_ELEMENTAL]) ? 1 : 0) 189 /* [note: the light ranges above were reduced to 1 for performance...] */ 190 #define likes_lava(ptr) (ptr == &mons[PM_FIRE_ELEMENTAL] || \ 191 ptr == &mons[PM_SALAMANDER]) 192 #define pm_invisible(ptr) ((ptr) == &mons[PM_STALKER] || \ 193 (ptr) == &mons[PM_BLACK_LIGHT]) 194 195 /* could probably add more */ 196 #define likes_fire(ptr) ((ptr) == &mons[PM_FIRE_VORTEX] || \ 197 (ptr) == &mons[PM_FLAMING_SPHERE] || \ 198 likes_lava(ptr)) 199 200 #define touch_petrifies(ptr) ((ptr) == &mons[PM_COCKATRICE] || \ 201 (ptr) == &mons[PM_CHICKATRICE]) 202 203 #define is_gargoyle(ptr) ((ptr) == &mons[PM_GARGOYLE] || \ 204 (ptr) == &mons[PM_WINGED_GARGOYLE]) 205 206 #define is_weeping(ptr) ((ptr) == &mons[PM_WEEPING_ANGEL] || \ 207 (ptr) == &mons[PM_WEEPING_ARCHANGEL]) 208 209 #ifdef WEBB_DISINT 210 # define touch_disintegrates(ptr) ((ptr) == &mons[PM_DISINTEGRATOR]) 211 #endif 212 213 #define is_mind_flayer(ptr) ((ptr) == &mons[PM_MIND_FLAYER] || \ 214 (ptr) == &mons[PM_MASTER_MIND_FLAYER]) 215 216 #define nonliving(ptr) (is_golem(ptr) || is_undead(ptr) || \ 217 is_statue(ptr) || \ 218 (ptr)->mlet == S_VORTEX || \ 219 (ptr) == &mons[PM_MANES]) 220 221 #define is_blinker(ptr) ((ptr)->mflags3 & M3_BLINKER) 222 #define is_groupattacker(ptr) ((ptr)->mflags3 & M3_GROUPATTACK) 223 224 #define likes_swamp(ptr) ((ptr)->mlet == S_PUDDING || \ 225 (ptr)->mlet == S_FUNGUS || \ 226 (ptr) == &mons[PM_OCHRE_JELLY]) 227 #define stationary(ptr) ((ptr)->mflags3 & M3_STATIONARY) 228 229 /* Used for conduct with corpses, tins, and digestion attacks */ 230 /* G_NOCORPSE monsters might still be swallowed as a purple worm */ 231 /* Maybe someday this could be in mflags... */ 232 #define vegan(ptr) ((ptr)->mlet == S_BLOB || \ 233 (ptr)->mlet == S_JELLY || \ 234 (ptr)->mlet == S_FUNGUS || \ 235 (ptr)->mlet == S_VORTEX || \ 236 (ptr)->mlet == S_LIGHT || \ 237 ((ptr)->mlet == S_ELEMENTAL && \ 238 (ptr) != &mons[PM_STALKER]) || \ 239 ((ptr)->mlet == S_GOLEM && \ 240 (ptr) != &mons[PM_FLESH_GOLEM] && \ 241 (ptr) != &mons[PM_LEATHER_GOLEM]) || \ 242 noncorporeal(ptr)) 243 #define vegetarian(ptr) (vegan(ptr) || \ 244 ((ptr)->mlet == S_PUDDING && \ 245 (ptr) != &mons[PM_BLACK_PUDDING])) 246 247 /* Keep track of ferns, fern sprouts, fern spores, and other plants */ 248 249 #define is_fern_sprout(ptr) ((ptr) == &mons[PM_ARCTIC_FERN_SPROUT] || \ 250 (ptr) == &mons[PM_BLAZING_FERN_SPROUT] || \ 251 (ptr) == &mons[PM_DUNGEON_FERN_SPROUT] || \ 252 (ptr) == &mons[PM_SWAMP_FERN_SPROUT]) 253 254 #define is_fern_spore(ptr) ((ptr) == &mons[PM_FERN_SPORE] || \ 255 (ptr) == &mons[PM_ARCTIC_FERN_SPORE] || \ 256 (ptr) == &mons[PM_BLAZING_FERN_SPORE] || \ 257 (ptr) == &mons[PM_DUNGEON_FERN_SPORE] || \ 258 (ptr) == &mons[PM_SWAMP_FERN_SPORE]) 259 260 #define is_fern(ptr) (is_fern_sprout(ptr) || \ 261 (ptr) == &mons[PM_ARCTIC_FERN] || \ 262 (ptr) == &mons[PM_BLAZING_FERN] || \ 263 (ptr) == &mons[PM_DUNGEON_FERN] || \ 264 (ptr) == &mons[PM_SWAMP_FERN]) 265 266 #define is_vegetation(ptr) (is_fern(ptr) || \ 267 (ptr) == &mons[PM_DEVIL_S_SNARE]) 268 269 /* For vampires */ 270 #define has_blood(ptr) (!vegetarian(ptr) && \ 271 ((ptr)->mlet != S_GOLEM || (ptr) == &mons[PM_FLESH_GOLEM]) && \ 272 (!is_undead(ptr) || is_vampire(ptr))) 273 274 #ifdef CONVICT 275 #define befriend_with_obj(ptr, obj) ((obj)->oclass == FOOD_CLASS && \ 276 (is_domestic(ptr) || (is_rat(ptr) && Role_if(PM_CONVICT)))) 277 #else 278 #define befriend_with_obj(ptr, obj) ((obj)->oclass == FOOD_CLASS && \ 279 is_domestic(ptr)) 280 #endif 281 282 #define is_rockbreaker(ptr) (((ptr)->msound == MS_LEADER || \ 283 is_blkmktstaff((ptr)) || \ 284 is_rider((ptr))) && \ 285 !mtmp->mpeaceful) 286 287 #ifdef BLACKMARKET 288 #define is_blkmktstaff(ptr) (Is_blackmarket(&u.uz) && \ 289 ((ptr) == &mons[PM_BLACK_MARKETEER] || \ 290 (ptr) == &mons[PM_ONE_EYED_SAM])) 291 #endif /* BLACKMARKET */ 292 293 #endif /* MONDATA_H */ 294