1/* SCCS Id: @(#)obj.h 3.4 2002/01/07 */ 2/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3/* NetHack may be freely redistributed. See license for details. */ 4 5#ifndef OBJ_H 6#define OBJ_H 7 8/* #define obj obj_nh */ /* uncomment for SCO UNIX, which has a conflicting 9 * typedef for "obj" in <sys/types.h> */ 10 11union 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 */ 15}; 16 17struct obj { 18 struct obj *nobj; 19 union vptrs v; 20#define nexthere v.v_nexthere 21#define ocontainer v.v_ocontainer 22#define ocarry v.v_ocarry 23 24 struct obj *cobj; /* contents list for containers */ 25 unsigned o_id; 26 xchar ox,oy; 27 short otyp; /* object class number */ 28 unsigned owt; 29 long quan; /* number of items */ 30 31 schar spe; /* quality of weapon, armor or ring (+ or -) 32 number of charges for wand ( >= -1 ) 33 marks your eggs, spinach tins 34 royal coffers for a court ( == 2) 35 tells which fruit a fruit is 36 special for uball and amulet 37 historic and gender for statues */ 38#define STATUE_HISTORIC 0x01 39#define STATUE_MALE 0x02 40#define STATUE_FEMALE 0x04 41 char oclass; /* object class */ 42 char invlet; /* designation in inventory */ 43 char oartifact; /* artifact array index */ 44 45 xchar where; /* where the object thinks it is */ 46#define OBJ_FREE 0 /* object not attached to anything */ 47#define OBJ_FLOOR 1 /* object on floor */ 48#define OBJ_CONTAINED 2 /* object in a container */ 49#define OBJ_INVENT 3 /* object in the hero's inventory */ 50#define OBJ_MINVENT 4 /* object in a monster inventory */ 51#define OBJ_MIGRATING 5 /* object sent off to another level */ 52#define OBJ_BURIED 6 /* object buried */ 53#define OBJ_ONBILL 7 /* object on shk bill */ 54#define NOBJ_STATES 8 55 xchar timed; /* # of fuses (timers) attached to this obj */ 56 57 Bitfield(cursed,1); 58 Bitfield(blessed,1); 59 Bitfield(unpaid,1); /* on some bill */ 60 Bitfield(no_charge,1); /* if shk shouldn't charge for this */ 61 Bitfield(known,1); /* exact nature known */ 62 Bitfield(dknown,1); /* color or text known */ 63 Bitfield(bknown,1); /* blessing or curse known */ 64 Bitfield(rknown,1); /* rustproof or not known */ 65 66 Bitfield(oeroded,2); /* rusted/burnt weapon/armor */ 67 Bitfield(oeroded2,2); /* corroded/rotted weapon/armor */ 68#define greatest_erosion(otmp) (int)((otmp)->oeroded > (otmp)->oeroded2 ? (otmp)->oeroded : (otmp)->oeroded2) 69#define MAX_ERODE 3 70#define orotten oeroded /* rotten food */ 71#define odiluted oeroded /* diluted potions */ 72#define norevive oeroded2 73 Bitfield(oerodeproof,1); /* erodeproof weapon/armor */ 74 Bitfield(olocked,1); /* object is locked */ 75 Bitfield(obroken,1); /* lock has been broken */ 76 Bitfield(otrapped,1); /* container is trapped */ 77 /* or accidental tripped rolling boulder trap */ 78#define opoisoned otrapped /* object (weapon) is coated with poison */ 79 80 Bitfield(recharged,3); /* number of times it's been recharged */ 81 Bitfield(lamplit,1); /* a light-source -- can be lit */ 82#ifdef INVISIBLE_OBJECTS 83 Bitfield(oinvis,1); /* invisible */ 84#endif 85 Bitfield(greased,1); /* covered with grease */ 86 Bitfield(oattached,2); /* obj struct has special attachment */ 87#define OATTACHED_NOTHING 0 88#define OATTACHED_MONST 1 /* monst struct in oextra */ 89#define OATTACHED_M_ID 2 /* monst id in oextra */ 90#define OATTACHED_UNUSED3 3 91 92 Bitfield(in_use,1); /* for magic items before useup items */ 93 Bitfield(bypass,1); /* mark this as an object to be skipped by bhito() */ 94 /* 6 free bits */ 95 96 int corpsenm; /* type of corpse is mons[corpsenm] */ 97#define leashmon corpsenm /* gets m_id of attached pet */ 98#define spestudied corpsenm /* # of times a spellbook has been studied */ 99#define fromsink corpsenm /* a potion from a sink */ 100 unsigned oeaten; /* nutrition left in food, if partly eaten */ 101 long age; /* creation date */ 102 103 uchar onamelth; /* length of name (following oxlth) */ 104 short oxlth; /* length of following data */ 105 /* in order to prevent alignment problems oextra should 106 be (or follow) a long int */ 107 long owornmask; 108 long oextra[1]; /* used for name of ordinary objects - length 109 is flexible; amount for tmp gold objects */ 110}; 111 112#define newobj(xl) (struct obj *)alloc((unsigned)(xl) + sizeof(struct obj)) 113#define ONAME(otmp) (((char *)(otmp)->oextra) + (otmp)->oxlth) 114 115/* Weapons and weapon-tools */ 116/* KMH -- now based on skill categories. Formerly: 117 * #define is_sword(otmp) (otmp->oclass == WEAPON_CLASS && \ 118 * objects[otmp->otyp].oc_wepcat == WEP_SWORD) 119 * #define is_blade(otmp) (otmp->oclass == WEAPON_CLASS && \ 120 * (objects[otmp->otyp].oc_wepcat == WEP_BLADE || \ 121 * objects[otmp->otyp].oc_wepcat == WEP_SWORD)) 122 * #define is_weptool(o) ((o)->oclass == TOOL_CLASS && \ 123 * objects[(o)->otyp].oc_weptool) 124 * #define is_multigen(otyp) (otyp <= SHURIKEN) 125 * #define is_poisonable(otyp) (otyp <= BEC_DE_CORBIN) 126 */ 127#define is_blade(otmp) (otmp->oclass == WEAPON_CLASS && \ 128 objects[otmp->otyp].oc_skill >= P_DAGGER && \ 129 objects[otmp->otyp].oc_skill <= P_SABER) 130#define is_axe(otmp) ((otmp->oclass == WEAPON_CLASS || \ 131 otmp->oclass == TOOL_CLASS) && \ 132 objects[otmp->otyp].oc_skill == P_AXE) 133#define is_pick(otmp) ((otmp->oclass == WEAPON_CLASS || \ 134 otmp->oclass == TOOL_CLASS) && \ 135 objects[otmp->otyp].oc_skill == P_PICK_AXE) 136#define is_sword(otmp) (otmp->oclass == WEAPON_CLASS && \ 137 objects[otmp->otyp].oc_skill >= P_SHORT_SWORD && \ 138 objects[otmp->otyp].oc_skill <= P_SABER) 139#define is_pole(otmp) ((otmp->oclass == WEAPON_CLASS || \ 140 otmp->oclass == TOOL_CLASS) && \ 141 (objects[otmp->otyp].oc_skill == P_POLEARMS || \ 142 objects[otmp->otyp].oc_skill == P_LANCE)) 143#define is_spear(otmp) (otmp->oclass == WEAPON_CLASS && \ 144 objects[otmp->otyp].oc_skill >= P_SPEAR && \ 145 objects[otmp->otyp].oc_skill <= P_JAVELIN) 146#define is_launcher(otmp) (otmp->oclass == WEAPON_CLASS && \ 147 objects[otmp->otyp].oc_skill >= P_BOW && \ 148 objects[otmp->otyp].oc_skill <= P_CROSSBOW) 149#define is_ammo(otmp) ((otmp->oclass == WEAPON_CLASS || \ 150 otmp->oclass == GEM_CLASS) && \ 151 objects[otmp->otyp].oc_skill >= -P_CROSSBOW && \ 152 objects[otmp->otyp].oc_skill <= -P_BOW) 153#define ammo_and_launcher(otmp,ltmp) \ 154 (is_ammo(otmp) && (ltmp) && \ 155 objects[(otmp)->otyp].oc_skill == -objects[(ltmp)->otyp].oc_skill) 156#define is_missile(otmp) ((otmp->oclass == WEAPON_CLASS || \ 157 otmp->oclass == TOOL_CLASS) && \ 158 objects[otmp->otyp].oc_skill >= -P_BOOMERANG && \ 159 objects[otmp->otyp].oc_skill <= -P_DART) 160#define is_weptool(o) ((o)->oclass == TOOL_CLASS && \ 161 objects[(o)->otyp].oc_skill != P_NONE) 162#define bimanual(otmp) ((otmp->oclass == WEAPON_CLASS || \ 163 otmp->oclass == TOOL_CLASS) && \ 164 objects[otmp->otyp].oc_bimanual) 165#define is_multigen(otmp) (otmp->oclass == WEAPON_CLASS && \ 166 objects[otmp->otyp].oc_skill >= -P_SHURIKEN && \ 167 objects[otmp->otyp].oc_skill <= -P_BOW) 168#define is_poisonable(otmp) (otmp->oclass == WEAPON_CLASS && \ 169 objects[otmp->otyp].oc_skill >= -P_SHURIKEN && \ 170 objects[otmp->otyp].oc_skill <= -P_BOW) 171#define uslinging() (uwep && objects[uwep->otyp].oc_skill == P_SLING) 172 173/* Armor */ 174#define is_shield(otmp) (otmp->oclass == ARMOR_CLASS && \ 175 objects[otmp->otyp].oc_armcat == ARM_SHIELD) 176#define is_helmet(otmp) (otmp->oclass == ARMOR_CLASS && \ 177 objects[otmp->otyp].oc_armcat == ARM_HELM) 178#define is_boots(otmp) (otmp->oclass == ARMOR_CLASS && \ 179 objects[otmp->otyp].oc_armcat == ARM_BOOTS) 180#define is_gloves(otmp) (otmp->oclass == ARMOR_CLASS && \ 181 objects[otmp->otyp].oc_armcat == ARM_GLOVES) 182#define is_cloak(otmp) (otmp->oclass == ARMOR_CLASS && \ 183 objects[otmp->otyp].oc_armcat == ARM_CLOAK) 184#define is_shirt(otmp) (otmp->oclass == ARMOR_CLASS && \ 185 objects[otmp->otyp].oc_armcat == ARM_SHIRT) 186#define is_suit(otmp) (otmp->oclass == ARMOR_CLASS && \ 187 objects[otmp->otyp].oc_armcat == ARM_SUIT) 188#define is_elven_armor(otmp) ((otmp)->otyp == ELVEN_LEATHER_HELM\ 189 || (otmp)->otyp == ELVEN_MITHRIL_COAT\ 190 || (otmp)->otyp == ELVEN_CLOAK\ 191 || (otmp)->otyp == ELVEN_SHIELD\ 192 || (otmp)->otyp == ELVEN_BOOTS) 193#define is_orcish_armor(otmp) ((otmp)->otyp == ORCISH_HELM\ 194 || (otmp)->otyp == ORCISH_CHAIN_MAIL\ 195 || (otmp)->otyp == ORCISH_RING_MAIL\ 196 || (otmp)->otyp == ORCISH_CLOAK\ 197 || (otmp)->otyp == URUK_HAI_SHIELD\ 198 || (otmp)->otyp == ORCISH_SHIELD) 199#define is_dwarvish_armor(otmp) ((otmp)->otyp == DWARVISH_IRON_HELM\ 200 || (otmp)->otyp == DWARVISH_MITHRIL_COAT\ 201 || (otmp)->otyp == DWARVISH_CLOAK\ 202 || (otmp)->otyp == DWARVISH_ROUNDSHIELD) 203#define is_gnomish_armor(otmp) (FALSE) 204 205 206/* Eggs and other food */ 207#define MAX_EGG_HATCH_TIME 200 /* longest an egg can remain unhatched */ 208#define stale_egg(egg) ((monstermoves - (egg)->age) > (2*MAX_EGG_HATCH_TIME)) 209#define ofood(o) ((o)->otyp == CORPSE || (o)->otyp == EGG || (o)->otyp == TIN) 210#define polyfodder(obj) (ofood(obj) && \ 211 pm_to_cham((obj)->corpsenm) != CHAM_ORDINARY) 212#define mlevelgain(obj) (ofood(obj) && (obj)->corpsenm == PM_WRAITH) 213#define mhealup(obj) (ofood(obj) && (obj)->corpsenm == PM_NURSE) 214 215/* Containers */ 216#define carried(o) ((o)->where == OBJ_INVENT) 217#define mcarried(o) ((o)->where == OBJ_MINVENT) 218#define Has_contents(o) (/* (Is_container(o) || (o)->otyp == STATUE) && */ \ 219 (o)->cobj != (struct obj *)0) 220#define Is_container(o) ((o)->otyp >= LARGE_BOX && (o)->otyp <= BAG_OF_TRICKS) 221#define Is_box(otmp) (otmp->otyp == LARGE_BOX || otmp->otyp == CHEST) 222#define Is_mbag(otmp) (otmp->otyp == BAG_OF_HOLDING || \ 223 otmp->otyp == BAG_OF_TRICKS) 224 225/* dragon gear */ 226#define Is_dragon_scales(obj) ((obj)->otyp >= GRAY_DRAGON_SCALES && \ 227 (obj)->otyp <= YELLOW_DRAGON_SCALES) 228#define Is_dragon_mail(obj) ((obj)->otyp >= GRAY_DRAGON_SCALE_MAIL && \ 229 (obj)->otyp <= YELLOW_DRAGON_SCALE_MAIL) 230#define Is_dragon_armor(obj) (Is_dragon_scales(obj) || Is_dragon_mail(obj)) 231#define Dragon_scales_to_pm(obj) &mons[PM_GRAY_DRAGON + (obj)->otyp \ 232 - GRAY_DRAGON_SCALES] 233#define Dragon_mail_to_pm(obj) &mons[PM_GRAY_DRAGON + (obj)->otyp \ 234 - GRAY_DRAGON_SCALE_MAIL] 235#define Dragon_to_scales(pm) (GRAY_DRAGON_SCALES + (pm - mons)) 236 237/* Elven gear */ 238#define is_elven_weapon(otmp) ((otmp)->otyp == ELVEN_ARROW\ 239 || (otmp)->otyp == ELVEN_SPEAR\ 240 || (otmp)->otyp == ELVEN_DAGGER\ 241 || (otmp)->otyp == ELVEN_SHORT_SWORD\ 242 || (otmp)->otyp == ELVEN_BROADSWORD\ 243 || (otmp)->otyp == ELVEN_BOW) 244#define is_elven_obj(otmp) (is_elven_armor(otmp) || is_elven_weapon(otmp)) 245 246/* Orcish gear */ 247#define is_orcish_obj(otmp) (is_orcish_armor(otmp)\ 248 || (otmp)->otyp == ORCISH_ARROW\ 249 || (otmp)->otyp == ORCISH_SPEAR\ 250 || (otmp)->otyp == ORCISH_DAGGER\ 251 || (otmp)->otyp == ORCISH_SHORT_SWORD\ 252 || (otmp)->otyp == ORCISH_BOW) 253 254/* Dwarvish gear */ 255#define is_dwarvish_obj(otmp) (is_dwarvish_armor(otmp)\ 256 || (otmp)->otyp == DWARVISH_SPEAR\ 257 || (otmp)->otyp == DWARVISH_SHORT_SWORD\ 258 || (otmp)->otyp == DWARVISH_MATTOCK) 259 260/* Gnomish gear */ 261#define is_gnomish_obj(otmp) (is_gnomish_armor(otmp)) 262 263/* Light sources */ 264#define Is_candle(otmp) (otmp->otyp == TALLOW_CANDLE || \ 265 otmp->otyp == WAX_CANDLE) 266#define MAX_OIL_IN_FLASK 400 /* maximum amount of oil in a potion of oil */ 267 268/* MAGIC_LAMP intentionally excluded below */ 269/* age field of this is relative age rather than absolute */ 270#define age_is_relative(otmp) ((otmp)->otyp == BRASS_LANTERN\ 271 || (otmp)->otyp == OIL_LAMP\ 272 || (otmp)->otyp == CANDELABRUM_OF_INVOCATION\ 273 || (otmp)->otyp == TALLOW_CANDLE\ 274 || (otmp)->otyp == WAX_CANDLE\ 275 || (otmp)->otyp == POT_OIL) 276/* object can be ignited */ 277#define ignitable(otmp) ((otmp)->otyp == BRASS_LANTERN\ 278 || (otmp)->otyp == OIL_LAMP\ 279 || (otmp)->otyp == CANDELABRUM_OF_INVOCATION\ 280 || (otmp)->otyp == TALLOW_CANDLE\ 281 || (otmp)->otyp == WAX_CANDLE\ 282 || (otmp)->otyp == POT_OIL) 283 284/* special stones */ 285#define is_graystone(obj) ((obj)->otyp == LUCKSTONE || \ 286 (obj)->otyp == LOADSTONE || \ 287 (obj)->otyp == FLINT || \ 288 (obj)->otyp == TOUCHSTONE) 289 290/* misc */ 291#ifdef KOPS 292#define is_flimsy(otmp) (objects[(otmp)->otyp].oc_material <= LEATHER || \ 293 (otmp)->otyp == RUBBER_HOSE) 294#else 295#define is_flimsy(otmp) (objects[(otmp)->otyp].oc_material <= LEATHER) 296#endif 297 298/* helpers, simple enough to be macros */ 299#define is_plural(o) ((o)->quan > 1 || \ 300 (o)->oartifact == ART_EYES_OF_THE_OVERWORLD) 301 302/* Flags for get_obj_location(). */ 303#define CONTAINED_TOO 0x1 304#define BURIED_TOO 0x2 305 306#endif /* OBJ_H */ 307