/***************************************************************************
* File: bit.c *
* *
* Much time and thought has gone into this software and you are *
* benefitting. We hope that you share your changes too. What goes *
* around, comes around. *
* *
* This code was written by Jason Dinkel and inspired by Russ Taylor, *
* and has been used here for OLC - OLC would not be what it is without *
* all the previous coders who released their source code. *
***************************************************************************/
#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
/*
* The code below uses a table lookup system that is based on suggestions
* from Russ Taylor. There are many routines in handler.c that would benefit
* with the use of tables. You may consider simplifying your code base by
* implementing a system like below with such functions. - Jason Dinkel
*/
struct flag_stat_type
{
const struct flag_type *structure;
bool stat;
};
/*
* Name: flag_stat_table
* Purpose: This table catagorizes the tables following the lookup
* functions below into stats and flags. Flags can be toggled
* but stats can only be assigned. Update this table when a
* new set of flags is installed.
*/
const struct flag_stat_type flag_stat_table[] =
{
/*
* { structure stat },
*/
{ area_flags, FALSE },
{ sex_flags, TRUE },
{ exit_flags, FALSE },
{ door_resets, TRUE },
{ room_flags, FALSE },
{ sector_flags, TRUE },
{ type_flags, TRUE },
{ extra_flags, FALSE },
{ wear_flags, FALSE },
{ act_flags, FALSE },
{ affect_flags, FALSE },
{ apply_flags, TRUE },
{ wear_loc_flags, TRUE },
{ wear_loc_strings, TRUE },
{ weapon_flags, TRUE },
{ container_flags, FALSE },
{ liquid_flags, TRUE },
{ mprog_type_flags, TRUE },
{ portal_door_flags, FALSE },
{ portal_flags, FALSE },
{ 0, 0 }
};
/*
* Name: is_stat( table )
* Purpose: Returns TRUE if the table is a stat table and FALSE if flag.
* Called by: flag_value and flag_string.
* Note: This function is local and used only in bit.c.
*/
bool is_stat(const struct flag_type *flag_table)
{
int flag;
for (flag = 0; flag_stat_table[flag].structure; flag++)
{
if (flag_stat_table[flag].structure == flag_table
&& flag_stat_table[flag].stat)
return TRUE;
}
return FALSE;
}
/*
* This function is Russ Taylor's creation. Thanks Russ!
* All code copyright (C) Russ Taylor, permission to use and/or distribute
* has NOT been granted. Use only in this OLC package has been granted.
*
* Name: flag_lookup( flag, table )
* Purpose: Returns the value of a single, settable flag from the table.
* Called by: flag_value and flag_string.
* Note: This function is local and used only in bit.c.
*/
int flag_lookup(const char *name, const struct flag_type *flag_table)
{
int flag;
for (flag = 0; *flag_table[flag].name; flag++) /*
* OLC 1.1b
*/
{
if (!str_cmp(name, flag_table[flag].name)
&& flag_table[flag].settable)
return flag_table[flag].bit;
}
return NO_FLAG;
}
/*
* Name: flag_value( table, flag )
* Purpose: Returns the value of the flags entered. Multi-flags accepted.
* Called by: olc.c and olc_act.c.
*/
int flag_value(const struct flag_type *flag_table, char *argument)
{
char word[MAX_INPUT_LENGTH];
int bit;
int marked = 0;
bool found = FALSE;
if (is_stat(flag_table))
{
one_argument(argument, word);
if ((bit = flag_lookup(word, flag_table)) != NO_FLAG)
return bit;
else
return NO_FLAG;
}
/*
* Accept multiple flags.
*/
for (;;)
{
argument = one_argument(argument, word);
if (word[0] == '\0')
break;
if ((bit = flag_lookup(word, flag_table)) != NO_FLAG)
{
SET_BIT(marked, bit);
found = TRUE;
}
}
if (found)
return marked;
else
return NO_FLAG;
}
/*
* Name: flag_string( table, flags/stat )
* Purpose: Returns string with name(s) of the flags or stat entered.
* Called by: act_olc.c, olc.c, and olc_save.c.
*/
char *flag_string(const struct flag_type *flag_table, int bits)
{
static char buf[512];
int flag;
buf[0] = '\0';
for (flag = 0; *flag_table[flag].name; flag++) /*
* OLC 1.1b
*/
{
if (!is_stat(flag_table) && IS_SET(bits, flag_table[flag].bit))
{
strcat(buf, " ");
strcat(buf, flag_table[flag].name);
}
else if (flag_table[flag].bit == bits)
{
strcat(buf, " ");
strcat(buf, flag_table[flag].name);
break;
}
}
return (buf[0] != '\0') ? buf + 1 : "none";
}
const struct flag_type area_flags[] =
{
{ "none", AREA_NONE, FALSE },
{ "changed", AREA_CHANGED, FALSE },
{ "added", AREA_ADDED, FALSE },
{ "loading", AREA_LOADING, FALSE },
{ "verbose", AREA_VERBOSE, FALSE },
{ "", 0, 0 }
};
const struct flag_type sex_flags[] =
{
{ "male", SEX_MALE, TRUE },
{ "female", SEX_FEMALE, TRUE },
{ "neutral", SEX_NEUTRAL, TRUE },
{ "", 0, 0 }
};
const struct flag_type exit_flags[] =
{
{ "door", EX_ISDOOR, TRUE },
{ "closed", EX_CLOSED, TRUE },
{ "locked", EX_LOCKED, TRUE },
{ "bashed", EX_BASHED, FALSE },
{ "bashproof", EX_BASHPROOF, TRUE },
{ "pickproof", EX_PICKPROOF, TRUE },
{ "passproof", EX_PASSPROOF, TRUE },
{ "", 0, 0 }
};
const struct flag_type door_resets[] =
{
{ "open and unlocked", 0, TRUE },
{ "closed and unlocked", 1, TRUE },
{ "closed and locked", 2, TRUE },
{ "", 0, 0 }
};
const struct flag_type room_flags[] =
{
{ "dark", ROOM_DARK, TRUE },
{ "no_mob", ROOM_NO_MOB, TRUE },
{ "indoors", ROOM_INDOORS, TRUE },
{ "private", ROOM_PRIVATE, TRUE },
{ "safe", ROOM_SAFE, TRUE },
{ "solitary", ROOM_SOLITARY, TRUE },
{ "pet_shop", ROOM_PET_SHOP, TRUE },
{ "no_recall", ROOM_NO_RECALL, TRUE },
{ "cone_of_silence", ROOM_CONE_OF_SILENCE, TRUE },
{ "arena", ROOM_ARENA, TRUE },
{ "", 0, 0 }
};
const struct flag_type sector_flags[] =
{
{ "inside", SECT_INSIDE, TRUE },
{ "city", SECT_CITY, TRUE },
{ "field", SECT_FIELD, TRUE },
{ "forest", SECT_FOREST, TRUE },
{ "hills", SECT_HILLS, TRUE },
{ "mountain", SECT_MOUNTAIN, TRUE },
{ "swim", SECT_WATER_SWIM, TRUE },
{ "noswim", SECT_WATER_NOSWIM, TRUE },
{ "underwater", SECT_UNDERWATER, TRUE },
{ "air", SECT_AIR, TRUE },
{ "desert", SECT_DESERT, TRUE },
{ "", 0, 0 }
};
const struct flag_type type_flags[] =
{
{ "light", ITEM_LIGHT, TRUE },
{ "scroll", ITEM_SCROLL, TRUE },
{ "wand", ITEM_WAND, TRUE },
{ "staff", ITEM_STAFF, TRUE },
{ "weapon", ITEM_WEAPON, TRUE },
{ "treasure", ITEM_TREASURE, TRUE },
{ "armor", ITEM_ARMOR, TRUE },
{ "potion", ITEM_POTION, TRUE },
{ "furniture", ITEM_FURNITURE, TRUE },
{ "trash", ITEM_TRASH, TRUE },
{ "container", ITEM_CONTAINER, TRUE },
{ "drink-container", ITEM_DRINK_CON, TRUE },
{ "key", ITEM_KEY, TRUE },
{ "food", ITEM_FOOD, TRUE },
{ "money", ITEM_MONEY, TRUE },
{ "boat", ITEM_BOAT, TRUE },
{ "npc corpse", ITEM_CORPSE_NPC, TRUE },
{ "pc corpse", ITEM_CORPSE_PC, FALSE },
{ "fountain", ITEM_FOUNTAIN, TRUE },
{ "pill", ITEM_PILL, TRUE },
{ "portal", ITEM_PORTAL, TRUE },
{ "warp stone", ITEM_WARP_STONE, TRUE },
{ "", 0, 0 }
};
const struct flag_type extra_flags[] =
{
{ "glow", ITEM_GLOW, TRUE },
{ "hum", ITEM_HUM, TRUE },
{ "dark", ITEM_DARK, TRUE },
{ "lock", ITEM_LOCK, TRUE },
{ "evil", ITEM_EVIL, TRUE },
{ "invis", ITEM_INVIS, TRUE },
{ "magic", ITEM_MAGIC, TRUE },
{ "nodrop", ITEM_NODROP, TRUE },
{ "bless", ITEM_BLESS, TRUE },
{ "anti-good", ITEM_ANTI_GOOD, TRUE },
{ "anti-evil", ITEM_ANTI_EVIL, TRUE },
{ "anti-neutral", ITEM_ANTI_NEUTRAL, TRUE },
{ "noremove", ITEM_NOREMOVE, TRUE },
{ "inventory", ITEM_INVENTORY, TRUE },
{ "poisoned", ITEM_POISONED, TRUE },
{ "vampire-bane", ITEM_VAMPIRE_BANE, TRUE },
{ "holy", ITEM_HOLY, TRUE },
{ "visible death", ITEM_VIS_DEATH, TRUE },
{ "", 0, 0 }
};
const struct flag_type wear_flags[] =
{
{ "take", ITEM_TAKE, TRUE },
{ "finger", ITEM_WEAR_FINGER, TRUE },
{ "neck", ITEM_WEAR_NECK, TRUE },
{ "body", ITEM_WEAR_BODY, TRUE },
{ "head", ITEM_WEAR_HEAD, TRUE },
{ "legs", ITEM_WEAR_LEGS, TRUE },
{ "feet", ITEM_WEAR_FEET, TRUE },
{ "hands", ITEM_WEAR_HANDS, TRUE },
{ "arms", ITEM_WEAR_ARMS, TRUE },
{ "shield", ITEM_WEAR_SHIELD, TRUE },
{ "about", ITEM_WEAR_ABOUT, TRUE },
{ "waist", ITEM_WEAR_WAIST, TRUE },
{ "wrist", ITEM_WEAR_WRIST, TRUE },
{ "wield", ITEM_WIELD, TRUE },
{ "hold", ITEM_HOLD, TRUE },
{ "", 0, 0 }
};
const struct flag_type act_flags[] =
{
{ "npc", ACT_IS_NPC, FALSE },
{ "sentinel", ACT_SENTINEL, TRUE },
{ "scavenger", ACT_SCAVENGER, TRUE },
{ "aggressive", ACT_AGGRESSIVE, TRUE },
{ "stay_area", ACT_STAY_AREA, TRUE },
{ "wimpy", ACT_WIMPY, TRUE },
{ "pet", ACT_PET, TRUE },
{ "train", ACT_TRAIN, TRUE },
{ "practice", ACT_PRACTICE, TRUE },
{ "gamble", ACT_GAMBLE, TRUE },
{ "", 0, 0 }
};
const struct flag_type affect_flags[] =
{
{ "blind", AFF_BLIND, TRUE },
{ "invisible", AFF_INVISIBLE, TRUE },
{ "detect-evil", AFF_DETECT_EVIL, TRUE },
{ "detect-invis", AFF_DETECT_INVIS, TRUE },
{ "detect-magic", AFF_DETECT_MAGIC, TRUE },
{ "detect-hidden", AFF_DETECT_HIDDEN, TRUE },
{ "hold", AFF_HOLD, TRUE },
{ "sanctuary", AFF_SANCTUARY, TRUE },
{ "faerie-fire", AFF_FAERIE_FIRE, TRUE },
{ "infrared", AFF_INFRARED, TRUE },
{ "curse", AFF_CURSE, TRUE },
{ "poison", AFF_POISON, TRUE },
{ "protect-evil", AFF_PROTECT_EVIL, TRUE },
{ "sneak", AFF_SNEAK, TRUE },
{ "hide", AFF_HIDE, TRUE },
{ "sleep", AFF_SLEEP, TRUE },
{ "charm", AFF_CHARM, TRUE },
{ "flying", AFF_FLYING, TRUE },
{ "pass-door", AFF_PASS_DOOR, TRUE },
{ "waterwalk", AFF_WATERWALK, TRUE },
{ "summoned", AFF_SUMMONED, TRUE },
{ "mute", AFF_MUTE, TRUE },
{ "gills", AFF_GILLS, TRUE },
{ "vamp-bite", AFF_VAMP_BITE, TRUE },
{ "ghoul", AFF_GHOUL, TRUE },
{ "flaming", AFF_FLAMING, TRUE },
{ "detect-good", AFF_DETECT_GOOD, TRUE },
{ "protect-good", AFF_PROTECT_GOOD, TRUE },
{ "", 0, 0 }
};
/*
* Used when adding an affect to tell where it goes.
* See addaffect and delaffect in act_olc.c
*/
const struct flag_type apply_flags[] =
{
{ "none", APPLY_NONE, TRUE },
{ "strength", APPLY_STR, TRUE },
{ "dexterity", APPLY_DEX, TRUE },
{ "intelligence", APPLY_INT, TRUE },
{ "wisdom", APPLY_WIS, TRUE },
{ "constitution", APPLY_CON, TRUE },
{ "sex", APPLY_SEX, TRUE },
{ "class", APPLY_CLASS, TRUE },
{ "level", APPLY_LEVEL, TRUE },
{ "age", APPLY_AGE, TRUE },
{ "height", APPLY_HEIGHT, TRUE },
{ "weight", APPLY_WEIGHT, TRUE },
{ "mana", APPLY_MANA, TRUE },
{ "hp", APPLY_HIT, TRUE },
{ "move", APPLY_MOVE, TRUE },
{ "gold", APPLY_GOLD, TRUE },
{ "experience", APPLY_EXP, TRUE },
{ "ac", APPLY_AC, TRUE },
{ "hitroll", APPLY_HITROLL, TRUE },
{ "damroll", APPLY_DAMROLL, TRUE },
{ "saving-para", APPLY_SAVING_PARA, TRUE },
{ "saving-rod", APPLY_SAVING_ROD, TRUE },
{ "saving-petri", APPLY_SAVING_PETRI, TRUE },
{ "saving-breath", APPLY_SAVING_BREATH, TRUE },
{ "saving-spell", APPLY_SAVING_SPELL, TRUE },
{ "race", APPLY_RACE, TRUE },
{ "", 0, 0 }
};
/*
* What is seen.
*/
const struct flag_type wear_loc_strings[] =
{
{ "in the inventory", WEAR_NONE, TRUE },
{ "as a light", WEAR_LIGHT, TRUE },
{ "on the left finger", WEAR_FINGER_L, TRUE },
{ "on the right finger", WEAR_FINGER_R, TRUE },
{ "around the neck (1)", WEAR_NECK_1, TRUE },
{ "around the neck (2)", WEAR_NECK_2, TRUE },
{ "on the body", WEAR_BODY, TRUE },
{ "over the head", WEAR_HEAD, TRUE },
{ "on the legs", WEAR_LEGS, TRUE },
{ "on the feet", WEAR_FEET, TRUE },
{ "on the hands", WEAR_HANDS, TRUE },
{ "on the arms", WEAR_ARMS, TRUE },
{ "as a shield", WEAR_SHIELD, TRUE },
{ "about the shoulders", WEAR_ABOUT, TRUE },
{ "around the waist", WEAR_WAIST, TRUE },
{ "on the left wrist", WEAR_WRIST_L, TRUE },
{ "on the right wrist", WEAR_WRIST_R, TRUE },
{ "wielded", WEAR_WIELD, TRUE },
{ "held in the hands", WEAR_HOLD, TRUE },
{ "second wield", WEAR_WIELD_2, TRUE },
{ "", 0, 0 }
};
/*
* What is typed.
* Neck2 should not be settable for loaded mobiles.
*/
const struct flag_type wear_loc_flags[] =
{
{ "none", WEAR_NONE, TRUE },
{ "light", WEAR_LIGHT, TRUE },
{ "lfinger", WEAR_FINGER_L, TRUE },
{ "rfinger", WEAR_FINGER_R, TRUE },
{ "neck1", WEAR_NECK_1, TRUE },
{ "neck2", WEAR_NECK_2, TRUE },
{ "body", WEAR_BODY, TRUE },
{ "head", WEAR_HEAD, TRUE },
{ "legs", WEAR_LEGS, TRUE },
{ "feet", WEAR_FEET, TRUE },
{ "hands", WEAR_HANDS, TRUE },
{ "arms", WEAR_ARMS, TRUE },
{ "shield", WEAR_SHIELD, TRUE },
{ "about", WEAR_ABOUT, TRUE },
{ "waist", WEAR_WAIST, TRUE },
{ "lwrist", WEAR_WRIST_L, TRUE },
{ "rwrist", WEAR_WRIST_R, TRUE },
{ "wielded", WEAR_WIELD, TRUE },
{ "hold", WEAR_HOLD, TRUE },
{ "sec_wield", WEAR_WIELD_2, TRUE },
{ "", 0, 0 }
};
const struct flag_type weapon_flags[] =
{
{ "hit", 0, TRUE },
{ "slice", 1, TRUE },
{ "stab", 2, TRUE },
{ "slash", 3, TRUE },
{ "whip", 4, TRUE },
{ "claw", 5, TRUE },
{ "blast", 6, TRUE },
{ "pound", 7, TRUE },
{ "crush", 8, TRUE },
{ "grep", 9, TRUE },
{ "bite", 10, TRUE },
{ "pierce", 11, TRUE },
{ "suction", 12, TRUE },
{ "chop", 13, TRUE },
{ "", 0, 0 }
};
const struct flag_type container_flags[] =
{
{ "closeable", 1, TRUE },
{ "pickproof", 2, TRUE },
{ "closed", 4, TRUE },
{ "locked", 8, TRUE },
{ "", 0, 0 }
};
const struct flag_type portal_door_flags[] =
{
{ "closeable", 1, TRUE },
{ "pickproof", 2, TRUE },
{ "closed", 4, TRUE },
{ "locked", 8, TRUE },
{ "", 0, 0 }
};
const struct flag_type portal_flags[] =
{
{ "nocursed", 1, TRUE },
{ "gowithchar", 2, TRUE },
{ "random", 4, TRUE },
{ "buggy", 8, TRUE },
{ "", 0, 0 }
};
const struct flag_type liquid_flags[] =
{
{ "water", 0, TRUE },
{ "beer", 1, TRUE },
{ "wine", 2, TRUE },
{ "ale", 3, TRUE },
{ "dark-ale", 4, TRUE },
{ "whisky", 5, TRUE },
{ "lemonade", 6, TRUE },
{ "firebreather", 7, TRUE },
{ "local-specialty", 8, TRUE },
{ "slime-mold-juice", 9, TRUE },
{ "milk", 10, TRUE },
{ "tea", 11, TRUE },
{ "coffee", 12, TRUE },
{ "blood", 13, TRUE },
{ "salt-water", 14, TRUE },
{ "cola", 15, TRUE },
{ "white wine", 16, TRUE },
{ "root beer", 17, TRUE },
{ "champagne", 18, TRUE },
{ "vodka", 19, TRUE },
{ "absinth", 20, TRUE },
{ "brandy", 21, TRUE },
{ "schnapps", 22, TRUE },
{ "orange juice", 23, TRUE },
{ "sherry", 24, TRUE },
{ "rum", 25, TRUE },
{ "port", 26, TRUE },
{ "", 0, 0 }
};
/*
* For MobPrograms
*/
const struct flag_type mprog_type_flags[] =
{
{ "in_file_prog", IN_FILE_PROG, TRUE },
{ "act_prog", ACT_PROG, TRUE },
{ "speech_prog", SPEECH_PROG, TRUE },
{ "rand_prog", RAND_PROG, TRUE },
{ "fight_prog", FIGHT_PROG, TRUE },
{ "hitprcnt_prog", HITPRCNT_PROG, TRUE },
{ "death_prog", DEATH_PROG, TRUE },
{ "entry_prog", ENTRY_PROG, TRUE },
{ "greet_prog", GREET_PROG, TRUE },
{ "all_greet_prog", ALL_GREET_PROG, TRUE },
{ "give_prog", GIVE_PROG, TRUE },
{ "bribe_prog", BRIBE_PROG, TRUE },
{ "", 0, 0 }
};
/*
* Race types for medit - Envy 2.x version
* New table by Stoked for OLC
*/
const struct flag_type race_flags[] =
{
{ "Human", 0, TRUE },
{ "Elf", 1, TRUE },
{ "Halfelf", 2, TRUE },
{ "Drow", 3, TRUE },
{ "Dwarf", 4, TRUE },
{ "Halfdwarf", 5, TRUE },
{ "Hobbit", 6, TRUE },
{ "Giant", 7, TRUE },
{ "Ogre", 8, TRUE },
{ "Orc", 9, TRUE },
{ "Kobold", 10, TRUE },
{ "Minotaur", 11, TRUE },
{ "Troll", 12, TRUE },
{ "Hobgoblin", 13, TRUE },
{ "Insect", 14, TRUE },
{ "Dragon", 15, TRUE },
{ "Animal", 16, TRUE },
{ "God", 17, TRUE },
{ "Undead", 18, TRUE },
{ "Harpy", 19, TRUE },
{ "Bear", 20, TRUE },
{ "Githyanki", 21, TRUE },
{ "Elemental", 22, TRUE },
{ "Bat", 23, TRUE },
{ "Plant", 24, TRUE },
{ "Rat", 25, TRUE },
{ "Vampire", 26, TRUE },
{ "Werewolf", 27, TRUE },
{ "Goblin", 28, TRUE },
{ "Faerie", 29, TRUE },
{ "Arachnid", 30, TRUE },
{ "Mindflayer", 31, TRUE },
{ "Object", 32, TRUE },
{ "Mist", 33, TRUE },
{ "Snake", 34, TRUE },
{ "Worm", 35, TRUE },
{ "Fish", 36, TRUE },
{ "Hydra", 37, TRUE },
{ "Lizard", 38, TRUE },
{ "Gnome", 39, TRUE },
{ "Halfkobold", 40, TRUE },
{ "", 0, 0 }
};