#ifndef _STRUCTS_H_cfb9f6fa_ #define _STRUCTS_H_cfb9f6fa_ /* * Data structure definitions, including relevant constants. */ #include #include #include "param.h" /* * Levels are `named' by numbers. These are the numbers for the * special levels: the elemental planes, the underworld, and hell. */ #define L_EARTH (-1) #define L_AIR (-2) #define L_FIRE (-3) #define L_WATER (-4) #define L_UNDERWORLD (-5) #define L_HELL (-6) // The (algebraeically) lowest elemental level number. #define L__FIRSTELEM (-4) // The number of elemental levels. #define L__NELEM 4 // Negative of the most-negative special level number. #define LEVEL_OFFSET 6 // Total number of levels. #define N_LEVELS (DUNGEON_LEVELS+LEVEL_OFFSET) /* * Time. Time is nominally measured in "ticks", whose size is * unspecified. Since we want to be able to represent less than a * tick (eg, for hasted monsters), we also keep tick fractions. We do * this using fixed-point arithmetic; a TIME is just a 64-bit integer, * of which the low 32 bits are the fractional part and the high 32 * the integer part. TIMESCALE is the factor by which a tick count * must be multiplied to turn it into a TIME. */ typedef unsigned long long int TIME; #define TIMESCALE (0x100000000ULL) /* * An inventory type. There are two types of inventories: those * carried by monsters (incuding the player) and those in locations. * IT_MON corresponds to the former, IT_LOC to the latter. */ typedef enum { IT_MON = 1, IT_LOC, } INVTYPE; /* * The possible kinds of traps. */ typedef enum { TRAP_ARROW = 1, TRAP_TRAPDOOR, TRAP_PIT, } TRAPTYPE; /* * PIK = Prob Init Kind. These are used to describe probabilities of, * eg, monster spawning. See PROBINIT, below. */ typedef enum { PIK_END = 1, PIK_LEV, } PIKIND; /* * The possible kinds of location. * * ROCK is a completely undug cell. WALL is a cell forming the * boundary between dug and undug. SDOOR is a secret door the player * is not yet aware exists. CAVE is dug space - most of the * player-accessible cells are CAVE. GATE is a gate between planes. * DOOR is, well, a door. * * Some of these have subtypes (for example, WALL has variants for * horizontal, vertical, and corners). These subtypes are recorded * separately - see LOC, below. */ typedef enum { LOC_ROCK = 1, LOC_WALL, LOC_SDOOR, LOC_CAVE, LOC_GATE, LOC_DOOR, } LOCTYPE; /* * These are the subtypes of LOC_CAVE. JUSTCAVE is plain old boring * empthy space; STARS_U and STAIRS_D are stairs up and down. */ typedef enum { LOC_JUSTCAVE = 1, LOC_STAIRS_U, LOC_STAIRS_D, } CAVETYPE; /* * These are the subtypes of LOC_GATE. Which level the "in" and "out" * gates link to depends on the level the gate appears on. */ typedef enum { /* subtypes of LOC_GATE */ LOC_GATE_IN = 1, LOC_GATE_OUT, } GATETYPE; typedef struct invobj INVOBJ; typedef struct level LEVEL; typedef struct loc LOC; typedef struct monops MONOPS; typedef struct monst MONST; typedef struct montype MONTYPE; typedef struct mtinfo MTINFO; typedef struct obj OBJ; typedef struct objops OBJOPS; typedef struct objtype OBJTYPE; typedef struct shop SHOP; typedef struct trail TRAIL; typedef struct trap TRAP; typedef struct invent INVENT; typedef struct xy XY; typedef struct jmp JMP; typedef struct probinit PROBINIT; /* * These are used as part of SIGINT handling. See signals.c. */ struct jmp { jmp_buf b; } ; /* * Used in various places for coordinate pairs, either absolute or * relative. */ struct xy { short int x; short int y; } ; /* * An inventory list. This consists of the chain of objects (inv), a * type field indicating what kind of place the inventory is (type - * see INVOBJ above), and a type-specific field describing exactly * where the inventory is (u.m and u.l); */ struct invent { INVOBJ *inv; INVTYPE type; union { MONST *m; LOC *l; } u; } ; /* * A location in a dungeon level. This consists of coordinates (x and * y), a location type (type - see LOCTYPE above), and type-specific * data (orientation for WALL, orientation and open/closed state for * DOOR, subtype for CAVE and GATE), some flag bits, tracking data, * contents (a potential inventory of objects and a potential * monster), a link to the "other" location (for, eg, gates), and a * backpointer to the level this cell is part of. */ struct loc { unsigned char x; unsigned char y; LOCTYPE type; union { unsigned char walldoor; #define LOC_WALL_H 1 #define LOC_WALL_V 2 #define LOC_UWALL 0 #define LOC_HWALL (LOC_WALL_H) #define LOC_VWALL (LOC_WALL_V) #define LOC_TWALL (LOC_WALL_H|LOC_WALL_V) #define LOC_DOOR_CLOSED 0 #define LOC_DOOR_OPEN 4 #define LOC_CHDOOR (LOC_DOOR_CLOSED|LOC_HWALL) #define LOC_CVDOOR (LOC_DOOR_CLOSED|LOC_VWALL) #define LOC_OHDOOR (LOC_DOOR_OPEN|LOC_HWALL) #define LOC_OVDOOR (LOC_DOOR_OPEN|LOC_VWALL) CAVETYPE cavetype; GATETYPE gatetype; } ; unsigned int flags; #define LF_FLAG 0x00000001 #define LF_FLAGB 0x00000002 #define LF_VISIBLE 0x00000004 #define LF_SHOP 0x00000008 #define LF_VAULT 0x00000010 #define LF__PERMANENT (LF_SHOP|LF_VAULT) #define TRACK_DUMB 0 #define TRACK_SMART 1 #define NTRACKTYPES 2 LOC *tracks[NTRACKTYPES]; TIME tracktime[NTRACKTYPES]; unsigned int exitdist; INVENT objs; MONST *monst; LOC *to; LEVEL *on; } ; /* * A shop. Shops are kept in a linked list per level; besides the list * link, a shop knows what level it's on, its shopkeeper's name, a * type (some shops can specialize in, eg, scrolls or wands), a * position, size, and entrance door location. */ struct shop { SHOP *link; LEVEL *on; const char *shkname; int type; #define SHOP_BASETYPE 1 #define SHOP_TYPE_GENERAL 1 #define SHOP_NTYPES 1 XY pos; XY size; XY door; } ; /* * A trail left by a monster. Just a linked list of LOCs. These also * occasionally get abused for other linked lists of LOCs, but that * really is an abuse of the type. */ struct trail { TRAIL *link; LOC *loc; } ; /* * A trap. Traps are kept in a per-level linked list; besides the list * link, a trap has just a type and a location. */ struct trap { TRAP *link; TRAPTYPE type; LOC *loc; } ; /* * A dungeon level. A level knows its level number, its index in the * array of levels, a short name, a long name, some flags, an offset * so that the dungeon does not have to have all its levels' bounding * boxes line up vertically, an indication of how good visibility is, * counts of various things on the level, the list heads for shops and * trap, pointers to the levels above and below it (if any), the gates * in and out (if any), and the array of LOCs making it up. */ struct level { int levelno; int index; const char *shortname; const char *longname; int flags; #define LVF_WRAPAROUND 0x00000001 #define LVF_DRIFT 0x00000002 #define LVF_SEEN 0x00000004 XY off; int visibility; int ncorr; int nstup; int ncave; int nmonst; int nunflagged; SHOP *shops; TRAP *traps; LEVEL *up; LEVEL *down; LOC *gate_ib; LOC *gate_ob; LOC cells[LEV_X][LEV_Y]; } ; /* * A monster type. There's one of these per monster type. That is, * there is one for you (the player), one for rats, etc. See also * MTINFO, below. */ struct montype { const char *name; char letter; MTINFO *info; } ; /* * Used to describe per-level probabilities, eg of monaster spawning * (so that tough monsters don't spawn on early levels). */ struct probinit { PIKIND kind; int level; int nlevel; int prob; } ; #define PROBEND() { PIK_END } #define PROBLEV(lev,prob) { PIK_LEV, (lev), 1, (prob) } #define PROBLEVS(lev,n,prob) { PIK_LEV, (lev), (n), (prob) } #define PROBELEM(prob) { PIK_LEV, L__FIRSTELEM, L__NELEM, (prob) } #define PROBALL(prob) { PIK_LEV, -LEVEL_OFFSET, N_LEVELS, (prob) } /* * Monster type info. This summarizes almost everything about a * monster type. The only things it doesn't cover are those stored in * MONTYPE, above. * * The reason MONTYPE and MTINFO are split, rather than being a single * struct, is that MONTYPEs are generated mechanically from monlist * and just include a poiter to the MTINFO. * * Here, we have the probability vector (probinit, which get processed * into probs) for spawning, a call (new) to set up a new instance of * the monster given the allocated and cleared MONST (it returns a * pointer so that it can, for example, destroy the monster), and a * function to perform operations on the monster (monctl). */ struct mtinfo { PROBINIT *probinit; MONST *(*new)(MONST *, LEVEL *); void (*monctl)(MONST *, int, ...); #define MCTL_AGGR 1 int *probs; } ; /* * The operations vector for a monster. There is usually one of these * per monster type, but some monster types may have multiple ops * vectors and switch among them based on internal conditions. * * The operations: * * tick - it's the monster's turn to move; let it take its move. * * bemoved - the monster has been moved; let it adjust its internal * data structures, if appropriate. * * name - return the monster's name, suitable for contexts where simple * words begin with a lowercase letter (eg, "You hit %s"). * * Name - return the monster's name, suitable for contexts where simple * words begin with an uppercase letter (eg, "%s hits you"). * * attack - return a number giving the strength of the monster's * attack. This is the to-hit roll, to put it loosely. The higher * the return value, the likelier the attack is to hit. * * defend - return a number giving the strength of the monster's * defense. This will normally roll dice based on armour. The higher * the return value, the stronger the defense. * * givedamage - return the amount of damage done by a hit by this * monster. This is the damage roll. * * takedamage - The monster has been hit; take the damage and do * anything appropriate in consequence. This usually will point to * std_takedamage, but monsters with DR, for example, may do something * special here. * * kill - The monster has been reduced to 0hp or less; do anything * appropriate in consequence. This usually points to std_kill, which * just destroys the monster and drops its inventory, but monsters for * which something special needs to happen can override this. (For * example, the player-avatar monster does this, because death for * that monster means Game Over.) * * destroy - The monster is gone; clean up any associated data * structures. This usually points to std_destroyi, which just * free()s the argument, but if the monster has private data, this is * the hook for freeing it up. */ struct monops { void (*tick)(MONST *); void (*bemoved)(MONST *); const char *(*name)(MONST *); const char *(*Name)(MONST *); int (*attack)(MONST *); int (*defend)(MONST *); int (*givedamage)(MONST *, int); int (*takedamage)(MONST *, int); void (*kill)(MONST *); void (*destroy)(MONST *); } ; /* * A monster. This consists of the type, the on-screen symbol for it, * current and max HP, its healing rate, a bunch of flags, its speed * (as a time-between-actions delta), its age in actions (the number * of times its tick function has been called, that is, the number of * times it's had a chance to act), the TIME at which it was created, * the ID of the fuse for its actions, where you were when the monster * last saw you (valid only when MF_SAWYOU is set in flags), a private * data structure pointer, a link the next monster (all monsters are * kept in a linked list), the monster's ops vector, its inventory, * its previous location, and its current location. */ struct monst { MONTYPE *type; char symbol; int hp; int maxhp; int heal; int flags; #define MF_DEAD 0x00000001 #define MF_ASLEEP 0x00000002 #define MF_INVISIBLE 0x00000004 #define MF_SEE_INVISIBLE 0x00000008 #define MF_TELEPATHIC 0x00000010 #define MF_SAWYOU 0x00000020 #define MF_TRACKING 0x00000040 TIME speed; int age; TIME created; int fuseid; XY you; char *private; MONST *link; MONOPS *ops; INVENT invent; LOC *lastloc; LOC *loc; } ; /* * An object in an inventory. This consists of a link to the next * INVOBJ in the inventory (link), a backpointer to the INVENT it * belongs to (inv), its index within the inventory (xwi), the number * of objects displayed (dispn, eg, 25 in "25 arrows"), and a vector * (v) and count (n) of the objects proper making up this inventory * object. * * The reason there can be multiple objects in a single inventory * object is that unidentified objects may be different in important * ways but indistinguishable to the player, so they have to be kept * separate but displayed as if they were identical. (For example, if * the player is carrying 10 unidentified +0,+0 arrows and picks up 3 * unidentified +1,+2 arrows, they will display as "13 arrows" until * and unless something happens to distinguish them like using a * scroll of identify on them.) * * Note that objects of different types never occur together in a * single INVOBJ. */ struct invobj { INVOBJ *link; INVENT *inv; int xwi; int dispn; int n; OBJ **v; } ; /* * An object proper. This is just a type, a count, and type-specific * private data. */ struct obj { int type; int number; void *private; } ; /* * The ops vector for an object type. THe methods here are * * new - set up a new object of this type. The object is passed in and * returned. The first argument is the object type (so that the same * new function can be used for multiple types). * * old - free up any private data the object has. This is called just * before free()ing the OBJ. * * format - print, to the FILE *, the text for an INVOBJ of this type. * This generates a string suitable for displaying in, eg, an * inventory listing. * * fmt_cond - handles type-specific conditionals in description * strings. See format.c for more. * * fmt_spec - handles type-specific format specifiers in description * strings. See format.c for more. * * collapsible - decides whether two OBJs of this type should be merged * in an inventory slot. For example, objects with plusses will * usually test whether either object is identified, and, if both are, * whether the plusses are identical. * * identical - decides whether two OBJs of this type should be * considered completely identical. * * split - turn a plural OBJ of this type into two OBJs, with a given * number of them in the new OBJ. The new OBJ is returned. * * identified - returns whether an INVOBJ of this type is identified. * * identify - identifies an INVOBJ of this type, returning a * (potentially multi-entry) INVOBJ list it turns into. */ struct objops { OBJ *(*new)(int, OBJ *); void (*old)(OBJ *); void (*format)(FILE *, INVOBJ *); int (*fmt_cond)(char, INVOBJ *); void (*fmt_spec)(FILE *, char, INVOBJ *); int (*collapsible)(OBJ *, OBJ *); int (*identical)(OBJ *, OBJ *); OBJ *(*split)(OBJ *, int); int (*identified)(INVOBJ *); INVOBJ *(*identify)(INVOBJ *); } ; /* * An object type. These are the next level of granularity after * object class. Thus, for example, there is the object class * "potion" (OC_POTION), but there is the OBJTYPE "potion of healing". * * There are three name strings (typically name is the function, name2 * is the when-unidentified description, and name3 is "a" or "an" * depending on name2), a format string used for generating inventory * strings, the object's class, the symbol used for display, the ops * vector, a flags field, and a player-specified identifier. */ struct objtype { const char *name; const char *name2; const char *name3; const char *format; int class; char sym; OBJOPS *ops; unsigned int flags; #define OTF_KNOWN 0x00000001 char *called; } ; #endif