/* * Implementation of armours. */ #include #include "obj.h" #include "vars.h" #include "dice.h" #include "util.h" #include "pline.h" #include "format.h" #include "structs.h" #include "objtypes.h" #include "obj-armour.h" typedef struct armour ARMOUR; /* * Private data for a piece of armour. Consists of flags (currently * indicating whether its plusses are known), its armour class (innate * plusses to defense), its bonus (plusses if positive, minuses if * negative), a string for passing to roll() for its defense, and a * backpointer to the monster, if any, that's wearing it. */ struct armour { unsigned int flags; #define AF_KNOWN 0x00000001 const char *roll_type; int plus; char *roll_plus; MONST *wornby; } ; /* * Return the ARMOUR for an OBJ (or, if the OBJ isn't armour, panic). */ static ARMOUR *armour_for_obj(OBJ *o) { if (objtypes[o->type].class != OC_ARMOUR) panic("non-armour where armour needed"); return(o->private); } /* * The new method for armour. */ static OBJ *new_armour(int type, OBJ *o) { ARMOUR *a; a = malloc(sizeof(ARMOUR)); a->flags = 0; a->roll_type = objtypes[type].name2; a->plus = 0; a->roll_plus = 0; a->wornby = 0; reset_roll_string(&a->roll_plus,a->plus); o->private = a; return(o); } /* * The old method for armour. */ static void old_armour(OBJ *o) { ARMOUR *a; a = armour_for_obj(o); free(a->roll_plus); free(a); } /* * Armour-specific format conditionals. * * K - does this armour have its plusses known? * * W - is this armour currently being worn? */ static int fmt_cond_armour(char ch, INVOBJ *io) { switch (ch) { case 'K': return(armour_for_obj(io->v[0])->flags&AF_KNOWN); break; case 'W': return(!!armour_for_obj(io->v[0])->wornby); break; } panic("invalid conditional +%c for armour",ch); } /* * Armour-specific formats. * * P - this armour's plusses (or minuses). */ static void fmt_spec_armour(FILE *f, char ch, INVOBJ *io) { switch (ch) { case 'P': fprintf(f,"%+d",armour_for_obj(io->v[0])->plus); break; default: panic("invalid format %%+%c for armour",ch); break; } } /* * Return true iff a piece of armour has its plusses known. */ static int identified_armour(INVOBJ *io) { return(armour_for_obj(io->v[0])->flags & AF_KNOWN); } /* * Identify a piece of armour. */ static INVOBJ *identify_armour(INVOBJ *io) { armour_for_obj(io->v[0])->flags |= AF_KNOWN; return(io); } /* * The OBJOPS for armour. */ #define format_armour std_format #define collapsible_armour never_collapsible #define identical_armour never_identical #define split_armour std_split #define moved_armour noop_moved OBJOPS objops_armour = OBJOPS_INIT(armour); /* * Return the defense bonus for a piece of armour. This is a random * number suitable for directly adding to the wearer's innate defense * roll in the wearer's defense method. */ int armour_def_bonus(OBJ *o) { ARMOUR *a; if (! o) return(0); a = armour_for_obj(o); return(roll(a->roll_type)+roll(a->roll_plus)); } /* * Test whether a piece of armour is being worn (true) or not (false). */ int armour_being_worn(OBJ *o) { return(!!armour_for_obj(o)->wornby); } /* * Make the monster wear the armour. */ void armour_wear(MONST *m, OBJ *o) { ARMOUR *a; a = armour_for_obj(o); if (a->wornby) panic("wearing already-worn armour"); if (m->armour) panic("monster is already wearing armour"); m->armour = o; a->wornby = m; } /* * Make the monster take the armour off. */ void armour_take_off(MONST *m, OBJ *o) { ARMOUR *a; if (m->armour != o) panic("taking off armour monster isn't wearing"); a = armour_for_obj(o); if (a->wornby != m) panic("armour wornby pointer wrong"); m->armour = 0; a->wornby = 0; }