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
11#define pm_resistance(ptr,typ)	(((ptr)->mresists & (typ)) != 0)
12
13#define resists_fire(mon)	(((mon)->mintrinsics & MR_FIRE) != 0)
14#define resists_cold(mon)	(((mon)->mintrinsics & MR_COLD) != 0)
15#define resists_sleep(mon)	(((mon)->mintrinsics & MR_SLEEP) != 0)
16#define resists_disint(mon)	(((mon)->mintrinsics & MR_DISINT) != 0)
17#define resists_elec(mon)	(((mon)->mintrinsics & MR_ELEC) != 0)
18#define resists_poison(mon)	(((mon)->mintrinsics & MR_POISON) != 0)
19#define resists_acid(mon)	(((mon)->mintrinsics & MR_ACID) != 0)
20#define resists_ston(mon)	(((mon)->mintrinsics & MR_STONE) != 0)
21
22#define is_lminion(mon)		(is_minion((mon)->data) && \
23				 (mon)->data->maligntyp >= A_COALIGNED && \
24				 ((mon)->data != &mons[PM_ANGEL] || \
25				  EPRI(mon)->shralign > 0))
26
27#define is_flyer(ptr)		(((ptr)->mflags1 & M1_FLY) != 0L)
28#define is_floater(ptr)		((ptr)->mlet == S_EYE)
29#define is_clinger(ptr)		(((ptr)->mflags1 & M1_CLING) != 0L)
30#define is_swimmer(ptr)		(((ptr)->mflags1 & M1_SWIM) != 0L)
31#define breathless(ptr)		(((ptr)->mflags1 & M1_BREATHLESS) != 0L)
32#define amphibious(ptr)		(((ptr)->mflags1 & (M1_AMPHIBIOUS | M1_BREATHLESS)) != 0L)
33#define passes_walls(ptr)	(((ptr)->mflags1 & M1_WALLWALK) != 0L)
34#define amorphous(ptr)		(((ptr)->mflags1 & M1_AMORPHOUS) != 0L)
35#define noncorporeal(ptr)	((ptr)->mlet == S_GHOST)
36#define tunnels(ptr)		(((ptr)->mflags1 & M1_TUNNEL) != 0L)
37#define needspick(ptr)		(((ptr)->mflags1 & M1_NEEDPICK) != 0L)
38#define hides_under(ptr)	(((ptr)->mflags1 & M1_CONCEAL) != 0L)
39#define is_hider(ptr)		(((ptr)->mflags1 & M1_HIDE) != 0L)
40#define haseyes(ptr)		(((ptr)->mflags1 & M1_NOEYES) == 0L)
41#define eyecount(ptr)		(!haseyes(ptr) ? 0 : \
42				 ((ptr) == &mons[PM_CYCLOPS] || \
43				  (ptr) == &mons[PM_FLOATING_EYE]) ? 1 : 2)
44#define nohands(ptr)		(((ptr)->mflags1 & M1_NOHANDS) != 0L)
45#define nolimbs(ptr)		(((ptr)->mflags1 & M1_NOLIMBS) == M1_NOLIMBS)
46#define notake(ptr)		(((ptr)->mflags1 & M1_NOTAKE) != 0L)
47#define has_head(ptr)		(((ptr)->mflags1 & M1_NOHEAD) == 0L)
48#define has_horns(ptr)		(num_horns(ptr) > 0)
49#define is_whirly(ptr)		((ptr)->mlet == S_VORTEX || \
50				 (ptr) == &mons[PM_AIR_ELEMENTAL])
51#define flaming(ptr)		((ptr) == &mons[PM_FIRE_VORTEX] || \
52				 (ptr) == &mons[PM_FLAMING_SPHERE] || \
53				 (ptr) == &mons[PM_FIRE_ELEMENTAL] || \
54				 (ptr) == &mons[PM_SALAMANDER])
55#define is_silent(ptr)		((ptr)->msound == MS_SILENT)
56#define unsolid(ptr)		(((ptr)->mflags1 & M1_UNSOLID) != 0L)
57#define mindless(ptr)		(((ptr)->mflags1 & M1_MINDLESS) != 0L)
58#define humanoid(ptr)		(((ptr)->mflags1 & M1_HUMANOID) != 0L)
59#define is_animal(ptr)		(((ptr)->mflags1 & M1_ANIMAL) != 0L)
60#define slithy(ptr)		(((ptr)->mflags1 & M1_SLITHY) != 0L)
61#define is_wooden(ptr)		((ptr) == &mons[PM_WOOD_GOLEM])
62#define thick_skinned(ptr)	(((ptr)->mflags1 & M1_THICK_HIDE) != 0L)
63#define lays_eggs(ptr)		(((ptr)->mflags1 & M1_OVIPAROUS) != 0L)
64#define regenerates(ptr)	(((ptr)->mflags1 & M1_REGEN) != 0L)
65#define perceives(ptr)		(((ptr)->mflags1 & M1_SEE_INVIS) != 0L)
66#define can_teleport(ptr)	(((ptr)->mflags1 & M1_TPORT) != 0L)
67#define control_teleport(ptr)	(((ptr)->mflags1 & M1_TPORT_CNTRL) != 0L)
68#define telepathic(ptr)		((ptr) == &mons[PM_FLOATING_EYE] || \
69				 (ptr) == &mons[PM_MIND_FLAYER] || \
70				 (ptr) == &mons[PM_MASTER_MIND_FLAYER])
71#define is_armed(ptr)		attacktype(ptr, AT_WEAP)
72#define acidic(ptr)		(((ptr)->mflags1 & M1_ACID) != 0L)
73#define poisonous(ptr)		(((ptr)->mflags1 & M1_POIS) != 0L)
74#define carnivorous(ptr)	(((ptr)->mflags1 & M1_CARNIVORE) != 0L)
75#define herbivorous(ptr)	(((ptr)->mflags1 & M1_HERBIVORE) != 0L)
76#define metallivorous(ptr)	(((ptr)->mflags1 & M1_METALLIVORE) != 0L)
77#define polyok(ptr)		(((ptr)->mflags2 & M2_NOPOLY) == 0L)
78#define is_undead(ptr)		(((ptr)->mflags2 & M2_UNDEAD) != 0L)
79#define is_were(ptr)		(((ptr)->mflags2 & M2_WERE) != 0L)
80#define is_elf(ptr)		(((ptr)->mflags2 & M2_ELF) != 0L)
81#define is_dwarf(ptr)		(((ptr)->mflags2 & M2_DWARF) != 0L)
82#define is_gnome(ptr)		(((ptr)->mflags2 & M2_GNOME) != 0L)
83#define is_orc(ptr)		(((ptr)->mflags2 & M2_ORC) != 0L)
84#define is_human(ptr)		(((ptr)->mflags2 & M2_HUMAN) != 0L)
85#define your_race(ptr)		(((ptr)->mflags2 & urace.selfmask) != 0L)
86#define is_bat(ptr)		((ptr) == &mons[PM_BAT] || \
87				 (ptr) == &mons[PM_GIANT_BAT] || \
88				 (ptr) == &mons[PM_VAMPIRE_BAT])
89#define is_bird(ptr)		((ptr)->mlet == S_BAT && !is_bat(ptr))
90#define is_giant(ptr)		(((ptr)->mflags2 & M2_GIANT) != 0L)
91#define is_golem(ptr)		((ptr)->mlet == S_GOLEM)
92#define is_domestic(ptr)	(((ptr)->mflags2 & M2_DOMESTIC) != 0L)
93#define is_demon(ptr)		(((ptr)->mflags2 & M2_DEMON) != 0L)
94#define is_mercenary(ptr)	(((ptr)->mflags2 & M2_MERC) != 0L)
95#define is_male(ptr)		(((ptr)->mflags2 & M2_MALE) != 0L)
96#define is_female(ptr)		(((ptr)->mflags2 & M2_FEMALE) != 0L)
97#define is_neuter(ptr)		(((ptr)->mflags2 & M2_NEUTER) != 0L)
98#define is_wanderer(ptr)	(((ptr)->mflags2 & M2_WANDER) != 0L)
99#define always_hostile(ptr)	(((ptr)->mflags2 & M2_HOSTILE) != 0L)
100#define always_peaceful(ptr)	(((ptr)->mflags2 & M2_PEACEFUL) != 0L)
101#define race_hostile(ptr)	(((ptr)->mflags2 & urace.hatemask) != 0L)
102#define race_peaceful(ptr)	(((ptr)->mflags2 & urace.lovemask) != 0L)
103#define extra_nasty(ptr)	(((ptr)->mflags2 & M2_NASTY) != 0L)
104#define strongmonst(ptr)	(((ptr)->mflags2 & M2_STRONG) != 0L)
105#define can_breathe(ptr)	attacktype(ptr, AT_BREA)
106#define cantwield(ptr)		(nohands(ptr) || verysmall(ptr))
107#define could_twoweap(ptr)	((ptr)->mattk[1].aatyp == AT_WEAP)
108#define cantweararm(ptr)	(breakarm(ptr) || sliparm(ptr))
109#define throws_rocks(ptr)	(((ptr)->mflags2 & M2_ROCKTHROW) != 0L)
110#define type_is_pname(ptr)	(((ptr)->mflags2 & M2_PNAME) != 0L)
111#define is_lord(ptr)		(((ptr)->mflags2 & M2_LORD) != 0L)
112#define is_prince(ptr)		(((ptr)->mflags2 & M2_PRINCE) != 0L)
113#define is_ndemon(ptr)		(is_demon(ptr) && \
114				 (((ptr)->mflags2 & (M2_LORD|M2_PRINCE)) == 0L))
115#define is_dlord(ptr)		(is_demon(ptr) && is_lord(ptr))
116#define is_dprince(ptr)		(is_demon(ptr) && is_prince(ptr))
117#define is_minion(ptr)		((ptr)->mflags2 & M2_MINION)
118#define likes_gold(ptr)		(((ptr)->mflags2 & M2_GREEDY) != 0L)
119#define likes_gems(ptr)		(((ptr)->mflags2 & M2_JEWELS) != 0L)
120#define likes_objs(ptr)		(((ptr)->mflags2 & M2_COLLECT) != 0L || \
121				 is_armed(ptr))
122#define likes_magic(ptr)	(((ptr)->mflags2 & M2_MAGIC) != 0L)
123#define webmaker(ptr)		((ptr) == &mons[PM_CAVE_SPIDER] || \
124				 (ptr) == &mons[PM_GIANT_SPIDER])
125#define is_unicorn(ptr)		((ptr)->mlet == S_UNICORN && likes_gems(ptr))
126#define is_longworm(ptr)	(((ptr) == &mons[PM_BABY_LONG_WORM]) || \
127				 ((ptr) == &mons[PM_LONG_WORM]) || \
128				 ((ptr) == &mons[PM_LONG_WORM_TAIL]))
129#define is_covetous(ptr)	((ptr->mflags3 & M3_COVETOUS))
130#define infravision(ptr)	((ptr->mflags3 & M3_INFRAVISION))
131#define infravisible(ptr)	((ptr->mflags3 & M3_INFRAVISIBLE))
132#define is_mplayer(ptr)		(((ptr) >= &mons[PM_ARCHEOLOGIST]) && \
133				 ((ptr) <= &mons[PM_WIZARD]))
134#define is_rider(ptr)		((ptr) == &mons[PM_DEATH] || \
135				 (ptr) == &mons[PM_FAMINE] || \
136				 (ptr) == &mons[PM_PESTILENCE])
137#define is_placeholder(ptr)	((ptr) == &mons[PM_ORC] || \
138				 (ptr) == &mons[PM_GIANT] || \
139				 (ptr) == &mons[PM_ELF] || \
140				 (ptr) == &mons[PM_HUMAN])
141/* return TRUE if the monster tends to revive */
142#define is_reviver(ptr)		(is_rider(ptr) || (ptr)->mlet == S_TROLL)
143
144/* this returns the light's range, or 0 if none; if we add more light emitting
145   monsters, we'll likely have to add a new light range field to mons[] */
146#define emits_light(ptr)	(((ptr)->mlet == S_LIGHT || \
147				  (ptr) == &mons[PM_FLAMING_SPHERE] || \
148				  (ptr) == &mons[PM_SHOCKING_SPHERE] || \
149				  (ptr) == &mons[PM_FIRE_VORTEX]) ? 1 : \
150				 ((ptr) == &mons[PM_FIRE_ELEMENTAL]) ? 1 : 0)
151/*	[note: the light ranges above were reduced to 1 for performance...] */
152#define likes_lava(ptr)		(ptr == &mons[PM_FIRE_ELEMENTAL] || \
153				 ptr == &mons[PM_SALAMANDER])
154#define pm_invisible(ptr) ((ptr) == &mons[PM_STALKER] || \
155			   (ptr) == &mons[PM_BLACK_LIGHT])
156
157/* could probably add more */
158#define likes_fire(ptr)		((ptr) == &mons[PM_FIRE_VORTEX] || \
159				  (ptr) == &mons[PM_FLAMING_SPHERE] || \
160				 likes_lava(ptr))
161
162#define touch_petrifies(ptr)	((ptr) == &mons[PM_COCKATRICE] || \
163				 (ptr) == &mons[PM_CHICKATRICE])
164
165#define is_mind_flayer(ptr)	((ptr) == &mons[PM_MIND_FLAYER] || \
166				 (ptr) == &mons[PM_MASTER_MIND_FLAYER])
167
168#define nonliving(ptr)		(is_golem(ptr) || is_undead(ptr) || \
169				 (ptr)->mlet == S_VORTEX || \
170				 (ptr) == &mons[PM_MANES])
171
172/* Used for conduct with corpses, tins, and digestion attacks */
173/* G_NOCORPSE monsters might still be swallowed as a purple worm */
174/* Maybe someday this could be in mflags... */
175#define vegan(ptr)		((ptr)->mlet == S_BLOB || \
176				 (ptr)->mlet == S_JELLY ||            \
177				 (ptr)->mlet == S_FUNGUS ||           \
178				 (ptr)->mlet == S_VORTEX ||           \
179				 (ptr)->mlet == S_LIGHT ||            \
180				((ptr)->mlet == S_ELEMENTAL &&        \
181				 (ptr) != &mons[PM_STALKER]) ||       \
182				((ptr)->mlet == S_GOLEM &&            \
183				 (ptr) != &mons[PM_FLESH_GOLEM] &&    \
184				 (ptr) != &mons[PM_LEATHER_GOLEM]) || \
185				 noncorporeal(ptr))
186#define vegetarian(ptr)		(vegan(ptr) || \
187				((ptr)->mlet == S_PUDDING &&         \
188				 (ptr) != &mons[PM_BLACK_PUDDING]))
189
190#define befriend_with_obj(ptr, obj) ((obj)->oclass == FOOD_CLASS && \
191				     is_domestic(ptr))
192
193#endif /* MONDATA_H */
194