/* ************************************************************************
* File: utils.h EmpireMUD AD 1.0 *
* Usage: header file: utility macros and prototypes of utility funcs *
* *
* All rights reserved. See license.doc for complete information. *
* *
* Code base by Paul Clarke. EmpireMUD Project, a tbgMUD Production. *
* Based upon CircleMUD 3.0, beta patch level 17, by Jeremy Elson. *
* *
* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. *
************************************************************************ */
/* external declarations and prototypes **********************************/
/* Log information */
extern FILE *logfile;
#define log basic_mud_log
/* public functions in utils.c */
char *str_dup(const char *source);
int str_cmp(const char *arg1, const char *arg2);
extern bool str_str(const char *arg1, const char *arg2);
int strn_cmp(const char *arg1, const char *arg2, int n);
void basic_mud_log(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
int touch(const char *path);
void syslog(int level, bool file, const char *str, ...);
void mortlog(Creature ch, const char *str, ...);
int number(int from, int to);
int dice(int number, int size);
int ww_dice(int num, int diff);
void sprintbit(bitvector_t vektor, const char *names[], char *result, bool space);
void sprinttype(int type, const char *names[], char *result);
int get_line(FILE *fl, char *buf);
int get_filename(char *orig_name, char *filename, int mode);
struct time_info_data *age(Creature ch);
int num_pc_in_room(Room room);
void save_char(Creature ch, room_rnum load_room);
#define SAVE_CHAR(ch) save_char((ch), (ch)->in_room != NOWHERE ? (ch)->in_room : GET_LOADROOM(ch) != NOWHERE ? GET_LOADROOM(ch) : NOWHERE)
extern struct reboot_data reboot;
/* resources */
void extract_resources(Creature ch, Resource list[], bool ground);
void give_resources(Creature ch, Resource list[], bool split);
extern int get_total_resources(Resource list[]);
extern int get_amount_of_resource(Resource list[], obj_vnum vnum);
extern bool has_resources(Creature ch, Resource list[], bool ground);
/* undefine MAX and MIN so that our macros are used instead */
#ifdef MAX
#undef MAX
#endif
#define MAX(a, b) (a > b ? a : b)
#ifdef MIN
#undef MIN
#endif
#define MIN(a, b) (a < b ? a : b)
extern char *CAP(char *txt);
/* in act.informative.c */
void look_at_room_by_rnum(Creature ch, room_rnum room);
#define look_at_room(ch) look_at_room_by_rnum((ch), (ch)->in_room)
/* various constants *****************************************************/
/* get_filename() */
#define CRASH_FILE 0
#define ETEXT_FILE 1
#define ALIAS_FILE 2
#define REC_FILE 3
#define LORE_FILE 4
/*
* XXX: These constants should be configurable. See act.informative.c
* and utils.c for other places to change.
*/
/* mud-life time */
#define SECS_PER_MUD_HOUR 75
#define SECS_PER_MUD_DAY (24 * SECS_PER_MUD_HOUR)
#define SECS_PER_MUD_MONTH (30 * SECS_PER_MUD_DAY)
#define SECS_PER_MUD_YEAR (12 * SECS_PER_MUD_MONTH)
/* real-life time (remember Real Life?) */
#define SECS_PER_REAL_MIN 60
#define SECS_PER_REAL_HOUR (60 * SECS_PER_REAL_MIN)
#define SECS_PER_REAL_DAY (24 * SECS_PER_REAL_HOUR)
#define SECS_PER_REAL_YEAR (365 * SECS_PER_REAL_DAY)
/* string utils **********************************************************/
#define YESNO(a) ((a) ? "YES" : "NO")
#define ONOFF(a) ((a) ? "ON" : "OFF")
#define LOWER(c) (((c)>='A' && (c) <= 'Z') ? ((c)+('a'-'A')) : (c))
#define UPPER(c) (((c)>='a' && (c) <= 'z') ? ((c)+('A'-'a')) : (c) )
#define ISNEWL(ch) ((ch) == '\n' || (ch) == '\r')
#define IF_STR(st) ((st) ? (st) : "\0")
#define AN(string) (strchr("aeiouAEIOU", *string) ? "an" : "a")
/* memory utils **********************************************************/
#define CREATE(result, type, number) do {\
if ((number) * sizeof(type) <= 0) \
log("SYSERR: Zero bytes or less requested at %s:%d.", __FILE__, __LINE__); \
if (!((result) = (type *) calloc ((number), sizeof(type)))) \
{ log("SYSERR: malloc failure: %s: %d", __FILE__, __LINE__); abort(); } } while(0)
#define RECREATE(result, type, number) do {\
if (!((result) = (type *) realloc ((result), sizeof(type) * (number))))\
{ log("SYSERR: realloc failure: %s: %d", __FILE__, __LINE__); abort(); } } while(0)
/*
* the source previously used the same code in many places to remove an item
* from a list: if it's the list head, change the head, else traverse the
* list looking for the item before the one to be removed. Now, we have a
* macro to do this. To use, just make sure that there is a variable 'temp'
* declared as the same type as the list to be manipulated.
*/
#define REMOVE_FROM_LIST(item, head, next) \
if ((item) == (head)) \
head = (item)->next; \
else { \
temp = head; \
while (temp && (temp->next != (item))) \
temp = temp->next; \
if (temp) \
temp->next = (item)->next; \
} \
/* npc safeguard *********************************************************
*
* Accessing player specific data structures on a mobile is a very bad thing
* to do. Consider that changing these variables for a single mob will change
* it for every other single mob in the game. If we didn't specifically check
* for it, 'wimpy' would be an extremely bad thing for a mob to do, as an
* example. If you really couldn't care less, change this to a '#if 0'.
*/
#if 1
#define CHECK_PLAYER_SPECIAL(ch, var) (*(((ch)->player_specials == &dummy_mob) ? (log("SYSERR: Mob using '"#var"' at %s:%d.", __FILE__, __LINE__), &(var)) : &(var)))
#else
#define CHECK_PLAYER_SPECIAL(ch, var) (var)
#endif
#define REAL_CHAR(ch) (((ch)->desc && (ch)->desc->original) ? (ch)->desc->original : (ch))
/* basic bitvector utils *************************************************/
#define IS_SET(flag,bit) ((flag) & (bit))
#define SET_BIT(var,bit) ((var) |= (bit))
#define REMOVE_BIT(var,bit) ((var) &= ~(bit))
#define TOGGLE_BIT(var,bit) ((var) = (var) ^ (bit))
#define MOB_FLAGS(ch) ((ch)->char_specials.saved.act)
#define PLR_FLAGS(ch) (REAL_CHAR(ch)->char_specials.saved.act)
#define PRF_FLAGS(ch) CHECK_PLAYER_SPECIAL(REAL_CHAR(ch), (REAL_CHAR(ch)->player_specials->saved.pref))
#define AFF_FLAGS(ch) ((ch)->char_specials.saved.affected_by)
#define DSC_FLAGS(ch) ((ch)->char_specials.saved.dsc_flags)
#define ROOM_AFF_FLAGS(r) (world[HOME_ROOM(r)].affects)
#define INJURY_FLAGS(ch) ((ch)->char_specials.saved.injuries)
#define IS_NPC(ch) (IS_SET(MOB_FLAGS(ch), MOB_ISNPC))
#define REAL_NPC(ch) (IS_NPC(REAL_CHAR(ch)))
#define IS_MOB(ch) (IS_NPC(ch) && GET_MOB_RNUM(ch) >= 0)
#define MOB_FLAGGED(ch, flag) (IS_NPC(ch) && IS_SET(MOB_FLAGS(ch), (flag)))
#define PLR_FLAGGED(ch, flag) (!REAL_NPC(ch) && IS_SET(PLR_FLAGS(ch), (flag)))
#define AFF_FLAGGED(ch, flag) (IS_SET(AFF_FLAGS(ch), (flag)))
#define DSC_FLAGGED(ch, flag) (IS_SET(DSC_FLAGS(ch), (flag)))
#define ROOM_AFF_FLAGGED(r, flag) (IS_SET(world[(r)].affects, (flag)))
#define PRF_FLAGGED(ch, flag) (!REAL_NPC(ch) && IS_SET(PRF_FLAGS(ch), (flag)))
#define IS_INJURED(ch, flag) (IS_SET(INJURY_FLAGS(ch), (flag)))
#define EXIT_FLAGGED(exit, flag) (IS_SET((exit)->exit_info, (flag)))
#define OBJVAL_FLAGGED(obj, flag) (IS_SET(GET_OBJ_VAL((obj), 1), (flag)))
#define OBJ_FLAGGED(obj, flag) (IS_SET(GET_OBJ_EXTRA(obj), (flag)))
#define PLR_TOG_CHK(ch,flag) ((TOGGLE_BIT(PLR_FLAGS(ch), (flag))) & (flag))
#define PRF_TOG_CHK(ch,flag) ((TOGGLE_BIT(PRF_FLAGS(ch), (flag))) & (flag))
#define IS_WRITING(ch) (PLR_FLAGGED(ch, PLR_WRITING) || PLR_FLAGGED(ch, PLR_MAILING))
/* room utils ************************************************************/
extern struct weather_data weather_info;
extern bool adjacent_room_is_light(room_rnum room);
extern int shift_dir[][2];
extern int shift_room(int origin, int x, int y);
int get_season();
#define SECT(room) (world[(room)].sector_type)
#define BUILDING_TYPE(room) (SECT(room) == SECT_BUILDING ? world[(room)].type : NOWHERE)
#define ROOM_TYPE(room) (SECT(room) == SECT_INSIDE ? world[(room)].type : NOWHERE)
#define OPEN_MONUMENT_TYPE(room) (SECT(room) == SECT_MONUMENT_OPEN ? world[(room)].type : NOWHERE)
#define CLOSED_MONUMENT_TYPE(room) (SECT(room) == SECT_MONUMENT_CLOSED ? world[(room)].type : NOWHERE)
#define IS_DARK(room) ((SECT(room) != SECT_BUILDING && SECT(room) != SECT_MULTI && SECT(room) != SECT_INSIDE && !world[room].light && weather_info.sunlight == SUN_DARK) || ROOM_AFF_FLAGGED((room), ROOM_AFF_DARK))
#define IS_REAL_LIGHT(room) ((!IS_DARK(room) || SECT(room) == SECT_BUILDING || SECT(room) == SECT_MULTI || SECT(room) == SECT_INSIDE) && !ROOM_AFF_FLAGGED((room), ROOM_AFF_DARK))
#define IS_LIGHT(room) ((!IS_DARK(room) || adjacent_room_is_light(room) || SECT(room) == SECT_BUILDING || SECT(room) == SECT_MULTI || SECT(room) == SECT_INSIDE) && !ROOM_AFF_FLAGGED((room), ROOM_AFF_DARK))
#define VALID_RNUM(rnum) ((rnum) >= 0 && (rnum) <= top_of_world)
#define GET_ROOM_VNUM(rnum) ((room_vnum)(VALID_RNUM(rnum) ? world[(rnum)].number : NOWHERE))
#define EXIT(ch, door) (world[(ch)->in_room].dir_option[door])
#define HOME_ROOM(room) (world[(room)].home_room != NOWHERE && real_room(world[(room)].home_room) != NOWHERE ? real_room(world[(room)].home_room) : (room))
#define ROOM_WEIGHT(room) (world[(room)].weight)
#define ALWAYS_CLOSED(room) (SECT(room) == SECT_MONUMENT_CLOSED || BUILDING_TYPE(room) == BUILDING_MINE || BUILDING_TYPE(room) == BUILDING_MINE_COMPLEX || BUILDING_TYPE(room) == BUILDING_MOUNTAIN_OUTPOST || BUILDING_TYPE(room) == BUILDING_CLIFF_DWELLING || BUILDING_TYPE(room) == BUILDING_TUNNEL || BUILDING_TYPE(room) == BUILDING_TUNNEL2)
#define IS_HAVEN(room) (BUILDING_TYPE(room) == BUILDING_HAVEN_HOUSE || BUILDING_TYPE(room) == BUILDING_HAVEN_BURROW || BUILDING_TYPE(room) == BUILDING_HAVEN_PUEBLO || BUILDING_TYPE(room) == BUILDING_HAVEN_CAVE)
#define BUILDING_CAN_BURN(room) (BUILDING_TYPE(room) == BUILDING_HUT || BUILDING_TYPE(room) == BUILDING_TREE_HOUSE || BUILDING_TYPE(room) == BUILDING_WATCH_TOWER || BUILDING_TYPE(room) == BUILDING_TREE_COMPLEX || BUILDING_TYPE(room) == BUILDING_CABIN || BUILDING_TYPE(room) == BUILDING_HOUSE || (SECT(room) == SECT_BARRIER && !world[room].type) || BUILDING_TYPE(room) == BUILDING_GUARD_TOWER || BUILDING_TYPE(room) == BUILDING_GUARD_TOWER2)
extern bool STORE_BUILDING(room_rnum room);
extern bool CAN_USE_ROOM(Creature ch, room_rnum room, bool mode);
#define real_shift(a, b, c) (real_room(shift_room(world[a].number, b, c)))
#define shift_nw(room) real_shift(room, -1, 1)
#define shift_n(room) real_shift(room, 0, 1)
#define shift_ne(room) real_shift(room, 1, 1)
#define shift_e(room) real_shift(room, 1, 0)
#define shift_se(room) real_shift(room, 1, -1)
#define shift_s(room) real_shift(room, 0, -1)
#define shift_sw(room) real_shift(room, -1, -1)
#define shift_w(room) real_shift(room, -1, 0)
#define IS_OUTDOORS(ch) (SECT(ch->in_room) != SECT_BUILDING && SECT(ch->in_room) != SECT_INSIDE && SECT(ch->in_room) != SECT_MULTI && SECT(ch->in_room) != SECT_MONUMENT_CLOSED)
#define GET_BOAT(room) (world[HOME_ROOM(room)].boat)
#define BOAT_ROOM(room) (world[HOME_ROOM(room)].boat ? world[HOME_ROOM(room)].boat->in_room : room)
#define X_COORD(room) (world[HOME_ROOM(BOAT_ROOM(room))].number % MAP_WIDTH)
#define Y_COORD(room) (world[HOME_ROOM(BOAT_ROOM(room))].number / MAP_HEIGHT)
#define FLAT_X_COORD(room) (world[BOAT_ROOM(room)].number % MAP_WIDTH)
#define FLAT_Y_COORD(room) (world[BOAT_ROOM(room)].number / MAP_HEIGHT)
#define GET_BUILD_VALUE(room) (world[room].build_value)
#define IS_COMPLETE(room) (!world[room].res.logs && !world[room].res.sticks && !world[room].res.rocks && !world[room].res.iron)
#define IS_DISMANTLING(room) (world[room].dismantling)
#define CAN_GO(ch, door) (EXIT(ch,door) && \
(EXIT(ch,door)->to_room != NOWHERE) && \
!IS_SET(EXIT(ch, door)->exit_info, EX_CLOSED))
/* char utils ************************************************************/
/* ch */
#define GET_PFILEPOS(ch) ((ch)->pfilepos)
#define IN_ROOM(ch) ((ch)->in_room)
#define GET_WAS_IN(ch) ((ch)->was_in_room)
#define GET_AGE(ch) (IS_VAMPIRE(ch) ? GET_APPARENT_AGE(ch) : age(ch)->year)
#define GET_REAL_AGE(ch) (age(ch)->year)
#define GET_EQ(ch, i) ((ch)->equipment[i])
/* ch->player */
#define GET_PC_NAME(ch) ((ch)->player.name)
#define GET_NAME(ch) (IS_NPC(ch) ? (ch)->player.short_descr : GET_PC_NAME(ch))
#define GET_TITLE(ch) ((ch)->player.title)
#define GET_PROMPT(ch) ((ch)->player.prompt)
#define POOFIN(ch) ((ch)->player.poofin)
#define POOFOUT(ch) ((ch)->player.poofout)
#define GET_EMAIL(ch) ((ch)->player.email)
#define GET_LASTNAME(ch) ((ch)->player.lastname)
#define GET_LEVEL(ch) ((ch)->player.level)
#define GET_REAL_LEVEL(ch) (ch->desc && ch->desc->original ? GET_LEVEL(ch->desc->original) : GET_LEVEL(ch))
#define IS_IMMORTAL(ch) (GET_LEVEL(ch) >= LVL_START_IMM)
#define IS_GOD(ch) (GET_LEVEL(ch) == LVL_GOD)
#define GET_PASSWD(ch) ((ch)->player.passwd)
#define GET_HEIGHT(ch) ((ch)->player.height)
#define GET_WEIGHT(ch) ((ch)->player.weight)
#define GET_SEX(ch) ((ch)->player.sex)
#define GET_LORE(ch) ((ch)->player.lore)
/* ch->aff_abils */
#define GET_STRENGTH(ch) ((ch)->aff_abils.strength)
#define GET_DEXTERITY(ch) ((ch)->aff_abils.dexterity)
#define GET_STAMINA(ch) ((ch)->aff_abils.stamina)
#define GET_CHARISMA(ch) ((ch)->aff_abils.charisma)
#define GET_MANIPULATION(ch) ((ch)->aff_abils.manipulation)
#define GET_APPEARANCE(ch) ((ch)->aff_abils.appearance)
#define GET_PERCEPTION(ch) ((ch)->aff_abils.perception)
#define GET_INTELLIGENCE(ch) ((ch)->aff_abils.intelligence)
#define GET_WITS(ch) ((ch)->aff_abils.wits)
#define GET_CONSCIENCE(ch) ((ch)->points.conscience)
#define GET_SELF_CONTROL(ch) ((ch)->points.self_control)
#define GET_COURAGE(ch) ((ch)->points.courage)
#define GET_HUMANITY(ch) ((ch)->points.humanity)
#define GET_WILLPOWER(ch) ((ch)->points.willpower)
#define GET_MAX_WILLPOWER(ch) ((ch)->points.max_willpower)
#define GET_RAGE(ch) ((ch)->points.rage)
#define GET_MAX_RAGE(ch) ((ch)->points.max_rage)
#define GET_GNOSIS(ch) ((ch)->points.gnosis)
#define GET_MAX_GNOSIS(ch) ((ch)->points.max_gnosis)
#define GET_SOAK(ch) ((ch)->points.soak)
#define GET_BLOCK(ch) ((ch)->points.block)
#define GET_BLOOD(ch) ((ch)->points.blood)
#define GET_VAMP_BLOOD(ch) ((ch)->points.vamp_blood)
extern byte GET_MAX_BLOOD(Creature ch);
/* ch->points */
#define GET_DAMAGE(ch) ((ch)->points.damage)
#define GET_AGG_DAMAGE(ch) ((ch)->points.agg_damage)
#define GET_MOVE(ch) ((ch)->points.move)
#define GET_MAX_MOVE(ch) ((ch)->points.max_move)
#define GET_EXPERIENCE(ch) ((ch)->points.experience)
/* ch->char_specials */
#define GET_POS(ch) ((ch)->char_specials.position)
#define GET_IDNUM(ch) (REAL_CHAR(ch)->char_specials.saved.idnum)
#define IS_CARRYING_W(ch) ((ch)->char_specials.carry_weight)
#define IS_CARRYING_N(ch) ((ch)->char_specials.carry_items)
#define HUNTING(ch) ((ch)->char_specials.hunting)
#define ON_CHAIR(ch) ((ch)->char_specials.chair)
#define GET_RIDING(ch) ((ch)->char_specials.riding)
#define GET_RIDDEN_BY(ch) ((ch)->char_specials.ridden_by)
#define GET_FEEDING_FROM(ch) ((ch)->char_specials.feeding_from)
#define GET_FED_ON_BY(ch) ((ch)->char_specials.fed_on_by)
#define GET_LEADING(ch) ((ch)->char_specials.leading)
#define GET_LED_BY(ch) ((ch)->char_specials.led_by)
#define GET_PULLING(ch) ((ch)->char_specials.pulling)
#define FIGHTING(ch) ((ch)->char_specials.fighting.victim)
#define FIGHT_MODE(ch) ((ch)->char_specials.fighting.mode)
#define FIGHT_WAIT(ch) ((ch)->char_specials.fighting.wait)
#define ATTACK_BONUS(ch) ((ch)->char_specials.fighting.attack_bonus)
/* ch->player_specials->saved */
#define GET_DAYS_SINCE_BATHING(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.days_since_bathing))
#define GET_APPARENT_AGE(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.apparent_age))
#define GET_EXP_TODAY(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.exp_today))
#define GET_LANGUAGES(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.languages))
#define SET_SPEAKING(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.speaking))
#define GET_SPEAKING(ch) (GET_MORPH(ch) == MORPH_NONE || CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.speaking)) == LANG_HIGH_TONGUE ? CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.speaking)) : LANG_FERAL_SPEECH)
#define GET_EXP_CYCLE(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.exp_cycle))
#define GET_MORPH(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.morph))
#define GET_LOYALTY(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.loyalty))
#define GET_DEFECT_TIMER(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.defect_timer))
#define GET_LAST_DIR(ch) CHECK_PLAYER_SPECIAL(REAL_CHAR(ch), (REAL_CHAR(ch)->player_specials->saved.last_direction))
#define GET_RANK(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.rank))
#define GET_PLEDGE(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.pledge))
#define GET_IMM_LEV(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.imm_lev))
#define GET_COND(ch, i) CHECK_PLAYER_SPECIAL(REAL_CHAR(ch), (REAL_CHAR(ch)->player_specials->saved.conditions[(i)]))
#define GET_LOADROOM(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.load_room))
#define GET_SPARE_ROOM(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.spare_room))
#define GET_INVIS_LEV(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.invis_level))
#define GET_BAD_PWS(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.bad_pws))
#define GET_ACTION(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.action))
#define GET_ACTION_TIMER(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.action_timer))
#define GET_ACTION_ROOM(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.action_room))
#define GET_ACTION_ROTATION(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.action_rotation))
#define GET_ACTION_VNUM(ch, n) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.action_vnum[(n)]))
#define GET_SKIN(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.skin))
#define GET_HAIR(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.hair))
#define GET_EYES(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.eyes))
#define GET_RESOURCE(ch, i) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.res[i]))
#define GET_MEMORY(ch, i) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.memory[i]))
#define GET_CLAN(ch) (IS_VAMPIRE(ch) ? GET_REAL_CLAN(ch) : -1)
#define GET_REAL_CLAN(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.clan))
#define GET_GENERATION(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.generation))
#define GET_TALENT(ch, i) (REAL_NPC(ch) ? 1 : CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.talents[i])))
#define GET_SKILL(ch, i) (REAL_NPC(ch) ? 1 : CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.skills[i])))
#define GET_KNOWLEDGE(ch, i) (IS_NPC(ch) ? 1 : CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.knowledges[i])))
#define GET_TRIBE(ch) (IS_WEREWOLF(ch) ? GET_REAL_TRIBE(ch) : -1)
#define GET_REAL_TRIBE(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.tribe))
#define GET_BREED(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.breed))
#define GET_AUSPICE(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.auspice))
/* Disciplines */
#define GET_DISC(ch, disc) ((IS_VAMPIRE(ch) || IS_GHOUL(ch)) ? (ch)->player_specials->saved.discs[(disc)] : 0)
#define GET_REAL_DISC(ch, disc) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.discs[(disc)]))
#define GET_ANIMALISM(ch) ((IS_VAMPIRE(ch) || IS_GHOUL(ch)) ? (ch)->player_specials->saved.discs[DISC_ANIMALISM] : 0)
#define GET_AUSPEX(ch) ((IS_VAMPIRE(ch) || IS_GHOUL(ch)) ? (ch)->player_specials->saved.discs[DISC_AUSPEX] : 0)
#define GET_CELERITY(ch) ((IS_VAMPIRE(ch) || IS_GHOUL(ch)) ? (ch)->player_specials->saved.discs[DISC_CELERITY] : 0)
#define GET_CHIMERSTRY(ch) ((IS_VAMPIRE(ch) || IS_GHOUL(ch)) ? (ch)->player_specials->saved.discs[DISC_CHIMERSTRY] : 0)
#define GET_DEMENTATION(ch) ((IS_VAMPIRE(ch) || IS_GHOUL(ch)) ? (ch)->player_specials->saved.discs[DISC_DEMENTATION] : 0)
#define GET_DOMINATE(ch) ((IS_VAMPIRE(ch) || IS_GHOUL(ch)) ? (ch)->player_specials->saved.discs[DISC_DOMINATE] : 0)
#define GET_FORTITUDE(ch) ((IS_VAMPIRE(ch) || IS_GHOUL(ch)) ? (ch)->player_specials->saved.discs[DISC_FORTITUDE] : 0)
#define GET_MORTIS(ch) ((IS_VAMPIRE(ch) || IS_GHOUL(ch)) ? (ch)->player_specials->saved.discs[DISC_MORTIS] : 0)
#define GET_OBFUSCATE(ch) ((IS_VAMPIRE(ch) || IS_GHOUL(ch)) ? (ch)->player_specials->saved.discs[DISC_OBFUSCATE] : 0)
#define GET_OBTENEBRATION(ch) ((IS_VAMPIRE(ch) || IS_GHOUL(ch)) ? (ch)->player_specials->saved.discs[DISC_OBTENEBRATION] : 0)
#define GET_POTENCE(ch) ((IS_VAMPIRE(ch) || IS_GHOUL(ch)) ? (ch)->player_specials->saved.discs[DISC_POTENCE] : 0)
#define GET_PRESENCE(ch) ((IS_VAMPIRE(ch) || IS_GHOUL(ch)) ? (ch)->player_specials->saved.discs[DISC_PRESENCE] : 0)
#define GET_PROTEAN(ch) ((IS_VAMPIRE(ch) || IS_GHOUL(ch)) ? (ch)->player_specials->saved.discs[DISC_PROTEAN] : 0)
#define GET_QUIETUS(ch) ((IS_VAMPIRE(ch) || IS_GHOUL(ch)) ? (ch)->player_specials->saved.discs[DISC_QUIETUS] : 0)
#define GET_SERPENTIS(ch) ((IS_VAMPIRE(ch) || IS_GHOUL(ch)) ? (ch)->player_specials->saved.discs[DISC_SERPENTIS] : 0)
#define GET_THAUMATURGY(ch) ((IS_VAMPIRE(ch) || IS_GHOUL(ch)) ? (ch)->player_specials->saved.discs[DISC_THAUMATURGY] : 0)
#define GET_VICISSITUDE(ch) ((IS_VAMPIRE(ch) || IS_GHOUL(ch)) ? (ch)->player_specials->saved.discs[DISC_VICISSITUDE] : 0)
#define GET_PATH(ch, path) ((IS_VAMPIRE(ch) || IS_GHOUL(ch)) ? (ch)->player_specials->saved.paths[(path)] : 0)
#define GET_REAL_PATH(ch, path) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.paths[(path)]))
#define GET_PRIMARY_PATH(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.primary_path))
#define GET_REAL_PRIMARY_PATH(ch) ((ch)->player_specials->saved.primary_path)
#define GET_REGO_VITAE(ch) GET_PATH(ch, PATH_REGO_VITAE)
#define GET_CREO_IGNEM(ch) GET_PATH(ch, PATH_CREO_IGNEM)
#define GET_REGO_MOTUS(ch) GET_PATH(ch, PATH_REGO_MOTUS)
#define GET_REGO_TEMPESTAS(ch) GET_PATH(ch, PATH_REGO_TEMPESTAS)
#define GET_REGO_AQUAM(ch) GET_PATH(ch, PATH_REGO_AQUAM)
#define GET_REGO_ELEMENTUM(ch) GET_PATH(ch, PATH_REGO_ELEMENTUM)
#define GET_WAY_OF_LEVINBOLT(ch) GET_PATH(ch, PATH_WAY_OF_LEVINBOLT)
#define GET_PATH_OF_WARDING(ch) GET_PATH(ch, PATH_PATH_OF_WARDING)
#define IS_VAMPIRE(ch) (!IS_NPC(ch) && PLR_FLAGGED((ch), PLR_VAMPIRE))
#define IS_WEREWOLF(ch) (!IS_NPC(ch) && PLR_FLAGGED((ch), PLR_WEREWOLF))
#define IS_GHOUL(ch) (!IS_NPC(ch) && PLR_FLAGGED((ch), PLR_GHOUL))
#define IS_HUMAN(ch) (!IS_VAMPIRE(ch) && !IS_GHOUL(ch))
#define IS_HARDCORE(ch) (!IS_NPC(ch) && PLR_FLAGGED(ch, PLR_HARDCORE))
/* ch->player_specials */
#define GET_QUIT_TIMER(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->quit_timer))
#define GET_SLIT_WRIST(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->slit_wrist))
#define GET_ALIASES(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->aliases))
#define GET_LAST_TELL(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->last_tell))
#define IS_AFK(ch) (IS_NPC(ch) ? 0 : ((ch)->player_specials->isafk || ((ch->char_specials.timer * SECS_PER_MUD_HOUR / SECS_PER_REAL_MIN) >= 10)))
#define AFK_MSG(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->afk_msg))
#define AFK_MSGS(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->afk_msgs))
#define REBOOT_CONF(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->reboot_conf))
#define GET_MOVE_REGEN(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->move_regen))
#define GET_NEW_EQ_SET(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->eq_set))
#define GET_VC(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->vc))
#define GET_VC_NAME(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->vc_name))
/* ch->mob_specials */
#define MOB_TO_HIT(ch) ((ch)->mob_specials.to_hit)
#define MOB_TO_DODGE(ch) ((ch)->mob_specials.to_dodge)
#define MOB_SECTS(ch) ((ch)->mob_specials.sects)
#define MOB_ATTACK_TYPE(ch) ((ch)->mob_specials.attack_type)
#define MOB_DAMAGE(ch) ((ch)->mob_specials.damage)
#define MOB_LAST_DIR(ch) ((ch)->mob_specials.last_direction)
#define MOB_MILK_TIMER(ch) ((ch)->mob_specials.milk_timer)
#define MOB_TYPE(ch) ((ch)->mob_specials.type)
#define MOB_SKIN(ch) ((ch)->mob_specials.skin)
extern Creature mob_proto;
#define GET_MOB_NAME_BY_PROTO(rnum) mob_proto[(rnum)].player.short_descr
#define GET_MOB_RNUM(mob) ((mob)->nr)
#define GET_MOB_VNUM(mob) (IS_MOB(mob) ? mob_index[GET_MOB_RNUM(mob)].vnum : NOBODY)
/* Strength Data */
extern const struct str_app_type str_app[];
#define CAN_CARRY_W(ch) (str_app[GET_STRENGTH(ch)].carry_w)
#define CAN_CARRY_N(ch) (15 * GET_DEXTERITY(ch))
#define AWAKE(ch) (GET_POS(ch) > POS_SLEEPING)
#define HAS_INFRA(ch) (AFF_FLAGGED(ch, AFF_INFRAVISION) || DSC_FLAGGED(ch, DSC_WITNESS_OF_DARKNESS))
#define CAN_SEE_IN_DARK(ch) (HAS_INFRA(ch) || (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_HOLYLIGHT)))
#define NOCTURNE_DARK(room) (ROOM_AFF_FLAGGED((room), ROOM_AFF_DARK))
#define CAN_SEE_IN_NOCTURNE(ch) (GET_OBTENEBRATION(ch) >= 2)
#define CAN_SEE_IN_DARK_ROOM(ch, room) ((IS_LIGHT(room) || CAN_SEE_IN_DARK(ch)) && (!NOCTURNE_DARK(room) || CAN_SEE_IN_NOCTURNE(ch)))
/* These three deprecated. */
#define WAIT_STATE(ch, cycle) do { GET_WAIT_STATE(ch) = (cycle); } while(0)
#define CHECK_WAIT(ch) ((ch)->wait > 0)
#define GET_MOB_WAIT(ch) GET_WAIT_STATE(ch)
/* New, preferred macro. */
#define GET_WAIT_STATE(ch) ((ch)->wait)
/* descriptor-based utils ************************************************/
#define STATE(d) ((d)->connected)
/* object utils **********************************************************/
extern char *get_obj_desc(Object obj, Creature ch, int mode);
extern Object obj_proto;
#define GET_OBJ_NAME_BY_PROTO(rnum) obj_proto[(rnum)].short_description
#define GET_OBJ_DESC(obj, ch, mode) get_obj_desc((obj), (ch), (mode))
#define GET_OBJ_TYPE(obj) ((obj)->obj_flags.type_flag)
#define GET_OBJ_COST(obj) ((obj)->obj_flags.cost)
#define GET_OBJ_RENT(obj) ((obj)->obj_flags.cost_per_day)
#define GET_OBJ_EXTRA(obj) ((obj)->obj_flags.extra_flags)
#define GET_OBJ_WEAR(obj) ((obj)->obj_flags.wear_flags)
#define GET_OBJ_VAL(obj, val) ((obj)->obj_flags.value[(val)])
#define GET_OBJ_WEIGHT(obj) ((obj)->obj_flags.weight)
#define GET_OBJ_TIMER(obj) ((obj)->obj_flags.timer)
#define GET_OBJ_MATERIAL(obj) ((obj)->obj_flags.material)
#define GET_OBJ_RNUM(obj) ((obj)->item_number)
#define GET_OBJ_VNUM(obj) (GET_OBJ_RNUM(obj) >= 0 ? obj_index[GET_OBJ_RNUM(obj)].vnum : NOTHING)
#define IS_OBJ_STAT(obj,stat) (IS_SET((obj)->obj_flags.extra_flags,stat))
#define IS_CORPSE(obj) (GET_OBJ_TYPE(obj) == ITEM_CORPSE)
#define CAN_WEAR(obj, part) (IS_SET((obj)->obj_flags.wear_flags, (part)))
#define IN_CHAIR(obj) ((obj)->sitting)
#define GET_PULLED_BY(obj, i) (i == 0 ? (obj)->pulled_by1 : (obj)->pulled_by2)
/* Sight notes */
#define NIGHTVIS(ch) (AFF_FLAGGED((ch), AFF_NIGHTVISION))
/* Is anyone carrying this object and if so, are they visible? */
#define CAN_SEE_OBJ_CARRIER(sub, obj) \
((!obj->carried_by || CAN_SEE(sub, obj->carried_by)) && \
(!obj->worn_by || CAN_SEE(sub, obj->worn_by)))
#define MORT_CAN_SEE_OBJ(sub, obj) \
((LIGHT_OK(sub) || (SENSES_BONUS(sub) && obj->in_room == sub->in_room) || obj->worn_by == sub || obj->carried_by == sub) && CAN_SEE_OBJ_CARRIER(sub, obj))
#define CAN_SEE_OBJ(sub, obj) \
(MORT_CAN_SEE_OBJ(sub, obj) || (!IS_NPC(sub) && PRF_FLAGGED((sub), PRF_HOLYLIGHT)))
#define CAN_CARRY_OBJ(ch,obj) \
(((IS_CARRYING_W(ch) + GET_OBJ_WEIGHT(obj)) <= CAN_CARRY_W(ch)) && \
((IS_CARRYING_N(ch) + 1) <= CAN_CARRY_N(ch)))
#define CAN_GET_OBJ(ch, obj) \
(CAN_WEAR((obj), ITEM_WEAR_TAKE) && CAN_CARRY_OBJ((ch),(obj)) && \
CAN_SEE_OBJ((ch),(obj)))
#define OBJS(obj, vict) (CAN_SEE_OBJ((vict), (obj)) ? GET_OBJ_DESC((obj), vict, 1) : "something")
/* personal utilities ***************************************************/
extern char *PERS(Creature ch, Creature vict, bool real);
#define HSHR(ch) (MOB_FLAGGED((ch), MOB_PLURAL) ? "their" : (GET_SEX(ch) ? (GET_SEX(ch) == SEX_MALE ? "his":"her") :"its"))
#define HSSH(ch) (MOB_FLAGGED((ch), MOB_PLURAL) ? "they" : (GET_SEX(ch) ? (GET_SEX(ch) == SEX_MALE ? "he" :"she") : "it"))
#define HMHR(ch) (MOB_FLAGGED((ch), MOB_PLURAL) ? "them" : (GET_SEX(ch) ? (GET_SEX(ch) == SEX_MALE ? "him":"her") : "it"))
#define ANA(obj) (strchr("aeiouyAEIOUY", *(obj)->name) ? "An" : "A")
#define SANA(obj) (strchr("aeiouyAEIOUY", *(obj)->name) ? "an" : "a")
/* Various macros building up to CAN_SEE ********************************/
#define LIGHT_OK(sub) (!AFF_FLAGGED(sub, AFF_BLIND) && \
(IS_LIGHT((sub)->in_room) || HAS_INFRA(sub)))
#define INVIS_OK(sub, obj) ((!AFF_FLAGGED(obj, AFF_INVISIBLE)) && \
(!AFF_FLAGGED((obj), AFF_HIDE) || AFF_FLAGGED((sub), AFF_SENSE_HIDE)))
#define CAN_SEE_UNSEEN(sub, obj) (DSC_FLAGGED(obj, DSC_UNSEEN_PRESENCE) ? (DSC_FLAGGED(sub, DSC_HEIGHTENED_SENSES) ? (GET_AUSPEX(sub) > GET_OBFUSCATE(obj) ? 1 : (GET_AUSPEX(sub) == GET_OBFUSCATE(obj) ? (ww_dice(GET_PERCEPTION(sub) + GET_TALENT(sub, TALENT_SUBTERFUGE), 7) > ww_dice(GET_MANIPULATION(obj) + GET_TALENT(obj, TALENT_SUBTERFUGE), 7) ? 1 : 0) : 0)) : 0) : 1)
#define MORT_CAN_SEE(sub, obj) (((LIGHT_OK(sub) || (SENSES_BONUS(sub) && obj->in_room == sub->in_room)) && CAN_SEE_UNSEEN(sub, obj) && INVIS_OK(sub, obj)) && !AFF_FLAGGED(sub, AFF_BLIND))
#define MORT_CAN_SEE_NO_DARK(sub, obj) ((INVIS_OK(sub, obj)) && !AFF_FLAGGED(sub, AFF_BLIND))
#define IMM_CAN_SEE(sub, obj) \
(MORT_CAN_SEE(sub, obj) || (!IS_NPC(sub) && PRF_FLAGGED(sub, PRF_HOLYLIGHT)))
#define IMM_CAN_SEE_NO_DARK(sub, obj) \
(MORT_CAN_SEE_NO_DARK(sub, obj) || (!IS_NPC(sub) && PRF_FLAGGED(sub, PRF_HOLYLIGHT)))
#define SELF(sub, obj) ((sub) == (obj))
/* Can subject see character "obj"? */
#define CAN_SEE_DARK(sub, obj) (SELF(sub, obj) || \
((GET_REAL_LEVEL(sub) >= (IS_NPC(obj) ? 0 : GET_INVIS_LEV(obj))) && \
IMM_CAN_SEE(sub, obj)))
#define CAN_SEE_NO_DARK(sub, obj) (SELF(sub, obj) || \
((GET_REAL_LEVEL(sub) >= (IS_NPC(obj) ? 0 : GET_INVIS_LEV(obj))) && \
IMM_CAN_SEE_NO_DARK(sub, obj)))
#define CAN_SEE(sub, obj) (Global_ignore_dark ? CAN_SEE_NO_DARK(sub, obj) : CAN_SEE_DARK(sub, obj))
/* OS compatibility *****************************************************/
/* there could be some strange OS which doesn't have NULL... */
#ifndef NULL
#define NULL (void *)0
#endif
#if !defined(FALSE)
#define FALSE 0
#endif
#if !defined(TRUE)
#define TRUE (!FALSE)
#endif
/* defines for fseek */
#ifndef SEEK_SET
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif
/*
* NOCRYPT can be defined by an implementor manually in sysdep.h.
* EMPIRE_CRYPT is a variable that the 'configure' script
* automatically sets when it determines whether or not the system is
* capable of encrypting.
*/
#if defined(NOCRYPT) || !defined(EMPIRE_CRYPT)
#define CRYPT(a, b) (a)
#else
#define CRYPT(a, b) ((char *) crypt((a),(b)))
#endif
#define ABSOLUTE(x) ((x < 0) ? (x * -1) : (x))
#define BOTCHED < 0 /* a result on a ww_dice roll was < 0 */
#define FAILED == 0 /* a result on a ww_dice roll was == 0 */
extern struct clan_data clan[];
extern struct discipline_data disc[];
/* Vampire related bonuses */
#define SENSES_BONUS(ch) (DSC_FLAGGED(ch, DSC_HEIGHTENED_SENSES) ? 2 : 0)
#define CAN_SPEND_BLOOD(ch) (!DSC_FLAGGED(ch, DSC_CANT_SPEND_BLOOD))
#define CAN_SPEND_WILLPOWER(ch) (!DSC_FLAGGED(ch, DSC_CANT_SPEND_WILLPOWER))
/* Werewolf related stuff */
#define GET_BREED_FORM(ch) (GET_BREED(ch) == BREED_HOMID ? MORPH_NONE : (GET_BREED(ch) == BREED_METIS ? MORPH_CRINOS : MORPH_LUPUS))
/* Other */
#define SHOULD_APPEAR(ch) (AFF_FLAGGED(ch, AFF_HIDE | AFF_INVISIBLE) || DSC_FLAGGED(ch, DSC_UNSEEN_PRESENCE))