1stMUD4.0/bin/
1stMUD4.0/doc/MPDocs/
1stMUD4.0/player/
1stMUD4.0/win32/
1stMUD4.0/win32/rom/
/**************************************************************************
*  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
*  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
*                                                                         *
*  Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael         *
*  Chastain, Michael Quan, and Mitchell Tse.                              *
*                                                                         *
*  In order to use any part of this Merc Diku Mud, you must comply with   *
*  both the original Diku license in 'license.doc' as well the Merc       *
*  license in 'license.txt'.  In particular, you may not remove either of *
*  these copyright notices.                                               *
*                                                                         *
*  Much time and thought has gone into this software and you are          *
*  benefiting.  We hope that you share your changes too.  What goes       *
*  around, comes around.                                                  *
***************************************************************************
*       ROM 2.4 is copyright 1993-1998 Russ Taylor                        *
*       ROM has been brought to you by the ROM consortium                 *
*           Russ Taylor (rtaylor@hypercube.org)                           *
*           Gabrielle Taylor (gtaylor@hypercube.org)                      *
*           Brian Moore (zump@rom.org)                                    *
*       By using this code, you have agreed to follow the terms of the    *
*       ROM license, in the file Rom24/doc/rom.license                    *
***************************************************************************
*       1stMUD ROM Derivative (c) 2001-2003 by Ryan Jennings              *
*            http://1stmud.dlmud.com/  <r-jenn@shaw.ca>                   *
***************************************************************************/
#if !defined(MACRO_H)
#define MACRO_H

#define init_cols(ch, cols) \
    int column_pos = 0; \
    bool done_newline = FALSE; \
    int line_length = get_scr_cols(ch); \
    int line_pos = 0; \
    int column_count = (cols); \
    int column_length = line_length / column_count

#define reset_cols \
    column_pos = 0; \
    done_newline = FALSE; \
    line_pos = 0

#define print_cols(pfunc, out, buf) \
do { \
    int buf_len = strlen_color(buf); \
    line_pos += buf_len; \
    if(!done_newline && line_pos >= line_length) { \
        pfunc##ln((out), ""); \
        done_newline = TRUE; \
        column_pos = 0; \
        line_pos = buf_len; \
    } \
    pfunc((out), buf); \
    column_pos++; \
	if(column_pos >= column_count) { \
		pfunc##ln((out), ""); \
        done_newline = TRUE; \
        column_pos = line_pos = 0; \
    } else { \
        int col_diff = 0; \
        if(column_length > buf_len) { \
            col_diff = column_length - buf_len; \
        } else if(buf_len > column_length) { \
            int diff_count = 0; \
            while(buf_len > column_length) \
                ++diff_count, buf_len -= column_length; \
            col_diff = (column_length * diff_count) - buf_len; \
            column_pos += diff_count; \
        } \
        if (line_pos + col_diff < line_length) { \
            line_pos += col_diff; \
            if(col_diff > 0) \
                pfunc##f((out), FORMATF("%%%d.%ds", col_diff, col_diff), " "); \
        } \
        done_newline = FALSE; \
    } \
} while(0)

#define alloc_mem(result, type, number)                            \
do                                                                \
{                                                                \
    if (!((result) = (type *) calloc ((number), sizeof(type))))    \
    {                                                            \
    log_error("malloc failure");                                \
    logf( "Malloc failure @ %s:%d\n", __FILE__, __LINE__ ); \
    abort();                                            \
    }                                                            \
} while(0)

#define realloc_mem(result,type,number)                                        \
do                                                                            \
{                                                                            \
    if (!((result) = (type *) realloc ((void *)(result), sizeof(type) * (number)))) \
    {                                                                        \
    log_error("realloc failure");                                            \
    logf( "Realloc failure @ %s:%d\n", __FILE__, __LINE__ );            \
    abort();                                                        \
    }                                                                        \
} while(0)

#define free_mem(point) \
do \
{ \
  if (!(point)) \
    bugf("Freeing null pointer %s:%d", __FILE__, __LINE__ ); \
  else free((void *)(point));  \
  (point) = NULL;  \
} while(0)

/*
 * 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)                ((c) >= 'A' && (c) <= 'Z' ? (c)+'a'-'A' : (c))
#define	UPPER(c)                ((c) >= 'a' && (c) <= 'z' ? (c)+'A'-'a' : (c))
#define IS_SET(flag, bit)	((flag) & (bit))
#define SET_BIT(var, bit)	((var) |= (bit))
#define REMOVE_BIT(var, bit)	((var) &= ~(bit))
/* bit string operation macro. */
#define    STR_IS_SET(var, bit)     ((((char *)(var))[((bit)/8)]) &   ((1<<((bit)%8))))
#define    STR_SET_BIT(var, bit)    ((((char *)(var))[((bit)/8)]) |=  ((1<<((bit)%8))))
#define    STR_REMOVE_BIT(var, bit) ((((char *)(var))[((bit)/8)]) &= ~((1<<((bit)%8))))
#define    STR_TOGGLE_BIT(var, bit) ((((char *)(var))[((bit)/8)]) ^=  ((1<<((bit)%8))))

#define IS_NULLSTR(str)		((str) == NULL || (str)[0] == '\0')
#define ENTRE(min,num,max)	( ((min) < (num)) && ((num) < (max)) )
#define	CHECK_POS(a, b, c)      {                                                       \
	(a) = (b);                                  \
	if ( (a) < 0 )                                      \
					bug( "CHECK_POS : " c " == < 0");	\
				}

#define SET_STAT(ch, pos, val) ((ch)->pcdata->gamestat[pos] = val)
#define GET_STAT(ch, pos)		((ch)->pcdata->gamestat[pos])
#define ADD_STAT(ch, pos, val) ((ch)->pcdata->gamestat[pos] += val)

#define    IS_VALID_STANCE(st) ((st) > STANCE_NONE && (st) < STANCE_CURRENT)
#define    GET_STANCE(ch, st)  ((ch)->stance[(st)])
#define    IS_STANCE(ch, sn)   (GET_STANCE((ch), STANCE_CURRENT) == (sn))
#define    SET_STANCE(ch, pos, st)  ((ch)->stance[(pos)] = (st))

#define UNLINK_SINGLE(pdata,pnext,type,list) \
do                                          \
{                                          \
	if (list == pdata)                      \
	{                                       \
		list = pdata->pnext;                 \
	}                                       \
	else                                    \
	{                                       \
		type *prev;                         \
		for (prev = list; prev != NULL; prev = prev->pnext) \
		{                                   \
			if (prev->pnext == pdata)        \
			{                               \
				prev->pnext = pdata->pnext;   \
				break;                      \
			}                               \
		}                                   \
		if (prev == NULL)                   \
		{                                   \
			bugf (#pdata " not found in " #list "."); \
		}                                   \
	}                                       \
} while(0)

#define LINK_SINGLE(pdata,pnext,list) \
do \
{ \
		pdata->pnext = list; \
		list = pdata; \
} \
while (0)

#define LINK_LAST(pdata,pnext,type,list) \
do \
{ \
    type *tmp; \
    if((tmp = list) == NULL) \
    { \
		pdata->pnext = list; \
		list = pdata; \
        break; \
    } \
    for(; tmp; tmp = tmp->pnext) \
    { \
        if(!tmp->pnext) \
        { \
            tmp->pnext = pdata; \
            pdata->pnext = NULL; \
            break; \
        } \
    } \
} \
while (0)

#define LINK(link, first, last, next, prev)                     	\
do                                                              	\
{                                                               	\
   if ( !(first) )								\
   {                                           				\
      (first) = (link);				                       	\
      (last) = (link);							    	\
   }											\
   else                                                      	\
      (last)->next = (link);			                       	\
   (link)->next = NULL;			                         	\
   if (first == link)								\
      (link)->prev = NULL;							\
   else										\
      (link)->prev = (last);			                       	\
   (last) = (link);				                       	\
} while(0)

#define INSERT(link, insert, first, next, prev)                 \
do                                                              \
{                                                               \
   (link)->prev = (insert)->prev;			                \
   if ( !(insert)->prev )                                       \
      (first) = (link);                                         \
   else                                                         \
      (insert)->prev->next = (link);                            \
   (insert)->prev = (link);                                     \
   (link)->next = (insert);                                     \
} while(0)

#define UNLINK(link, first, last, next, prev)                   	\
do                                                              	\
{                                                               	\
	if ( !(link)->prev )							\
	{			                                    	\
         (first) = (link)->next;			                 	\
	   if ((first))							 	\
	      (first)->prev = NULL;						\
	} 										\
	else										\
	{                                                 		\
         (link)->prev->next = (link)->next;                 	\
	}										\
	if ( !(link)->next ) 							\
	{				                                    \
         (last) = (link)->prev;                 			\
	   if ((last))								\
	      (last)->next = NULL;						\
	} 										\
	else										\
	{                                                    		\
         (link)->next->prev = (link)->prev;                 	\
	}										\
} while(0)

#define CHECK_LINKS(first, last, next, prev, type)		\
do {								\
  type *ptr, *pptr = NULL;					\
  if ( !(first) && !(last) )					\
    break;							\
  if ( !(first) )						\
  {								\
    bugf( "CHECK_LINKS: last with NULL first!  %s.",		\
        #first );					\
    for ( ptr = (last); ptr->prev; ptr = ptr->prev );		\
    (first) = ptr;						\
  }								\
  else if ( !(last) )						\
  {								\
    bugf( "CHECK_LINKS: first with NULL last!  %s.",		\
        #first );					\
    for ( ptr = (first); ptr->next; ptr = ptr->next );		\
    (last) = ptr;						\
  }								\
  if ( (first) )						\
  {								\
    for ( ptr = (first); ptr; ptr = ptr->next )			\
    {								\
      if ( ptr->prev != pptr )					\
      {								\
        bugf( "CHECK_LINKS(%s): %p:->prev != %p.  Fixing.",	\
            #first, ptr, pptr );			\
        ptr->prev = pptr;					\
      }								\
      if ( ptr->prev && ptr->prev->next != ptr )		\
      {								\
        bugf( "CHECK_LINKS(%s): %p:->prev->next != %p.  Fixing.",\
            #first, ptr, ptr );			\
        ptr->prev->next = ptr;					\
      }								\
      pptr = ptr;						\
    }								\
    pptr = NULL;						\
  }								\
  if ( (last) )							\
  {								\
    for ( ptr = (last); ptr; ptr = ptr->prev )			\
    {								\
      if ( ptr->next != pptr )					\
      {								\
        bugf( "CHECK_LINKS (%s): %p:->next != %p.  Fixing.",	\
            #first, ptr, pptr );			\
        ptr->next = pptr;					\
      }								\
      if ( ptr->next && ptr->next->prev != ptr )		\
      {								\
        bugf( "CHECK_LINKS(%s): %p:->next->prev != %p.  Fixing.",\
            #first, ptr, ptr );			\
        ptr->next->prev = ptr;					\
      }								\
      pptr = ptr;						\
    }								\
  }								\
} while(0)

#define replace_string(astr, bstr)  do{ free_string(astr); astr = str_dup(bstr); }while(0)

#define free_string(pstr) _free_string(pstr), pstr = NULL

#define NUL '\0'

#define IS_STRSET(str)  (IS_NULLSTR(str) ? "Not set." : (str))

/*
 * Character macros.
 */
#define IS_NPC(ch)		(IS_SET((ch)->act, ACT_IS_NPC))
#define IS_IMMORTAL(ch)		(get_trust(ch) >= LEVEL_IMMORTAL)
#define IS_HERO(ch)		(get_trust(ch) >= LEVEL_HERO)
#define IS_TRUSTED(ch,level)	(get_trust((ch)) >= (level))
#define IS_AFFECTED(ch, sn)	(IS_SET((ch)->affected_by, (sn)))

#define GET_AGE(ch)		((int) (17 + ((ch)->played \
				    + current_time - (ch)->logon )/72000))

#define IS_GOOD(ch)		(ch->alignment >= 350)
#define IS_EVIL(ch)		(ch->alignment <= -350)
#define IS_NEUTRAL(ch)		(!IS_GOOD(ch) && !IS_EVIL(ch))

#define IS_AWAKE(ch)		(ch->position > POS_SLEEPING)
#define GET_AC(ch,type)		((ch)->armor[type]			    \
		        + ( IS_AWAKE(ch)			    \
			? dex_app[get_curr_stat(ch,STAT_DEX)].defensive : 0 ))
#define GET_HITROLL(ch)	\
		((ch)->hitroll+str_app[get_curr_stat(ch,STAT_STR)].tohit)
#define GET_DAMROLL(ch) \
		((ch)->damroll+str_app[get_curr_stat(ch,STAT_STR)].todam)

#define IS_OUTSIDE(ch)		(!IS_SET(				    \
				    (ch)->in_room->room_flags,		    \
				    ROOM_INDOORS))
#define IS_IN_WAR(ch)   (ch->war != NULL \
                        && IS_SET((ch)->in_room->room_flags, ROOM_ARENA))

#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 act(format,ch,arg1,arg2,type)\
	act_new((format),(ch),(arg1),(arg2),(type),POS_RESTING)

#define log_wiznet(ch, flag, level, fmt) \
do { log_string(fmt); wiznet(fmt, NULL, NULL, flag, 0, 0); } while(0)

#define wiznet(string, ch, obj, flag, skip, level) \
    new_wiznet((ch),(obj),(flag),(skip),(level),(string))

#define HAS_TRIGGER_MOB(ch,trig)	(IS_SET((ch)->pIndexData->mprog_flags,(trig)))
#define HAS_TRIGGER_OBJ(obj,trig) (IS_SET((obj)->pIndexData->oprog_flags,(trig)))
#define HAS_TRIGGER_ROOM(room,trig) (IS_SET((room)->rprog_flags,(trig)))

#define IS_SWITCHED( ch )       ( ch->desc && ch->desc->original )
#define IS_BUILDER(ch, Area)	( !IS_NPC(ch) && !IS_SWITCHED( ch ) &&	  \
				( ch->pcdata->security >= Area->security  \
				|| strstr( Area->builders, ch->name )	  \
				|| strstr( Area->builders, "All" ) ) )

#define DESC_FLAGGED(d, flag) (IS_SET((d)->d_flags, (flag)))

#define CH(descriptor)  ((descriptor)->original ? \
(descriptor)->original : (descriptor)->character)

#define IS_REMORT(ch)      (!IS_NPC(ch) && ( IS_SET((ch)->act, PLR_REMORT) \
                                || number_classes(ch) > 1))

#define	ON_GQUEST(ch)      (gquest_info.running != GQUEST_OFF && ch->gquest)

#define STR_EDIT_KEY(ch) (IS_NPC(ch) ? '.' : ch->pcdata->str_ed_key)

#define GET_TZONE(ch)   (IS_NPC(ch) ? -1 : ch->pcdata->timezone)

#define		IS_PORTAL(d)		((d) && IS_SET((d)->d_flags, DESC_PORTAL))
#define		IS_FIRECL(d)       ((d) && IS_SET((d)->d_flags, DESC_IMP))
#define    IS_MXP(d)           ((d) && IS_SET((d)->d_flags, DESC_MXP) \
                                && ((d)->mxp.mxp_ver * 10) >= 4)
#define    IS_MSP(d)               ((d) && IS_SET((d)->d_flags, DESC_MSP))
#define    IS_COMPRESSED(d)        (d && d->out_compress)
#define		IS_PUEBLO(d)            ((d) && IS_SET((d)->d_flags, DESC_PUEBLO))

#define SCR_WIDTH(d)    (!(d) ? DEFAULT_SCR_WIDTH - 2 : (d)->scr_width)
#define SCR_HEIGHT(d)   (!(d) ? DEFAULT_SCR_HEIGHT - 2 : (d)->scr_height)

/*
 * Object macros.
 */
#define CAN_WEAR(obj, part)	(IS_SET((obj)->wear_flags,  (part)))
#define IS_OBJ_STAT(obj, stat)	(IS_SET((obj)->extra_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	IS_QUESTOR(ch)     (!IS_NPC(ch) && IS_SET((ch)->act, PLR_QUESTOR) && \
							(ch)->pcdata->questgiver != 0 )

/*
 * Description macros.
 */
#define PERS(ch, looker)	( can_see( looker, (ch) ) ?		\
				( IS_NPC(ch) ? (ch)->short_descr	\
				: (ch)->name ) : IS_IMMORTAL(ch) ? "an Immortal" : "someone" )

#endif