/**************************************************************************** * Eldhamud Codebase V2.2 * * ------------------------------------------------------------------------ * * EldhaMUD code (C) 2003-2008 by Robert Powell (Tommi) * * ------------------------------------------------------------------------ * * * ****************************************************************************/ /* * Utility macros. */ #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)) /* * Old-style Bit manipulation macros * * The bit passed is the actual value of the bit (Use the BV## defines) */ #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) ^= (bit)) /* * Macros for accessing virtually unlimited bitvectors. -Thoric * * Note that these macros use the bit number rather than the bit value * itself -- which means that you can only access _one_ bit at a time * * This code uses an array of integers */ /* * Here are the extended bitvector macros: */ #define xIS_SET(var, bit) ((var).bits[(bit) >> RSV] & 1 << ((bit) & XBM)) #define xSET_BIT(var, bit) ((var).bits[(bit) >> RSV] |= 1 << ((bit) & XBM)) #define xSET_BITS(var, bit) (ext_set_bits(&(var), &(bit))) #define xREMOVE_BIT(var, bit) ((var).bits[(bit) >> RSV] &= ~(1 << ((bit) & XBM))) #define xREMOVE_BITS(var, bit) (ext_remove_bits(&(var), &(bit))) #define xTOGGLE_BIT(var, bit) ((var).bits[(bit) >> RSV] ^= 1 << ((bit) & XBM)) #define xTOGGLE_BITS(var, bit) (ext_toggle_bits(&(var), &(bit))) #define xCLEAR_BITS(var) (ext_clear_bits(&(var))) #define xIS_EMPTY(var) (ext_is_empty(&(var))) #define xHAS_BITS(var, bit) (ext_has_bits(&(var), &(bit))) #define xSAME_BITS(var, bit) (ext_same_bits(&(var), &(bit))) /* * Memory allocation macros. */ #define CREATE(result, type, number) \ do \ { \ if (!((result) = (type *) calloc ((number), sizeof(type)))) \ { \ perror("malloc failure"); \ fprintf(stderr, "Malloc failure @ %s:%d\n", __FILE__, __LINE__ ); \ abort(); \ } \ } while(0) #define RECREATE(result,type,number) \ do \ { \ if(!((result) = (type *)realloc((result), sizeof(type) * (number)))) \ { \ perror("realloc failure"); \ fprintf(stderr, "Realloc failure @ %s:%d\n", __FILE__, __LINE__); \ abort(); \ } \ } while(0) #define DISPOSE(point) \ do \ { \ if((point)) \ { \ free((point)); \ (point) = NULL; \ } \ } while(0) #ifdef HASHSTR #define STRALLOC(point) str_alloc((point)) #define QUICKLINK(point) quick_link((point)) #define QUICKMATCH(p1, p2) (int) (p1) == (int) (p2) #define STRFREE(point) \ do \ { \ if((point)) \ { \ if( str_free((point)) == -1 ) \ bug( "STRFREEing bad pointer in %s, line %d\n", __FILE__, __LINE__ ); \ (point) = NULL; \ } \ } while(0) #else #define STRALLOC(point) str_dup((point)) #define QUICKLINK(point) str_dup((point)) #define QUICKMATCH(p1, p2) strcmp((p1), (p2)) == 0 #define STRFREE(point) DISPOSE((point)) #endif /* double-linked list handling macros -Thoric */ /* Updated by Scion 8/6/1999 */ #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) ) \ { \ bug( "CHECK_LINKS: last with NULL first! %s.", \ __STRING(first) ); \ for ( ptr = (last); ptr->prev; ptr = ptr->prev ); \ (first) = ptr; \ } \ else if ( !(last) ) \ { \ bug( "CHECK_LINKS: first with NULL last! %s.", \ __STRING(first) ); \ for ( ptr = (first); ptr->next; ptr = ptr->next ); \ (last) = ptr; \ } \ if ( (first) ) \ { \ for ( ptr = (first); ptr; ptr = ptr->next ) \ { \ if ( ptr->prev != pptr ) \ { \ bug( "CHECK_LINKS(%s): %p:->prev != %p. Fixing.", \ __STRING(first), ptr, pptr ); \ ptr->prev = pptr; \ } \ if ( ptr->prev && ptr->prev->next != ptr ) \ { \ bug( "CHECK_LINKS(%s): %p:->prev->next != %p. Fixing.",\ __STRING(first), ptr, ptr ); \ ptr->prev->next = ptr; \ } \ pptr = ptr; \ } \ pptr = NULL; \ } \ if ( (last) ) \ { \ for ( ptr = (last); ptr; ptr = ptr->prev ) \ { \ if ( ptr->next != pptr ) \ { \ bug( "CHECK_LINKS (%s): %p:->next != %p. Fixing.", \ __STRING(first), ptr, pptr ); \ ptr->next = pptr; \ } \ if ( ptr->next && ptr->next->prev != ptr ) \ { \ bug( "CHECK_LINKS(%s): %p:->next->prev != %p. Fixing.",\ __STRING(first), ptr, ptr ); \ ptr->next->prev = ptr; \ } \ pptr = ptr; \ } \ } \ } while(0) #define ASSIGN_GSN(gsn, skill) \ do \ { \ if ( ((gsn) = skill_lookup((skill))) == -1 ) \ fprintf( stderr, "ASSIGN_GSN: Skill %s not found.\n", \ (skill) ); \ } while(0) #define CHECK_SUBRESTRICTED(ch) \ do \ { \ if ( (ch)->substate == SUB_RESTRICTED ) \ { \ send_to_char( "You cannot use this command from within another command.\n\r", ch ); \ return; \ } \ } while(0) #define NULLSTR(str) (str[0] == '\0') #define STRING_NULL ('\0') /* * Character macros. */ #define IS_NPC(ch) (xIS_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_AFFECTED(ch, sn) (xIS_SET((ch)->affected_by, (sn))) #define HAS_BODYPART(ch, part) ((ch)->xflags == 0 || IS_SET((ch)->xflags, (part))) #define CAN_CAST(ch) ((ch)->Class != 2 && (ch)->Class != 3) #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) ((ch)->armor \ + ( IS_AWAKE(ch) \ ? dex_app[get_curr_dex(ch)].defensive \ : 0 )) #define GET_HITROLL(ch) ((ch)->hitroll \ +str_app[get_curr_str(ch)].tohit) /* Thanks to Chriss Baeke for noticing damplus was unused */ #define GET_DAMROLL(ch) ((ch)->damroll \ +(ch)->damplus \ +str_app[get_curr_str(ch)].todam) #define xIS_OUTSIDE(ch) (!xIS_SET( \ (ch)->in_room->room_flags, \ ROOM_INDOORS) && !xIS_SET( \ (ch)->in_room->room_flags, \ ROOM_TUNNEL)) #define NO_WEATHER_SECT(sect) ( sect == SECT_INSIDE || \ sect == SECT_UNDERWATER || \ sect == SECT_OCEANFLOOR || \ sect == SECT_UNDERGROUND ) #define IS_CLANNED(ch) (!IS_NPC((ch)) \ && (ch)->pcdata->clan \ && (ch)->pcdata->clan->clan_type != CLAN_ORDER \ && (ch)->pcdata->clan->clan_type != CLAN_GUILD) #define IS_ORDERED(ch) (!IS_NPC((ch)) \ && (ch)->pcdata->clan \ && (ch)->pcdata->clan->clan_type == CLAN_ORDER) #define IS_GUILDED(ch) (!IS_NPC((ch)) \ && (ch)->pcdata->clan \ && (ch)->pcdata->clan->clan_type == CLAN_GUILD) #define IS_DEADLYCLAN(ch) (!IS_NPC((ch)) && (ch)->pcdata->clan #define IS_DEVOTED(ch) (!IS_NPC((ch)) && (ch)->pcdata->deity) #define IS_IDLE(ch) ((ch)->pcdata && IS_SET( (ch)->pcdata->flags, PCFLAG_IDLE )) #define IS_PKILL(ch) ((ch)->pcdata && IS_SET( (ch)->pcdata->flags, PCFLAG_DEADLY )) #define CAN_PKILL(ch) (IS_PKILL((ch)) && (ch)->level >= 5 && get_age( (ch) ) >= 18 ) #define WAIT_STATE(ch, npulse) ((ch)->wait = npulse) #define EXIT(ch, door) ( get_exit( (ch)->in_room, door ) ) #define CAN_GO(ch, door) (EXIT((ch),(door)) \ && (EXIT((ch),(door))->to_room != NULL) \ && !IS_SET(EXIT((ch), (door))->exit_info, EX_CLOSED)) #define IS_FLOATING(ch) ( IS_AFFECTED((ch), AFF_FLYING) || IS_AFFECTED((ch), AFF_FLOATING) ) #define IS_VALID_SN(sn) ( (sn) >=0 && (sn) < MAX_SKILL \ && skill_table[(sn)] \ && skill_table[(sn)]->name ) #define IS_VALID_HERB(sn) ( (sn) >=0 && (sn) < MAX_HERB \ && herb_table[(sn)] \ && herb_table[(sn)]->name ) #define IS_VALID_DISEASE(sn) ( (sn) >=0 && (sn) < MAX_DISEASE \ && disease_table[(sn)] \ && disease_table[(sn)]->name ) #define IS_PACIFIST(ch) (IS_NPC(ch) && xIS_SET(ch->act, ACT_PACIFIST)) #define SPELL_FLAG(skill, flag) ( IS_SET((skill)->flags, (flag)) ) #define SPELL_DAMAGE(skill) ( ((skill)->info ) & 7 ) #define SPELL_ACTION(skill) ( ((skill)->info >> 3) & 7 ) #define SPELL_CLASS(skill) ( ((skill)->info >> 6) & 7 ) #define SPELL_POWER(skill) ( ((skill)->info >> 9) & 3 ) #define SPELL_SAVE(skill) ( ((skill)->info >> 11) & 7 ) #define SET_SDAM(skill, val) ( (skill)->info = ((skill)->info & SDAM_MASK) + ((val) & 7) ) #define SET_SACT(skill, val) ( (skill)->info = ((skill)->info & SACT_MASK) + (((val) & 7) << 3) ) #define SET_SCLA(skill, val) ( (skill)->info = ((skill)->info & SCLA_MASK) + (((val) & 7) << 6) ) #define SET_SPOW(skill, val) ( (skill)->info = ((skill)->info & SPOW_MASK) + (((val) & 3) << 9) ) #define SET_SSAV(skill, val) ( (skill)->info = ((skill)->info & SSAV_MASK) + (((val) & 7) << 11) ) /* Retired and guest imms. */ #define IS_RETIRED(ch) (ch->pcdata && IS_SET(ch->pcdata->flags,PCFLAG_RETIRED)) #define IS_GUEST(ch) (ch->pcdata && IS_SET(ch->pcdata->flags,PCFLAG_GUEST)) /* RIS by gsn lookups. -- Altrag. Will need to add some || stuff for spells that need a special GSN. */ #define IS_FIRE(dt) ( IS_VALID_SN(dt) && \ SPELL_DAMAGE(skill_table[(dt)]) == SD_FIRE ) #define IS_COLD(dt) ( IS_VALID_SN(dt) && \ SPELL_DAMAGE(skill_table[(dt)]) == SD_COLD ) #define IS_ACID(dt) ( IS_VALID_SN(dt) && \ SPELL_DAMAGE(skill_table[(dt)]) == SD_ACID ) #define IS_ELECTRICITY(dt) ( IS_VALID_SN(dt) && \ SPELL_DAMAGE(skill_table[(dt)]) == SD_ELECTRICITY ) #define IS_ENERGY(dt) ( IS_VALID_SN(dt) && \ SPELL_DAMAGE(skill_table[(dt)]) == SD_ENERGY ) #define IS_DRAIN(dt) ( IS_VALID_SN(dt) && \ SPELL_DAMAGE(skill_table[(dt)]) == SD_DRAIN ) #define IS_POISON(dt) ( IS_VALID_SN(dt) && \ SPELL_DAMAGE(skill_table[(dt)]) == SD_POISON ) #define NOT_AUTHED(ch) (!IS_NPC(ch) && ch->pcdata->auth_state <= 3 \ && IS_SET(ch->pcdata->flags, PCFLAG_UNAUTHED) ) #define IS_WAITING_FOR_AUTH(ch) (!IS_NPC(ch) && ch->desc \ && ch->pcdata->auth_state == 1 \ && IS_SET(ch->pcdata->flags, PCFLAG_UNAUTHED) ) /* * Object macros. */ #define CAN_WEAR(obj, part) (IS_SET((obj)->wear_flags, (part))) #define IS_OBJ_STAT(obj, stat) (xIS_SET((obj)->extra_flags, (stat))) /* * MudProg macros. -Thoric */ #define HAS_PROG(what, prog) (xIS_SET((what)->progtypes, (prog))) /* * Description macros. */ #define PERS(ch, looker, from) ( can_see( (looker), (ch), (from) ) ? \ ( IS_NPC(ch) ? (ch)->short_descr \ : (ch)->name ) : "someone" ) #define log_string(txt) ( log_string_plus( (txt), LOG_NORMAL, LEVEL_LOG ) ) #define dam_message(ch, victim, dam, dt) ( new_dam_message((ch), (victim), (dam), (dt), NULL) ) #define MANA UMAX(skill->min_mana,100/(2+ch->level-skill->skill_level[ch->Class])) #define BLOOD UMAX(1,(MANA+4)/8) #define GET_ADEPT(ch,sn) ( skill_table[(sn)]->skill_adept[(ch)->Class]) #define LEARNED(ch,sn) (IS_NPC(ch) ? 80 : URANGE(0, ch->pcdata->learned[sn], 101)) /* Structure and macros for using long bit vectors */ #define CHAR_SIZE sizeof(char) typedef char * LONG_VECTOR; #define LV_CREATE(vector, bit_length) \ do \ { \ int i; \ CREATE(vector, char, 1 + bit_length/CHAR_SIZE); \ \ for(i = 0; i <= bit_length/CHAR_SIZE; i++) \ *(vector + i) = 0; \ }while(0) #define LV_IS_SET(vector, index) \ (*(vector + index/CHAR_SIZE) & (1 << index%CHAR_SIZE)) #define LV_SET_BIT(vector, index) \ (*(vector + index/CHAR_SIZE) |= (1 << index%CHAR_SIZE)) #define LV_REMOVE_BIT(vector, index) \ (*(vector + index/CHAR_SIZE) &= ~(1 << index%CHAR_SIZE)) #define LV_TOGGLE_BIT(vector, index) \ (*(vector + index/CHAR_SIZE) ^= (1 << index%CHAR_SIZE))