NHDT->ANH, in most cases
[aNetHack.git] / include / obj.h
blob3dd39bf8e62da3774fee57f821b463c01c25f287
1 /* NetHack 3.6 obj.h $ANH-Date: 1456618994 2016/02/28 00:23:14 $ $ANH-Branch: NetHack-3.6.0 $:$ANH-Revision: 1.53 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 #ifndef OBJ_H
6 #define OBJ_H
8 /* #define obj obj_nh */ /* uncomment for SCO UNIX, which has a conflicting
9 * typedef for "obj" in <sys/types.h> */
11 union vptrs {
12 struct obj *v_nexthere; /* floor location lists */
13 struct obj *v_ocontainer; /* point back to container */
14 struct monst *v_ocarry; /* point back to carrying monst */
17 /****
18 *** oextra -- collection of all object extensions
19 ** (see the note at the bottom of this file before adding oextra fields)
21 struct oextra {
22 char *oname; /* ptr to name of object */
23 struct monst *omonst; /* ptr to attached monst struct */
24 unsigned *omid; /* ptr to m_id */
25 long *olong; /* ptr to misc long (temporary gold object) */
26 char *omailcmd; /* response_cmd for mail deliver */
29 struct obj {
30 struct obj *nobj;
31 union vptrs v;
32 #define nexthere v.v_nexthere
33 #define ocontainer v.v_ocontainer
34 #define ocarry v.v_ocarry
36 struct obj *cobj; /* contents list for containers */
37 unsigned o_id;
38 xchar ox, oy;
39 short otyp; /* object class number */
40 unsigned owt;
41 long quan; /* number of items */
43 schar spe; /* quality of weapon, armor or ring (+ or -);
44 number of charges for wand or charged tool ( >= -1 );
45 marks your eggs, tin variety and spinach tins;
46 Schroedinger's Box (1) or royal coffers for a court (2);
47 tells which fruit a fruit is;
48 special for uball and amulet;
49 scroll of mail (normal==0, bones or wishing==1, written==2);
50 historic and gender for statues */
51 #define STATUE_HISTORIC 0x01
52 #define STATUE_MALE 0x02
53 #define STATUE_FEMALE 0x04
54 char oclass; /* object class */
55 char invlet; /* designation in inventory */
56 char oartifact; /* artifact array index */
58 xchar where; /* where the object thinks it is */
59 #define OBJ_FREE 0 /* object not attached to anything */
60 #define OBJ_FLOOR 1 /* object on floor */
61 #define OBJ_CONTAINED 2 /* object in a container */
62 #define OBJ_INVENT 3 /* object in the hero's inventory */
63 #define OBJ_MINVENT 4 /* object in a monster inventory */
64 #define OBJ_MIGRATING 5 /* object sent off to another level */
65 #define OBJ_BURIED 6 /* object buried */
66 #define OBJ_ONBILL 7 /* object on shk bill */
67 #define NOBJ_STATES 8
68 xchar timed; /* # of fuses (timers) attached to this obj */
70 Bitfield(cursed, 1);
71 Bitfield(blessed, 1);
72 Bitfield(unpaid, 1); /* on some bill */
73 Bitfield(no_charge, 1); /* if shk shouldn't charge for this */
74 Bitfield(known, 1); /* exact nature known */
75 Bitfield(dknown, 1); /* color or text known */
76 Bitfield(bknown, 1); /* blessing or curse known */
77 Bitfield(rknown, 1); /* rustproof or not known */
79 Bitfield(oeroded, 2); /* rusted/burnt weapon/armor */
80 Bitfield(oeroded2, 2); /* corroded/rotted weapon/armor */
81 #define greatest_erosion(otmp) \
82 (int)((otmp)->oeroded > (otmp)->oeroded2 ? (otmp)->oeroded \
83 : (otmp)->oeroded2)
84 #define MAX_ERODE 3
85 #define orotten oeroded /* rotten food */
86 #define odiluted oeroded /* diluted potions */
87 #define norevive oeroded2
88 Bitfield(oerodeproof, 1); /* erodeproof weapon/armor */
89 Bitfield(olocked, 1); /* object is locked */
90 Bitfield(obroken, 1); /* lock has been broken */
91 #define degraded_horn obroken /* unicorn horn will poly to non-magic */
92 Bitfield(otrapped, 1); /* container is trapped */
93 /* or accidental tripped rolling boulder trap */
94 #define opoisoned otrapped /* object (weapon) is coated with poison */
96 Bitfield(recharged, 3); /* number of times it's been recharged */
97 #define on_ice recharged /* corpse on ice */
98 Bitfield(lamplit, 1); /* a light-source -- can be lit */
99 Bitfield(globby, 1); /* combines with like types on adjacent squares */
100 Bitfield(greased, 1); /* covered with grease */
101 Bitfield(nomerge, 1); /* set temporarily to prevent merging */
102 Bitfield(was_thrown, 1); /* thrown by hero since last picked up */
104 Bitfield(in_use, 1); /* for magic items before useup items */
105 Bitfield(bypass, 1); /* mark this as an object to be skipped by bhito() */
106 Bitfield(cknown, 1); /* contents of container assumed to be known */
107 Bitfield(lknown, 1); /* locked/unlocked status is known */
108 /* 4 free bits */
110 int corpsenm; /* type of corpse is mons[corpsenm] */
111 #define leashmon corpsenm /* gets m_id of attached pet */
112 #define fromsink corpsenm /* a potion from a sink */
113 #define novelidx corpsenm /* 3.6 tribute - the index of the novel title */
114 #define record_achieve_special corpsenm
115 int usecount; /* overloaded for various things that tally */
116 #define spestudied usecount /* # of times a spellbook has been studied */
117 unsigned oeaten; /* nutrition left in food, if partly eaten */
118 long age; /* creation date */
119 long owornmask;
120 struct oextra *oextra; /* pointer to oextra struct */
123 #define newobj() (struct obj *) alloc(sizeof(struct obj))
125 /***
126 ** oextra referencing and testing macros
129 #define ONAME(o) ((o)->oextra->oname)
130 #define OMID(o) ((o)->oextra->omid)
131 #define OMONST(o) ((o)->oextra->omonst)
132 #define OLONG(o) ((o)->oextra->olong)
133 #define OMAILCMD(o) ((o)->oextra->omailcmd)
135 #define has_oname(o) ((o)->oextra && ONAME(o))
136 #define has_omid(o) ((o)->oextra && OMID(o))
137 #define has_omonst(o) ((o)->oextra && OMONST(o))
138 #define has_olong(o) ((o)->oextra && OLONG(o))
139 #define has_omailcmd(o) ((o)->oextra && OMAILCMD(o))
141 /* Weapons and weapon-tools */
142 /* KMH -- now based on skill categories. Formerly:
143 * #define is_sword(otmp) (otmp->oclass == WEAPON_CLASS && \
144 * objects[otmp->otyp].oc_wepcat == WEP_SWORD)
145 * #define is_blade(otmp) (otmp->oclass == WEAPON_CLASS && \
146 * (objects[otmp->otyp].oc_wepcat == WEP_BLADE || \
147 * objects[otmp->otyp].oc_wepcat == WEP_SWORD))
148 * #define is_weptool(o) ((o)->oclass == TOOL_CLASS && \
149 * objects[(o)->otyp].oc_weptool)
150 * #define is_multigen(otyp) (otyp <= SHURIKEN)
151 * #define is_poisonable(otyp) (otyp <= BEC_DE_CORBIN)
153 #define is_blade(otmp) \
154 (otmp->oclass == WEAPON_CLASS \
155 && objects[otmp->otyp].oc_skill >= P_DAGGER \
156 && objects[otmp->otyp].oc_skill <= P_SABER)
157 #define is_axe(otmp) \
158 ((otmp->oclass == WEAPON_CLASS || otmp->oclass == TOOL_CLASS) \
159 && objects[otmp->otyp].oc_skill == P_AXE)
160 #define is_pick(otmp) \
161 ((otmp->oclass == WEAPON_CLASS || otmp->oclass == TOOL_CLASS) \
162 && objects[otmp->otyp].oc_skill == P_PICK_AXE)
163 #define is_sword(otmp) \
164 (otmp->oclass == WEAPON_CLASS \
165 && objects[otmp->otyp].oc_skill >= P_SHORT_SWORD \
166 && objects[otmp->otyp].oc_skill <= P_SABER)
167 #define is_pole(otmp) \
168 ((otmp->oclass == WEAPON_CLASS || otmp->oclass == TOOL_CLASS) \
169 && (objects[otmp->otyp].oc_skill == P_POLEARMS \
170 || objects[otmp->otyp].oc_skill == P_LANCE))
171 #define is_spear(otmp) \
172 (otmp->oclass == WEAPON_CLASS && objects[otmp->otyp].oc_skill == P_SPEAR)
173 #define is_launcher(otmp) \
174 (otmp->oclass == WEAPON_CLASS && objects[otmp->otyp].oc_skill >= P_BOW \
175 && objects[otmp->otyp].oc_skill <= P_CROSSBOW)
176 #define is_ammo(otmp) \
177 ((otmp->oclass == WEAPON_CLASS || otmp->oclass == GEM_CLASS) \
178 && objects[otmp->otyp].oc_skill >= -P_CROSSBOW \
179 && objects[otmp->otyp].oc_skill <= -P_BOW)
180 #define matching_launcher(a, l) \
181 ((l) && objects[(a)->otyp].oc_skill == -objects[(l)->otyp].oc_skill)
182 #define ammo_and_launcher(a, l) (is_ammo(a) && matching_launcher(a, l))
183 #define is_missile(otmp) \
184 ((otmp->oclass == WEAPON_CLASS || otmp->oclass == TOOL_CLASS) \
185 && objects[otmp->otyp].oc_skill >= -P_BOOMERANG \
186 && objects[otmp->otyp].oc_skill <= -P_DART)
187 #define is_weptool(o) \
188 ((o)->oclass == TOOL_CLASS && objects[(o)->otyp].oc_skill != P_NONE)
189 /* towel is not a weptool: spe isn't an enchantment, cursed towel
190 doesn't weld to hand, and twoweapon won't work with one */
191 #define is_wet_towel(o) ((o)->otyp == TOWEL && (o)->spe > 0)
192 #define bimanual(otmp) \
193 ((otmp->oclass == WEAPON_CLASS || otmp->oclass == TOOL_CLASS) \
194 && objects[otmp->otyp].oc_bimanual)
195 #define is_multigen(otmp) \
196 (otmp->oclass == WEAPON_CLASS \
197 && objects[otmp->otyp].oc_skill >= -P_SHURIKEN \
198 && objects[otmp->otyp].oc_skill <= -P_BOW)
199 #define is_poisonable(otmp) \
200 (otmp->oclass == WEAPON_CLASS \
201 && objects[otmp->otyp].oc_skill >= -P_SHURIKEN \
202 && objects[otmp->otyp].oc_skill <= -P_BOW)
203 #define uslinging() (uwep && objects[uwep->otyp].oc_skill == P_SLING)
204 /* 'is_quest_artifact()' only applies to the current role's artifact */
205 #define any_quest_artifact(o) ((o)->oartifact >= ART_ORB_OF_DETECTION)
207 /* Armor */
208 #define is_shield(otmp) \
209 (otmp->oclass == ARMOR_CLASS \
210 && objects[otmp->otyp].oc_armcat == ARM_SHIELD)
211 #define is_helmet(otmp) \
212 (otmp->oclass == ARMOR_CLASS && objects[otmp->otyp].oc_armcat == ARM_HELM)
213 #define is_boots(otmp) \
214 (otmp->oclass == ARMOR_CLASS \
215 && objects[otmp->otyp].oc_armcat == ARM_BOOTS)
216 #define is_gloves(otmp) \
217 (otmp->oclass == ARMOR_CLASS \
218 && objects[otmp->otyp].oc_armcat == ARM_GLOVES)
219 #define is_cloak(otmp) \
220 (otmp->oclass == ARMOR_CLASS \
221 && objects[otmp->otyp].oc_armcat == ARM_CLOAK)
222 #define is_shirt(otmp) \
223 (otmp->oclass == ARMOR_CLASS \
224 && objects[otmp->otyp].oc_armcat == ARM_SHIRT)
225 #define is_suit(otmp) \
226 (otmp->oclass == ARMOR_CLASS && objects[otmp->otyp].oc_armcat == ARM_SUIT)
227 #define is_elven_armor(otmp) \
228 ((otmp)->otyp == ELVEN_LEATHER_HELM \
229 || (otmp)->otyp == ELVEN_MITHRIL_COAT || (otmp)->otyp == ELVEN_CLOAK \
230 || (otmp)->otyp == ELVEN_SHIELD || (otmp)->otyp == ELVEN_BOOTS)
231 #define is_orcish_armor(otmp) \
232 ((otmp)->otyp == ORCISH_HELM || (otmp)->otyp == ORCISH_CHAIN_MAIL \
233 || (otmp)->otyp == ORCISH_RING_MAIL || (otmp)->otyp == ORCISH_CLOAK \
234 || (otmp)->otyp == URUK_HAI_SHIELD || (otmp)->otyp == ORCISH_SHIELD)
235 #define is_dwarvish_armor(otmp) \
236 ((otmp)->otyp == DWARVISH_IRON_HELM \
237 || (otmp)->otyp == DWARVISH_MITHRIL_COAT \
238 || (otmp)->otyp == DWARVISH_CLOAK \
239 || (otmp)->otyp == DWARVISH_ROUNDSHIELD)
240 #define is_gnomish_armor(otmp) (FALSE)
242 /* Eggs and other food */
243 #define MAX_EGG_HATCH_TIME 200 /* longest an egg can remain unhatched */
244 #define stale_egg(egg) \
245 ((monstermoves - (egg)->age) > (2 * MAX_EGG_HATCH_TIME))
246 #define ofood(o) ((o)->otyp == CORPSE || (o)->otyp == EGG || (o)->otyp == TIN)
247 #define polyfodder(obj) (ofood(obj) && pm_to_cham((obj)->corpsenm) != NON_PM)
248 #define mlevelgain(obj) (ofood(obj) && (obj)->corpsenm == PM_WRAITH)
249 #define mhealup(obj) (ofood(obj) && (obj)->corpsenm == PM_NURSE)
250 #define Is_pudding(o) \
251 (o->otyp == GLOB_OF_GRAY_OOZE || o->otyp == GLOB_OF_BROWN_PUDDING \
252 || o->otyp == GLOB_OF_GREEN_SLIME || o->otyp == GLOB_OF_BLACK_PUDDING)
254 /* Containers */
255 #define carried(o) ((o)->where == OBJ_INVENT)
256 #define mcarried(o) ((o)->where == OBJ_MINVENT)
257 #define Has_contents(o) \
258 (/* (Is_container(o) || (o)->otyp == STATUE) && */ \
259 (o)->cobj != (struct obj *) 0)
260 #define Is_container(o) ((o)->otyp >= LARGE_BOX && (o)->otyp <= BAG_OF_TRICKS)
261 #define Is_box(otmp) (otmp->otyp == LARGE_BOX || otmp->otyp == CHEST)
262 #define Is_mbag(otmp) \
263 (otmp->otyp == BAG_OF_HOLDING || otmp->otyp == BAG_OF_TRICKS)
264 #define SchroedingersBox(o) ((o)->otyp == LARGE_BOX && (o)->spe == 1)
266 /* dragon gear */
267 #define Is_dragon_scales(obj) \
268 ((obj)->otyp >= GRAY_DRAGON_SCALES && (obj)->otyp <= YELLOW_DRAGON_SCALES)
269 #define Is_dragon_mail(obj) \
270 ((obj)->otyp >= GRAY_DRAGON_SCALE_MAIL \
271 && (obj)->otyp <= YELLOW_DRAGON_SCALE_MAIL)
272 #define Is_dragon_armor(obj) (Is_dragon_scales(obj) || Is_dragon_mail(obj))
273 #define Dragon_scales_to_pm(obj) \
274 &mons[PM_GRAY_DRAGON + (obj)->otyp - GRAY_DRAGON_SCALES]
275 #define Dragon_mail_to_pm(obj) \
276 &mons[PM_GRAY_DRAGON + (obj)->otyp - GRAY_DRAGON_SCALE_MAIL]
277 #define Dragon_to_scales(pm) (GRAY_DRAGON_SCALES + (pm - mons))
279 /* Elven gear */
280 #define is_elven_weapon(otmp) \
281 ((otmp)->otyp == ELVEN_ARROW || (otmp)->otyp == ELVEN_SPEAR \
282 || (otmp)->otyp == ELVEN_DAGGER || (otmp)->otyp == ELVEN_SHORT_SWORD \
283 || (otmp)->otyp == ELVEN_BROADSWORD || (otmp)->otyp == ELVEN_BOW)
284 #define is_elven_obj(otmp) (is_elven_armor(otmp) || is_elven_weapon(otmp))
286 /* Orcish gear */
287 #define is_orcish_obj(otmp) \
288 (is_orcish_armor(otmp) || (otmp)->otyp == ORCISH_ARROW \
289 || (otmp)->otyp == ORCISH_SPEAR || (otmp)->otyp == ORCISH_DAGGER \
290 || (otmp)->otyp == ORCISH_SHORT_SWORD || (otmp)->otyp == ORCISH_BOW)
292 /* Dwarvish gear */
293 #define is_dwarvish_obj(otmp) \
294 (is_dwarvish_armor(otmp) || (otmp)->otyp == DWARVISH_SPEAR \
295 || (otmp)->otyp == DWARVISH_SHORT_SWORD \
296 || (otmp)->otyp == DWARVISH_MATTOCK)
298 /* Gnomish gear */
299 #define is_gnomish_obj(otmp) (is_gnomish_armor(otmp))
301 /* Light sources */
302 #define Is_candle(otmp) \
303 (otmp->otyp == TALLOW_CANDLE || otmp->otyp == WAX_CANDLE)
304 #define MAX_OIL_IN_FLASK 400 /* maximum amount of oil in a potion of oil */
306 /* MAGIC_LAMP intentionally excluded below */
307 /* age field of this is relative age rather than absolute */
308 #define age_is_relative(otmp) \
309 ((otmp)->otyp == BRASS_LANTERN || (otmp)->otyp == OIL_LAMP \
310 || (otmp)->otyp == CANDELABRUM_OF_INVOCATION \
311 || (otmp)->otyp == TALLOW_CANDLE || (otmp)->otyp == WAX_CANDLE \
312 || (otmp)->otyp == POT_OIL)
313 /* object can be ignited */
314 #define ignitable(otmp) \
315 ((otmp)->otyp == BRASS_LANTERN || (otmp)->otyp == OIL_LAMP \
316 || (otmp)->otyp == CANDELABRUM_OF_INVOCATION \
317 || (otmp)->otyp == TALLOW_CANDLE || (otmp)->otyp == WAX_CANDLE \
318 || (otmp)->otyp == POT_OIL)
320 /* things that can be read */
321 #define is_readable(otmp) \
322 ((otmp)->otyp == FORTUNE_COOKIE || (otmp)->otyp == T_SHIRT \
323 || (otmp)->otyp == ALCHEMY_SMOCK || (otmp)->otyp == CREDIT_CARD \
324 || (otmp)->otyp == CAN_OF_GREASE || (otmp)->otyp == MAGIC_MARKER \
325 || (otmp)->oclass == COIN_CLASS || (otmp)->oartifact == ART_ORB_OF_FATE \
326 || (otmp)->otyp == CANDY_BAR)
328 /* special stones */
329 #define is_graystone(obj) \
330 ((obj)->otyp == LUCKSTONE || (obj)->otyp == LOADSTONE \
331 || (obj)->otyp == FLINT || (obj)->otyp == TOUCHSTONE)
333 /* misc helpers, simple enough to be macros */
334 #define is_flimsy(otmp) \
335 (objects[(otmp)->otyp].oc_material <= LEATHER \
336 || (otmp)->otyp == RUBBER_HOSE)
337 #define is_plural(o) \
338 ((o)->quan != 1L \
339 /* "the Eyes of the Overworld" are plural, but \
340 "a pair of lenses named the Eyes of the Overworld" is not */ \
341 || ((o)->oartifact == ART_EYES_OF_THE_OVERWORLD \
342 && !undiscovered_artifact(ART_EYES_OF_THE_OVERWORLD)))
343 #define pair_of(o) ((o)->otyp == LENSES || is_gloves(o) || is_boots(o))
345 #define is_mines_prize(o) \
346 ((o)->otyp == LUCKSTONE && Is_mineend_level(&u.uz))
347 #define is_soko_prize(o) \
348 (((o)->otyp == AMULET_OF_REFLECTION \
349 || (o)->otyp == BAG_OF_HOLDING) \
350 && Is_sokoend_level(&u.uz))
353 /* Flags for get_obj_location(). */
354 #define CONTAINED_TOO 0x1
355 #define BURIED_TOO 0x2
357 /* object erosion types */
358 #define ERODE_BURN 0
359 #define ERODE_RUST 1
360 #define ERODE_ROT 2
361 #define ERODE_CORRODE 3
363 /* erosion flags for erode_obj() */
364 #define EF_NONE 0
365 #define EF_GREASE 0x1 /* check for a greased object */
366 #define EF_DESTROY 0x2 /* potentially destroy the object */
367 #define EF_VERBOSE 0x4 /* print extra messages */
368 #define EF_PAY 0x8 /* it's the player's fault */
370 /* erosion return values for erode_obj(), water_damage() */
371 #define ER_NOTHING 0 /* nothing happened */
372 #define ER_GREASED 1 /* protected by grease */
373 #define ER_DAMAGED 2 /* object was damaged in some way */
374 #define ER_DESTROYED 3 /* object was destroyed */
377 * Notes for adding new oextra structures:
379 * 1. Add the structure definition and any required macros in an
380 * appropriate header file that precedes this one.
381 * 2. Add a pointer to your new struct to oextra struct in this file.
382 * 3. Add a referencing macro to this file after the newobj macro above
383 * (see ONAME, OMONST, OMIN, OLONG, or OMAILCMD for examples).
384 * 4. Add a testing macro after the set of referencing macros
385 * (see has_oname(), has_omonst(), has_omin(), has_olong(),
386 * has_omailcmd() for examples).
387 * 5. Create newXX(otmp) function and possibly free_XX(otmp) function
388 * in an appropriate new or existing source file and add a prototype
389 * for it to include/extern.h. The majority of these are currently
390 * located in mkobj.c for convenience.
392 * void FDECL(newXX, (struct obj *));
393 * void FDECL(free_XX, (struct obj *));
395 * void
396 * newxx(otmp)
397 * struct obj *otmp;
399 * if (!otmp->oextra) otmp->oextra = newoextra();
400 * if (!XX(otmp)) {
401 * XX(otmp) = (struct XX *)alloc(sizeof(struct xx));
402 * (void) memset((genericptr_t) XX(otmp),
403 * 0, sizeof(struct xx));
407 * 6. Adjust size_obj() in src/cmd.c appropriately.
408 * 7. Adjust dealloc_oextra() in src/mkobj.c to clean up
409 * properly during obj deallocation.
410 * 8. Adjust copy_oextra() in src/mkobj.c to make duplicate
411 * copies of your struct or data onto another obj struct.
412 * 9. Adjust restobj() in src/restore.c to deal with your
413 * struct or data during a restore.
414 * 10. Adjust saveobj() in src/save.c to deal with your
415 * struct or data during a save.
418 #endif /* OBJ_H */