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