/**************************************************************************/
// macros.h - most of the compiler macros are defined in here
/***************************************************************************
* The Dawn of Time v1.69r (c)1997-2004 Michael Garratt *
* >> A number of people have contributed to the Dawn codebase, with the *
* majority of code written by Michael Garratt - www.dawnoftime.org *
* >> To use this source code, you must fully comply with all the licenses *
* in licenses.txt... In particular, you may not remove this copyright *
* notice. *
***************************************************************************
* >> Original Diku Mud copyright (c)1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, & Katja Nyboe. *
* >> Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* >> ROM 2.4 is copyright 1993-1995 Russ Taylor and has been brought to *
* you by the ROM consortium: Russ Taylor(rtaylor@pacinfo.com), *
* Gabrielle Taylor(gtaylor@pacinfo.com) & Brian Moore(rom@rom.efn.org) *
* >> Oblivion 1.2 is copyright 1996 Wes Wagner *
**************************************************************************/
#ifndef MACROS_H
#define MACROS_H
/**************************************************************************/
// disable minor printf optimisation macro used in versions of GCC >= 2.97
// this macro creates problems when you have member functions called
// printf() - such as in the char_data class
#ifdef __GNUC__
# ifdef printf
# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)
# undef printf
// macro is defined normally as below
//#ifdef __GNUC_PREREQ (2,97)
//# define printf(fmt, args...) fprintf (stdout, fmt, ##args)
# endif
# endif
#endif
/**************************************************************************/
// a assert pointer macro, used to make shorthand asserts
// compatible with gcc 3.3.1+
#define assertp(pointer) assert( (pointer) !=NULL)
/**************************************************************************/
#define alloc_mem(sz) malloc((size_t)sz)
#define free_mem(mem, sz) free(mem)
/**************************************************************************/
/*
* Utility macros.
*/
#define IS_VALID(data) ((data) != NULL && (data)->valid)
#define VALIDATE(data) ((data)->valid = true)
#define INVALIDATE(data) ((data)->valid = false)
#define UMIN(a, b) ((a) < (b) ? (a) : (b))
#define UMAX(a, b) ((a) > (b) ? (a) : (b))
#define URANGE(a, b, c) ((b) < (a) ? (a) : ((b) > (c) ? (c) : (b)))
#define LOWER(c) (tolower(c))
/* (c) >= 'A' && (c) <= 'Z' ? (c)+'a'-'A' : (c))*/
#define UPPER(c) ((c) >= 'a' && (c) <= 'z' ? (c)+'A'-'a' : (c))
#define IS_LOWER(c) ((c) >= 'a' && (c) <= 'a' ? true: false)
#define IS_UPPER(c) ((c) >= 'A' && (c) <= 'Z' ? true: false)
/* used by ident system */
#define replace_string( pstr, nstr ) \
{ free_string( (pstr) ); pstr=str_dup( (nstr) ); }
#define IS_NULLSTR(str) ((str)==NULL || (str)[0]=='\0')
#define IS_HEALER(mob) (IS_NPC(mob) && IS_SET(mob->act, ACT_IS_HEALER))
#define IS_WATER_SECTOR(sect) (sect==SECT_WATER_SWIM \
|| sect==SECT_WATER_NOSWIM \
|| sect==SECT_UNDERWATER)
#define HAS_CLASSFLAG(ch, flag) (IS_SET(class_table[(ch)->clss].flags, flag))
/**************************************************************************/
/*
* OLC Macros
*/
#define HAS_AREA_SECURITY(ch, Area) (\
IS_SET(Area->area_flags, AREA_LOCKED)? \
HAS_SECURITY(ch,9):HAS_SECURITY(ch, UMAX(6,Area->security) ) )
#define IS_BUILDER_WHEN_NOT_RESTRICTED(ch, Area) (\
HAS_AREA_SECURITY(ch, Area) \
|| is_exact_name(ch->name, Area->builders) )
#define IS_BUILDER_WHEN_RESTRICTED(ch, Area, type) (\
HAS_SECURITY(ch,9) \
||is_exact_name("all", \
Area->build_restricts[type]) \
||is_exact_name(ch->name, \
Area->build_restricts[type]) \
||is_exact_name("all", \
Area->build_restricts[BUILDRESTRICT_ALL]) \
||is_exact_name(ch->name, \
Area->build_restricts[BUILDRESTRICT_ALL]) )
#define IS_BUILDER(ch, Area, type) (\
IS_SET(Area->area_flags, AREA_LOCKED)? \
HAS_SECURITY(ch,9): \
HAS_SECURITY(ch,1) && \
(IS_SET(Area->area_flags, AREA_USE_BUILDRESTRICTS) \
?IS_BUILDER_WHEN_RESTRICTED(ch, Area, type) \
:IS_BUILDER_WHEN_NOT_RESTRICTED(ch, Area)) )
#define GET_SECURITY(ch) ( IS_NPC((ch))? 0 : (ch)->pcdata->security )
#define HAS_SECURITY(cha, value) (GET_SECURITY( (cha) ) >= (value) )
#define TOGGLE_BIT(var, bit) ((var) ^= (bit))
// macro used in reading in character files
#define IS_OLD_CHVER(ch) ( ch->version<9 || \
( ch->version==9 && ch->subversion<2))
/**************************************************************************/
/*
* Character macros.
*/
#define IS_OOC(ch) ( (ch)->in_room!=NULL && IS_SET((ch)->in_room->room_flags, ROOM_OOC))
#define IS_OLC(ch) ( (ch)->in_room && IS_SET((ch)->in_room->area->area_flags, AREA_OLCONLY))
#define IS_IC(ch) ( (ch)->in_room!=NULL \
&& !IS_SET((ch)->in_room->room_flags, ROOM_OOC) \
&& !IS_SET((ch)->in_room->area->area_flags, AREA_OLCONLY) )
#define IS_OLCAREA(area) (IS_SET( (area)->area_flags, AREA_OLCONLY) )
#define IS_NEWBIE(ch) ((ch->level) <= (10) && !IS_LETGAINED(ch))
#define IS_NEWBIE_SUPPORT(ch) (IS_SET((ch)->comm,COMM_NEWBIE_SUPPORT))
#define HAS_IMMTALK_NAME(ch) (ch && TRUE_CH(ch)->pcdata && !IS_NULLSTR(TRUE_CH(ch)->pcdata->immtalk_name))
#define IS_RP_SUPPORT(ch) (HAS_CONFIG((ch), CONFIG_RP_SUPPORT ))
#define IS_SPELL(sn) ((sn >= FIRST_SPELL) && (sn <= LAST_SPELL))
#define IS_REALM(sn) ((sn >= gsn_abjuration) && (sn <= gsn_time ))
#define IS_SKILL(sn) ((sn >= gsn_claw) && (sn <= gsn_kobold ))
#define IS_SKILL_VALID_FOR_CLASS(sn, class_index) \
(skill_table[sn].rating[class_index] > 0 \
&& skill_table[sn].skill_level[class_index] < LEVEL_IMMORTAL \
&& skill_table[sn].skill_level[class_index] >= 0 )
#define IS_SKILLGROUP_SELECTABLE_FOR_CHAR(gn, ch) \
(ch && (skillgroup_table[gn].rating[ch->clss] >= 0 || IS_SET(skillgroup_table[gn].flags, SKILLGROUP_FREE_FOR_ALL)) \
&& ch->remort>= skillgroup_table[gn].remort \
&& IS_SET(skillgroup_table[gn].flags, SKILLGROUP_CREATION_SELECTABLE))
#define IS_SWITCHED(ch) ((ch)->desc && (ch)->desc->original)
#define IS_CONTROLLED(victim) (IS_NPC(victim) && (victim)->desc != NULL)
#define HAS_DESC(ch) ((ch)->desc)
#define SAFE_DESC_CHARACTER(ch) (ch->desc->character? ch->desc->character: ch)
#define TRUE_CH(ch) (ch->desc ? \
(ch->desc->original ? ch->desc->original : SAFE_DESC_CHARACTER(ch)):ch)
#define TCH(ch) TRUE_CH(ch)
#define TRUE_CH_PCDATA(ch) (TRUE_CH(ch)?TRUE_CH(ch)->pcdata:NULL)
#define ACTIVE_CH(ch) (ch->desc ? ch: \
(ch->controlling? (ch->controlling->desc?ch->controlling:ch):ch))
#define ACH(ch) ACTIVE_CH(ch)
#define CH(descriptor) ((descriptor)->original ? \
(descriptor)->original : (descriptor)->character)
#define IS_IN_EDITMODE(ch) ((ch)->desc && (ch)->desc->pString)
#define IS_IN_REDIT(ch) (ch->desc && ch->desc->editor==ED_ROOM)
#define IS_NPC(ch) ((ch)->pcdata==NULL)
#define IS_KEEPER(ch) (IS_NPC((ch)) && (ch)->pIndexData && (ch)->pIndexData->pShop)
#define IS_UNSWITCHED_MOB(ch) (IS_NPC(ch) && !IS_CONTROLLED(ch))
#define IS_IRCCON(connection) ((connection)->contype==CONTYPE_IRC)
#define IS_IRC(ch) (!IS_SWITCHED(ch) && (ch)->desc && IS_IRCCON((ch)->desc) )
#define IS_IMMORTAL(ch) (get_trust(ch) >= LEVEL_IMMORTAL)
#define IS_ICIMMORTAL(ch) (!IS_NPC(ch) && ch->level >=LEVEL_IMMORTAL)
#define IS_HERO(ch) (get_trust(ch) == LEVEL_HERO)
#define IS_TRUSTED(ch,level) (get_trust((ch)) >= (level))
#define IS_AFFECTED(ch, bit) (IS_SET((ch)->affected_by, (bit)))
#define IS_AFFECTED2(ch, bit) (IS_SET((ch)->affected_by2, (bit)))
#define IS_ADMIN(ch) (TRUE_CH(ch)->level>=ADMIN)
#define IS_CREATOR(ch) (TRUE_CH(ch)->level>=99)
#define IS_SRADMIN(ch) (TRUE_CH(ch)->level>=98)
#define IS_JRADMIN(ch) (TRUE_CH(ch)->level>=97)
#define IS_CODER(ch) (TRUE_CH(ch)->level>=96)
#define IS_IBUILDER(ch) (TRUE_CH(ch)->level>=95)
#define IS_REMORTS(ch) (TRUE_CH(ch)->councils,COUNCIL_REMORTS)
#define IS_NOBLE(ch) (TRUE_CH(ch)->pcdata && ((TRUE_CH(ch))->pcdata->diplomacy>0) )
#define IS_SILENT(ch) (IS_SET((ch)->dyn, DYN_SILENTLY))
#define IS_QUESTER(ch) (IS_SET(TRUE_CH(ch)->act, PLR_QUESTER))
#define IS_JAILED(ch) (!IS_NPC(ch) && (ch)->level<LEVEL_IMMORTAL \
&& (ch)->in_room_vnum()==ROOM_VNUM_JAIL)
#define IS_JOB(ch) (IS_SET(TRUE_CH(ch)->job, JOB_JOB))
#define IS_CITY_GUARD(ch) (IS_SET(TRUE_CH(ch)->job, JOB_CITY_GUARD))
#define IS_LT_GUARD(ch) (IS_SET(TRUE_CH(ch)->job, JOB_LT_GUARD))
#define IS_THIEF(ch) (!IS_NPC(ch) && TRUE_CH_PCDATA(ch)->thief_until>current_time)
#define IS_KILLER(ch) (!IS_NPC(ch) && TRUE_CH_PCDATA(ch)->killer_until>current_time)
#define IS_LINKDEAD(ch) ( !IS_NPC(ch) && !ch->desc \
&& (ch->controlling? !ch->controlling->desc:true))
#define IS_ACTIVE(ch) (HAS_CONFIG(ch, CONFIG_ACTIVE) \
&& !GAMESETTING(GAMESET_PEACEFUL_MUD) \
&& !GAMESETTING2(GAMESET2_NO_DUEL_REQUIRED))
#define IS_PEACEFUL(ch) (!IS_ACTIVE(ch))
#define USING_AUTOMAP(ch) (HAS_CONFIG(ch, CONFIG_AUTOMAP))
// CONFIG MACROS
#define HAS_HOLYLIGHT(ch) (TRUE_CH(ch)->pcdata \
&& IS_SET(TRUE_CH(ch)->act,PLR_HOLYLIGHT))
#define HAS_AUTOSELF(ch) (IS_SET(TRUE_CH(ch)->comm,COMM_AUTOSELF))
#define GET_AGE(ch) ((int) (17 + ((ch)->played \
+ current_time - (ch)->logon )/72000))
#define GET_NEW_KARN_COUNTER(ch) (IS_NPC(ch)?0:((ch->pcdata->karns*1000)+400)\
* ((ch)->level<40 ? 1 : (1 + ((ch)->level-40)/10)))
#define GET_NEW_LAY_COUNTER(ch) (IS_NPC(ch)?0:8)
#define GET_MAX_KARN(ch) (IS_NPC(ch)?0: \
(IS_SET(ch->act, PLR_NOREDUCING_MAXKARN) \
|| GAMESETTING3(GAMESET3_NO_DECREASING_MAX_KARN)? \
5 : UMAX(0, 5-( (ch->pkkills-(ch->pkdefeats/2)) /5) ) ) )
#define IS_GOOD(ch) (ch->alliance >= 2)
#define IS_EVIL(ch) (ch->alliance <= -2)
#define IS_NEUTRAL(ch) (!IS_GOOD(ch) && !IS_EVIL(ch))
#define IS_TEND_CHAOTIC(ch) (ch->tendency < -1)
#define IS_TEND_LAWFUL(ch) (ch->tendency > 1)
#define IS_TEND_NEUTRAL(ch) (!IS_TEND_CHAOTIC(ch) && !IS_TEND_LAWFUL(ch))
#define IS_AWAKE(ch) (ch->position > POS_SLEEPING)
#define IS_MOUNTED(ch) ((ch)->ridden_by)
#define IS_RIDING(ch) ((ch)->mounted_on)
#define IS_TETHERED(ch) (IS_NPC((ch)) && ((ch)->tethered))
#define DAMTYPE(sn) (skill_table[sn].damtype)
#define IS_SUBDUED(ch) ((ch)->subdued)
#define GET_AC(ch,type)\
((ch)->armor[type] + \
( IS_AWAKE(ch) ? - (ch)->modifiers[STAT_QU] : 0 ))
#define GET_HITROLL(ch) \
((ch)->hitroll+ (ch)->modifiers[STAT_ST]/10 )
#define GET_DAMROLL(ch) \
((ch)->damroll+ (ch)->modifiers[STAT_ST]/5 )
#define XP_PAST_LEVEL(ch) \
(IS_NPC(ch)?0:(ch->exp- (ch->level *exp_per_level(ch, ch->pcdata->points))))
#define IS_LETGAINED(ch) (IS_NPC(ch)?true:IS_SET(ch->act,PLR_CAN_ADVANCE))
#define GAMESETTING_LETGAINING_IS_REQUIRED (!GAMESETTING(GAMESET_NO_LETGAINING_REQUIRED))
#define IS_OUTSIDE(ch) \
( !IS_SET(ch->in_room->room_flags, ROOM_INDOORS) \
&& ch->in_room->sector_type != SECT_UNDERWATER \
&& ch->in_room->sector_type != SECT_CAVE )
#define WIZI_LOOKUP(ch) (IS_OOC(ch)?ch->owizi:IS_OLC(ch)?ch->olcwizi:ch->iwizi)
#define INVIS_LEVEL(ch) (WIZI_LOOKUP(ch)?WIZI_LOOKUP(ch):ch->invis_level)
#define WAIT_STATE(ch, npulse) ((ch)->wait = UMAX((ch)->wait, (npulse)))
#define DAZE_STATE(ch, npulse) ((ch)->daze = UMAX((ch)->daze, (npulse)))
#define get_carry_weight(ch) ((ch)->carry_weight + (ch)->silver/10 + \
(ch)->gold * 2 / 5)
#define HAS_TRIGGER(ch,trig) (IS_SET((ch)->pIndexData->mprog_flags,(trig)))
#define GET_SECONDS_PLAYED(ch) \
(ch->played + (int) (current_time - ch->logon))
// config macros
#define HAS_CONFIG(ch, value) ( IS_SET (TRUE_CH(ch)->config, value ))
#define SET_CONFIG(ch, value) ( SET_BIT(TRUE_CH(ch)->config, value ))
#define REMOVE_CONFIG(ch, value) (REMOVE_BIT(TRUE_CH(ch)->config, value ))
#define TOGGLE_CONFIG(ch, value) (TOGGLE_BIT(TRUE_CH(ch)->config, value ))
// config2 macros
#define HAS_CONFIG2(ch, value) ( IS_SET (TRUE_CH(ch)->config2, value ))
#define SET_CONFIG2(ch, value) ( SET_BIT(TRUE_CH(ch)->config2, value ))
#define REMOVE_CONFIG2(ch, value) (REMOVE_BIT(TRUE_CH(ch)->config2, value ))
#define TOGGLE_CONFIG2(ch, value) (TOGGLE_BIT(TRUE_CH(ch)->config2, value ))
// pconfig macros - player configs, stored in pcdata
#define HAS_PCONFIG(ch, value) ( IS_SET (TRUE_CH_PCDATA->config, value ))
#define SET_PCONFIG(ch, value) ( SET_BIT(TRUE_CH_PCDATA->config, value ))
#define REMOVE_PCONFIG(ch, value) (REMOVE_BIT(TRUE_CH_PCDATA->config, value ))
#define TOGGLE_PCONFIG(ch, value) (TOGGLE_BIT(TRUE_CH_PCDATA->config, value ))
// channel macros
#define __CHAN_VALUE(ch) (TRUE_CH(ch)->pcdata?TRUE_CH(ch)->pcdata->channeloff:__CHANNEL_OFF_CRASH_PROTECTOR_VARIABLE)
#define HAS_CHANNELOFF(ch, value) ( IS_SET(__CHAN_VALUE(ch), value ))
#define SET_CHANNELOFF(ch, value) ( SET_BIT(__CHAN_VALUE(ch), value ))
#define REMOVE_CHANNELOFF(ch, value) (REMOVE_BIT(__CHAN_VALUE(ch), value ))
#define TOGGLE_CHANNELOFF(ch, value) (TOGGLE_BIT(__CHAN_VALUE(ch), value ))
#define HAS_MSP(ch) (ch && TRUE_CH(ch)->pcdata && TRUE_CH(ch)->pcdata->msp_enabled)
#define HAS_MXP(ch) (ch && TRUE_CH(ch)->pcdata && TRUE_CH(ch)->pcdata->mxp_enabled)
#define HAS_MXPDESC(d) (d && d->mxp_enabled)
#define MXP_DETECTED_OR_ON(ch) ( ch && TRUE_CH(ch)->pcdata \
&& (TRUE_CH(ch)->pcdata->preference_mxp==PREF_ON \
|| \
(TRUE_CH(ch)->pcdata->preference_mxp==PREF_AUTOSENSE && \
TRUE_CH(ch)->desc && \
IS_SET(TRUE_CH(ch)->desc->flags, CONNECTFLAG_MXP_DETECTED)) ) )
#define IS_COURT(ch) IS_SET((ch)->config, CONFIG_COURTMEMBER)
#define HAS_HOLYSPEECH(ch) IS_SET((ch)->config, CONFIG_HOLYSPEECH)
#define CAN_HEAR_MSP(ch) ( !IS_NPC(TRUE_CH(ch)) && \
HAS_MSP(ch) && \
!is_affected(ch, gsn_deafness) )
#define CAN_SEE_EXIT(ch, exit) (!IS_SET(exit->exit_info, EX_CLOSED) \
|| HAS_HOLYLIGHT(ch) \
|| IS_SET(TRUE_CH(ch)->act, PLR_HOLYWALK) \
|| IS_SET(exit->exit_info, EX_OBVIOUS))
// capitalized person
#define CPERS(ch, looker) (capitalize(PERS(ch,looker)))
/**************************************************************************/
/*
* Object macros.
*/
#define OBJECT_AFFECTS(obj) \
(obj->affected? obj->affected: (obj->no_affects?NULL:obj->pIndexData->affected))
// if an object is disenchanted (failed enchant etc), then it gets the
// obj->no_affects flag set.
// this flag is only checked if obj->affects is NULL... if obj->affects is NULL
// and obj->no_affects is not set then the olc templates affects
// (obj->pIndexData->affected) are used.
#define CAN_WEAR(obj, part) (IS_SET((obj)->wear_flags, (part)))
#define DISALLOWED_OBJECT_FOR_CHAR(obj, ch) \
(!IS_NPC(ch) && (obj)->pIndexData->class_allowances \
&& !IS_SET((obj)->pIndexData->class_allowances, 1<<(ch)->clss) )
#define IS_OBJ_STAT(obj, stat) (IS_SET((obj)->extra_flags, (stat)))
#define IS_OBJ2_STAT(obj, stat) (IS_SET((obj)->extra2_flags, (stat)))
//#define IS_OBJ3_STAT(obj, stat) (IS_SET((obj)->extra3_flags, (stat)))
#define IS_WEAPON_STAT(obj,stat)(IS_SET((obj)->value[4],(stat)))
#define WEIGHT_MULT(obj) ((obj)->item_type == ITEM_CONTAINER ? \
(obj)->value[4] : 100)
#define get_gold_weight(gold) ((gold)*2/5)
#define get_silver_weight(silv) ((silv)/10)
#define trim_string(str) (ltrim_string(rtrim_string(str)))
#define IS_TRAPPED(obj) (IS_SET((obj)->extra2_flags, (OBJEXTRA2_TRAP)))
/**************************************************************************/
/**************************************************************************/
// reading in a a defined datatype macro
#if defined(KEY)
#undef KEY
#endif
#define KEY( literal, field, value ) \
if ( !str_cmp( word, literal ) ) \
{ \
field = value; \
fMatch = true; \
break; \
}
/**************************************************************************/
// reading in a string from a file macro
#if defined(SKEY)
#undef SKEY
#endif
#define SKEY( string, field ) \
if ( !str_cmp( word, string ) ) \
{ \
free_string( field ); \
field = fread_string( fp ); \
fMatch = true; \
break; \
}
/**************************************************************************/
#define channel_colour_disabled(ch, channel) \
(TRUE_CH(ch)?(TRUE_CH(ch)->pcdata? IS_SET( \
TRUE_CH(ch)->pcdata->strip_colour_on_channel,channel):false):false)
/**************************************************************************/
// iSpell Related stuff below
#define Stringify(x) Str(x)
#define Str(x) #x
#ifdef WIN32
// compatiblity macros
#define vsnprintf(buf, len, fmt, args) _vsnprintf(buf, len, fmt, args)
#define snprintf _snprintf
#define popen(command, mode) _popen(command,mode)
#define pclose(fp) _pclose(fp)
#define getcwd(dir, size) _getcwd(dir, size)
#define chdir(dir) _chdir(dir)
#define mkdir(dir) _mkdir(dir)
#endif
#endif // MACROS_H