empiremud/cnf/
empiremud/doc/
empiremud/lib/boards/
empiremud/lib/etc/
empiremud/lib/misc/
empiremud/lib/plralias/F-J/
empiremud/lib/plralias/K-O/
empiremud/lib/plralias/P-T/
empiremud/lib/plralias/U-Z/
empiremud/lib/plrobjs/
empiremud/lib/plrobjs/F-J/
empiremud/lib/plrobjs/K-O/
empiremud/lib/plrobjs/P-T/
empiremud/lib/plrobjs/U-Z/
empiremud/lib/world/
empiremud/lib/world/mob/
empiremud/lib/world/obj/
empiremud/log/
/* ************************************************************************
*   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))