obj.h

Go to the documentation of this file.
00001 /*      SCCS Id: @(#)obj.h      3.4     2002/01/07      */
00002 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
00003 /* NetHack may be freely redistributed.  See license for details. */
00004 
00005 #ifndef OBJ_H
00006 #define OBJ_H
00007 
00008 /* #define obj obj_nh */ /* uncomment for SCO UNIX, which has a conflicting
00009                           * typedef for "obj" in <sys/types.h> */
00010 
00011 union vptrs {
00012             struct obj *v_nexthere;     /* floor location lists */
00013             struct obj *v_ocontainer;   /* point back to container */
00014             struct monst *v_ocarry;     /* point back to carrying monst */
00015 };
00016 
00017 struct obj {
00018         struct obj *nobj;
00019         union vptrs v;
00020 #define nexthere        v.v_nexthere
00021 #define ocontainer      v.v_ocontainer
00022 #define ocarry          v.v_ocarry
00023 
00024         struct obj *cobj;       /* contents list for containers */
00025         size_t o_id;
00026         xchar ox,oy;
00027         short otyp;             /* object class number */
00028         unsigned owt;
00029         long quan;              /* number of items */
00030 
00031         schar spe;              /* quality of weapon, armor or ring (+ or -)
00032                                    number of charges for wand ( >= -1 )
00033                                    marks your eggs, spinach tins
00034                                    royal coffers for a court ( == 2)
00035                                    tells which fruit a fruit is
00036                                    special for uball and amulet
00037                                    historic and gender for statues */
00038 #define STATUE_HISTORIC 0x01
00039 #define STATUE_MALE     0x02
00040 #define STATUE_FEMALE   0x04
00041         char    oclass;         /* object class */
00042         char    invlet;         /* designation in inventory */
00043         char    oartifact;      /* artifact array index */
00044 
00045         xchar where;            /* where the object thinks it is */
00046 #define OBJ_FREE        0               /* object not attached to anything */
00047 #define OBJ_FLOOR       1               /* object on floor */
00048 #define OBJ_CONTAINED   2               /* object in a container */
00049 #define OBJ_INVENT      3               /* object in the hero's inventory */
00050 #define OBJ_MINVENT     4               /* object in a monster inventory */
00051 #define OBJ_MIGRATING   5               /* object sent off to another level */
00052 #define OBJ_BURIED      6               /* object buried */
00053 #define OBJ_ONBILL      7               /* object on shk bill */
00054 #define NOBJ_STATES     8
00055         xchar timed;            /* # of fuses (timers) attached to this obj */
00056 
00057         Bitfield(cursed,1);
00058         Bitfield(blessed,1);
00059         Bitfield(unpaid,1);     /* on some bill */
00060         Bitfield(no_charge,1);  /* if shk shouldn't charge for this */
00061         Bitfield(known,1);      /* exact nature known */
00062         Bitfield(dknown,1);     /* color or text known */
00063         Bitfield(bknown,1);     /* blessing or curse known */
00064         Bitfield(rknown,1);     /* rustproof or not known */
00065 
00066         Bitfield(oeroded,2);    /* rusted/burnt weapon/armor */
00067         Bitfield(oeroded2,2);   /* corroded/rotted weapon/armor */
00068 #define greatest_erosion(otmp) (int)((otmp)->oeroded > (otmp)->oeroded2 ? (otmp)->oeroded : (otmp)->oeroded2)
00069 #define MAX_ERODE 3
00070 #define orotten oeroded         /* rotten food */
00071 #define odiluted oeroded        /* diluted potions */
00072 #define norevive oeroded2
00073         Bitfield(oerodeproof,1); /* erodeproof weapon/armor */
00074         Bitfield(olocked,1);    /* object is locked */
00075 #define sokoprize olocked       /* special flag for sokoban prize */
00076 #define orecursive olocked      /* special flag for preventing recursive calls */
00077         Bitfield(obroken,1);    /* lock has been broken */
00078         Bitfield(otrapped,1);   /* container is trapped */
00079                                 /* or accidental tripped rolling boulder trap */
00080 #define opoisoned otrapped      /* object (weapon) is coated with poison */
00081 
00082         Bitfield(recharged,3);  /* number of times it's been recharged */
00083         Bitfield(lamplit,1);    /* a light-source -- can be lit */
00084 #ifdef INVISIBLE_OBJECTS
00085         Bitfield(oinvis,1);     /* invisible */
00086 #endif
00087         Bitfield(greased,1);    /* covered with grease */
00088         Bitfield(oattached,2);  /* obj struct has special attachment */
00089 #define OATTACHED_NOTHING 0
00090 #define OATTACHED_MONST   1     /* monst struct in oextra */
00091 #define OATTACHED_M_ID    2     /* monst id in oextra */
00092 #define OATTACHED_UNUSED3 3
00093 
00094         Bitfield(in_use,1);     /* for magic items before useup items */
00095         Bitfield(bypass,1);     /* mark this as an object to be skipped by bhito() */
00096         Bitfield(was_thrown,1); /* thrown by the hero since last picked up */
00097         Bitfield(odrained,1);   /* drained corpse */
00098         Bitfield(was_dropped,1); /* dropped deliberately by the hero */
00099         /* 3 free bits */
00100 
00101         int     corpsenm;       /* type of corpse is mons[corpsenm] */
00102 #define leashmon  corpsenm      /* gets m_id of attached pet */
00103 #define spestudied corpsenm     /* # of times a spellbook has been studied */
00104 #define fromsink  corpsenm      /* a potion from a sink */
00105 
00106 #ifdef RECORD_ACHIEVE
00107         xchar record_achieve_special;
00108 #endif
00109 
00110         unsigned oeaten;        /* nutrition left in food, if partly eaten */
00111         long age;               /* creation date */
00112 
00113         uchar onamelth;         /* length of name (following oxlth) */
00114         short oxlth;            /* length of following data */
00115         /* in order to prevent alignment problems oextra should
00116            be (or follow) a long int */
00117         long owornmask;
00118         long oextra[1];         /* used for name of ordinary objects - length
00119                                    is flexible; amount for tmp gold objects */
00120 };
00121 
00122 #define newobj(xl)      (struct obj *)alloc((unsigned)(xl) + sizeof(struct obj))
00123 #define ONAME(otmp)     (((char *)(otmp)->oextra) + (otmp)->oxlth)
00124 
00125 /* Weapons and weapon-tools */
00126 /* KMH -- now based on skill categories.  Formerly:
00127  *      #define is_sword(otmp)  (otmp->oclass == WEAPON_CLASS && \
00128  *                       objects[otmp->otyp].oc_wepcat == WEP_SWORD)
00129  *      #define is_blade(otmp)  (otmp->oclass == WEAPON_CLASS && \
00130  *                       (objects[otmp->otyp].oc_wepcat == WEP_BLADE || \
00131  *                        objects[otmp->otyp].oc_wepcat == WEP_SWORD))
00132  *      #define is_weptool(o)   ((o)->oclass == TOOL_CLASS && \
00133  *                       objects[(o)->otyp].oc_weptool)
00134  *      #define is_multigen(otyp) (otyp <= SHURIKEN)
00135  *      #define is_poisonable(otyp) (otyp <= BEC_DE_CORBIN)
00136  */
00137 #define is_blade(otmp)  (otmp->oclass == WEAPON_CLASS && \
00138                          objects[otmp->otyp].oc_skill >= P_DAGGER && \
00139                          objects[otmp->otyp].oc_skill <= P_SABER)
00140 #define is_axe(otmp)    ((otmp->oclass == WEAPON_CLASS || \
00141                          otmp->oclass == TOOL_CLASS) && \
00142                          objects[otmp->otyp].oc_skill == P_AXE)
00143 #define is_pick(otmp)   ((otmp->oclass == WEAPON_CLASS || \
00144                          otmp->oclass == TOOL_CLASS) && \
00145                          objects[otmp->otyp].oc_skill == P_PICK_AXE)
00146 #define is_sword(otmp)  (otmp->oclass == WEAPON_CLASS && \
00147                          objects[otmp->otyp].oc_skill >= P_SHORT_SWORD && \
00148                          objects[otmp->otyp].oc_skill <= P_SABER)
00149 #define is_pole(otmp)   ((otmp->oclass == WEAPON_CLASS || \
00150                         otmp->oclass == TOOL_CLASS) && \
00151                          (objects[otmp->otyp].oc_skill == P_POLEARMS || \
00152                          objects[otmp->otyp].oc_skill == P_LANCE))
00153 #define is_spear(otmp)  (otmp->oclass == WEAPON_CLASS && \
00154                          objects[otmp->otyp].oc_skill >= P_SPEAR && \
00155                          objects[otmp->otyp].oc_skill <= P_JAVELIN)
00156 #define is_launcher(otmp)       (otmp->oclass == WEAPON_CLASS && \
00157                          objects[otmp->otyp].oc_skill >= P_BOW && \
00158                          objects[otmp->otyp].oc_skill <= P_CROSSBOW)
00159 #define is_ammo(otmp)   ((otmp->oclass == WEAPON_CLASS || \
00160                          otmp->oclass == GEM_CLASS) && \
00161                          objects[otmp->otyp].oc_skill >= -P_CROSSBOW && \
00162                          objects[otmp->otyp].oc_skill <= -P_BOW)
00163 #define ammo_and_launcher(otmp,ltmp) \
00164                          (is_ammo(otmp) && (ltmp) && \
00165                          objects[(otmp)->otyp].oc_skill == -objects[(ltmp)->otyp].oc_skill)
00166 #define is_missile(otmp)        ((otmp->oclass == WEAPON_CLASS || \
00167                          otmp->oclass == TOOL_CLASS) && \
00168                          objects[otmp->otyp].oc_skill >= -P_BOOMERANG && \
00169                          objects[otmp->otyp].oc_skill <= -P_DART)
00170 #define is_weptool(o)   ((o)->oclass == TOOL_CLASS && \
00171                          objects[(o)->otyp].oc_skill != P_NONE)
00172 #define bimanual(otmp)  ((otmp->oclass == WEAPON_CLASS || \
00173                          otmp->oclass == TOOL_CLASS) && \
00174                          objects[otmp->otyp].oc_bimanual)
00175 #define is_multigen(otmp)       (otmp->oclass == WEAPON_CLASS && \
00176                          objects[otmp->otyp].oc_skill >= -P_SHURIKEN && \
00177                          objects[otmp->otyp].oc_skill <= -P_BOW)
00178 #define is_poisonable(otmp)     (otmp->oclass == WEAPON_CLASS && \
00179                          objects[otmp->otyp].oc_skill >= -P_SHURIKEN && \
00180                          objects[otmp->otyp].oc_skill <= -P_BOW)
00181 #define uslinging()     (uwep && objects[uwep->otyp].oc_skill == P_SLING)
00182 
00183 /* Armor */
00184 #define is_shield(otmp) (otmp->oclass == ARMOR_CLASS && \
00185                          objects[otmp->otyp].oc_armcat == ARM_SHIELD)
00186 #define is_helmet(otmp) (otmp->oclass == ARMOR_CLASS && \
00187                          objects[otmp->otyp].oc_armcat == ARM_HELM)
00188 #define is_boots(otmp)  (otmp->oclass == ARMOR_CLASS && \
00189                          objects[otmp->otyp].oc_armcat == ARM_BOOTS)
00190 #define is_gloves(otmp) (otmp->oclass == ARMOR_CLASS && \
00191                          objects[otmp->otyp].oc_armcat == ARM_GLOVES)
00192 #define is_cloak(otmp)  (otmp->oclass == ARMOR_CLASS && \
00193                          objects[otmp->otyp].oc_armcat == ARM_CLOAK)
00194 #define is_shirt(otmp)  (otmp->oclass == ARMOR_CLASS && \
00195                          objects[otmp->otyp].oc_armcat == ARM_SHIRT)
00196 #define is_suit(otmp)   (otmp->oclass == ARMOR_CLASS && \
00197                          objects[otmp->otyp].oc_armcat == ARM_SUIT)
00198 #define is_elven_armor(otmp)    ((otmp)->otyp == ELVEN_LEATHER_HELM\
00199                                 || (otmp)->otyp == ELVEN_MITHRIL_COAT\
00200                                 || (otmp)->otyp == ELVEN_CLOAK\
00201                                 || (otmp)->otyp == ELVEN_SHIELD\
00202                                 || (otmp)->otyp == ELVEN_BOOTS)
00203 #define is_orcish_armor(otmp)   ((otmp)->otyp == ORCISH_HELM\
00204                                 || (otmp)->otyp == ORCISH_CHAIN_MAIL\
00205                                 || (otmp)->otyp == ORCISH_RING_MAIL\
00206                                 || (otmp)->otyp == ORCISH_CLOAK\
00207                                 || (otmp)->otyp == URUK_HAI_SHIELD\
00208                                 || (otmp)->otyp == ORCISH_SHIELD)
00209 #define is_dwarvish_armor(otmp) ((otmp)->otyp == DWARVISH_IRON_HELM\
00210                                 || (otmp)->otyp == DWARVISH_MITHRIL_COAT\
00211                                 || (otmp)->otyp == DWARVISH_CLOAK\
00212                                 || (otmp)->otyp == DWARVISH_ROUNDSHIELD)
00213 #define is_gnomish_armor(otmp)  (FALSE)
00214 
00215                                 
00216 /* Eggs and other food */
00217 #define MAX_EGG_HATCH_TIME 200  /* longest an egg can remain unhatched */
00218 #define stale_egg(egg)  ((monstermoves - (egg)->age) > (2*MAX_EGG_HATCH_TIME))
00219 #define ofood(o) ((o)->otyp == CORPSE || (o)->otyp == EGG || (o)->otyp == TIN)
00220 #define polyfodder(obj) (ofood(obj) && \
00221                          pm_to_cham((obj)->corpsenm) != CHAM_ORDINARY)
00222 #define mlevelgain(obj) (ofood(obj) && (obj)->corpsenm == PM_WRAITH)
00223 #define mhealup(obj)    (ofood(obj) && (obj)->corpsenm == PM_NURSE)
00224 #define drainlevel(corpse) (mons[(corpse)->corpsenm].cnutrit*4/5)
00225 
00226 /* Containers */
00227 #define carried(o)      ((o)->where == OBJ_INVENT)
00228 #define mcarried(o)     ((o)->where == OBJ_MINVENT)
00229 #define Has_contents(o) (/* (Is_container(o) || (o)->otyp == STATUE) && */ \
00230                          (o)->cobj != (struct obj *)0)
00231 #define Is_container(o) ((o)->otyp >= LARGE_BOX && (o)->otyp <= BAG_OF_TRICKS)
00232 #define Is_box(otmp)    (otmp->otyp == LARGE_BOX || otmp->otyp == CHEST || \
00233                          otmp->otyp == IRON_SAFE)
00234 #define Is_mbag(otmp)   (otmp->otyp == BAG_OF_HOLDING || \
00235                          otmp->otyp == BAG_OF_TRICKS)
00236 
00237 #define Is_sokoprize(otmp)      ((otmp)->sokoprize && !Is_box(otmp))
00238 
00239 /* dragon gear */
00240 #define Is_dragon_scales(idx)   (idx >= GRAY_DRAGON_SCALES && \
00241                                  idx <= YELLOW_DRAGON_SCALES)
00242 #define Is_dragon_mail(idx)     (idx >= GRAY_DRAGON_SCALE_MAIL && \
00243                                  idx <= YELLOW_DRAGON_SCALE_MAIL)
00244 #define Is_dragon_armor(idx)    (Is_dragon_scales(idx) || Is_dragon_mail(idx))
00245 #define Is_gold_dragon_armor(idx)       (Is_dragon_armor(idx) && \
00246                                          (OBJ_DESCR(objects[idx])) && \
00247                                          (!strncmp(OBJ_DESCR(objects[idx]), "gold ", 5)))
00248 #define Dragon_scales_to_mail(idx) (idx - GRAY_DRAGON_SCALES + GRAY_DRAGON_SCALE_MAIL)
00249 #define Dragon_mail_to_scales(idx) (idx - GRAY_DRAGON_SCALE_MAIL + GRAY_DRAGON_SCALES)
00250 #define Dragon_scales_to_pm(obj) &mons[PM_GRAY_DRAGON + (obj)->otyp \
00251                                        - GRAY_DRAGON_SCALES]
00252 #define Dragon_mail_to_pm(obj)  &mons[PM_GRAY_DRAGON + (obj)->otyp \
00253                                       - GRAY_DRAGON_SCALE_MAIL]
00254 #define Dragon_to_scales(pm)    (GRAY_DRAGON_SCALES + (pm - mons))
00255 
00256 /* Elven gear */
00257 #define is_elven_weapon(otmp)   ((otmp)->otyp == ELVEN_ARROW\
00258                                 || (otmp)->otyp == ELVEN_SPEAR\
00259                                 || (otmp)->otyp == ELVEN_DAGGER\
00260                                 || (otmp)->otyp == ELVEN_SHORT_SWORD\
00261                                 || (otmp)->otyp == ELVEN_BROADSWORD\
00262                                 || (otmp)->otyp == ELVEN_BOW)
00263 #define is_elven_obj(otmp)      (is_elven_armor(otmp) || is_elven_weapon(otmp))
00264 
00265 /* Orcish gear */
00266 #define is_orcish_obj(otmp)     (is_orcish_armor(otmp)\
00267                                 || (otmp)->otyp == ORCISH_ARROW\
00268                                 || (otmp)->otyp == ORCISH_SPEAR\
00269                                 || (otmp)->otyp == ORCISH_DAGGER\
00270                                 || (otmp)->otyp == ORCISH_SHORT_SWORD\
00271                                 || (otmp)->otyp == ORCISH_BOW)
00272 
00273 /* Dwarvish gear */
00274 #define is_dwarvish_obj(otmp)   (is_dwarvish_armor(otmp)\
00275                                 || (otmp)->otyp == DWARVISH_SPEAR\
00276                                 || (otmp)->otyp == DWARVISH_SHORT_SWORD\
00277                                 || (otmp)->otyp == DWARVISH_MATTOCK)
00278 
00279 /* Gnomish gear */
00280 #define is_gnomish_obj(otmp)    (is_gnomish_armor(otmp))
00281 
00282 /* Light sources */
00283 #define Is_candle(otmp) (otmp->otyp == TALLOW_CANDLE || \
00284                          otmp->otyp == WAX_CANDLE)
00285 #define MAX_OIL_IN_FLASK 400    /* maximum amount of oil in a potion of oil */
00286 
00287 /* MAGIC_LAMP intentionally excluded below */
00288 /* age field of this is relative age rather than absolute */
00289 #define age_is_relative(otmp)   ((otmp)->otyp == BRASS_LANTERN\
00290                                 || (otmp)->otyp == OIL_LAMP\
00291                                 || (otmp)->otyp == CANDELABRUM_OF_INVOCATION\
00292                                 || (otmp)->otyp == TALLOW_CANDLE\
00293                                 || (otmp)->otyp == WAX_CANDLE\
00294                                 || (otmp)->otyp == POT_OIL)
00295 /* object can be ignited */
00296 #define ignitable(otmp) ((otmp)->otyp == BRASS_LANTERN\
00297                                 || (otmp)->otyp == OIL_LAMP\
00298                                 || (otmp)->otyp == CANDELABRUM_OF_INVOCATION\
00299                                 || (otmp)->otyp == TALLOW_CANDLE\
00300                                 || (otmp)->otyp == WAX_CANDLE\
00301                                 || (otmp)->otyp == POT_OIL)
00302 
00303 /* special stones */
00304 #define is_graystone(obj)       ((obj)->otyp == LUCKSTONE || \
00305                                  (obj)->otyp == LOADSTONE || \
00306                                  (obj)->otyp == FLINT     || \
00307                                  (obj)->otyp == TOUCHSTONE)
00308 
00309 /* misc */
00310 #ifdef KOPS
00311 #define is_flimsy(otmp)         (objects[(otmp)->otyp].oc_material <= LEATHER || \
00312                                  (otmp)->otyp == RUBBER_HOSE)
00313 #else
00314 #define is_flimsy(otmp)         (objects[(otmp)->otyp].oc_material <= LEATHER)
00315 #endif
00316 #ifdef WEBB_DISINT
00317 # define oresist_disintegration(obj) \
00318                 (objects[obj->otyp].oc_oprop == DISINT_RES || \
00319                  obj_resists(obj, 5, 50) || is_quest_artifact(obj) )
00320 # define weight_dmg(i) {  \
00321   i = (i<=100)?1:i/100; \
00322   i = rnd(i); \
00323   if(i > 6) i = 6; \
00324 }
00325 
00326 #endif
00327 /* helpers, simple enough to be macros */
00328 #define is_plural(o)    ((o)->quan > 1 || \
00329                          (o)->oartifact == ART_EYES_OF_THE_OVERWORLD)
00330 
00331 /* Flags for get_obj_location(). */
00332 #define CONTAINED_TOO   0x1
00333 #define BURIED_TOO      0x2
00334 
00335 #endif /* OBJ_H */