crodo_mud/cnf/
crodo_mud/lib/
crodo_mud/lib/house/
crodo_mud/lib/misc/
crodo_mud/lib/plralias/F-J/
crodo_mud/lib/plralias/U-Z/
crodo_mud/lib/plrobjs/
crodo_mud/lib/plrvars/A-E/
crodo_mud/lib/plrvars/F-J/
crodo_mud/lib/plrvars/K-O/
crodo_mud/lib/plrvars/P-T/
crodo_mud/lib/plrvars/U-Z/
crodo_mud/lib/text/
crodo_mud/lib/text/help/
crodo_mud/lib/world/
crodo_mud/src/
/***************************************************************
Money.c - by Muerte of CrodoMud (telnet://crodomud.crodo.com 4000)
****************************************************************/

#include "conf.h"
#include "sysdep.h"

#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "handler.h"
#include "interpreter.h"
#include "db.h"
#include "spells.h"
#include "screen.h"
#include "constants.h"
#include "dg_scripts.h"
#include "money.h"

/* External Structures/Variables */
extern struct room_data *world;

/* Functions */
void add_cash_to_char(struct char_data *ch, int amount, int type) {

struct obj_data *obj, *next_obj;
int cur_amount = amount;

 /* Search through carried items for coins of proper type */

        for (obj = ch->carrying; obj; obj = next_obj) {
          next_obj = obj->next_content;
          
	if ((GET_OBJ_TYPE(obj) == ITEM_MONEY) &&
           (GET_OBJ_VAL(obj, type) > 0)) {
           cur_amount += GET_OBJ_VAL(obj, type);
           GET_OBJ_VAL(obj, type) += amount;
	   restring_money_obj(obj, cur_amount, type);
           break; }
        }

 /* No money of this type found, create a new one */
       if (obj == NULL) {
	obj = create_money(cur_amount, type);
        obj_to_eoi(obj, ch); }

        GET_GOLD(ch) += value_in_copper(amount, type);
	}

void sub_cash_from_char(struct char_data *ch, int amount, int type) {

struct obj_data *obj, *next_obj;
int cur_amount = 0;

 /* Search through carried items for coins of proper type */

        for (obj = ch->carrying; obj; obj = next_obj) {
          next_obj = obj->next_content;
    
        if ((GET_OBJ_TYPE(obj) == ITEM_MONEY) &&
           (GET_OBJ_VAL(obj, type) > 0)) {
           cur_amount = (GET_OBJ_VAL(obj, type) - amount);
           GET_OBJ_VAL(obj, type) = cur_amount;
           if (cur_amount > 0)
           restring_money_obj(obj, cur_amount, type);
           break; }   
        }

 /* Emptied out this type of currency */
  
        if (cur_amount < 1) 
	 extract_obj(obj);

        GET_GOLD(ch) -= value_in_copper(amount, type);

 /* Went negative (Immoratls loading into inv, then dropping) */

        if (GET_GOLD(ch)  < 0) {
         log("SYSERR: Char %s went negative. coins: %d room: %d",
         GET_NAME(ch), GET_GOLD(ch), GET_ROOM_VNUM(IN_ROOM(ch)));
	 GET_GOLD(ch) = 0;
 }

        }

struct obj_data *create_money(int amount, int type)
{
  struct obj_data *obj;
  obj_rnum r_num;
      
  if (amount < 1) {
    log("SYSERR: Try to create negative or 0 money. (%d)", amount);
    return (NULL);
  }

  r_num = real_object(7);
  obj = read_object(r_num, REAL);

  restring_money_obj(obj, amount, type);

  GET_OBJ_TYPE(obj) = ITEM_MONEY;
  GET_OBJ_WEAR(obj) = ITEM_WEAR_TAKE;
  GET_OBJ_VAL(obj, type) = amount;
  GET_OBJ_COST(obj) = amount;
  GET_OBJ_WEIGHT(obj) = amount * coin_weight[type];
  return (obj);
}


char *money_desc(int amount, int type)
{
  static char buf[128];
  
  if (amount <= 0) {
    log("SYSERR: Try to create negative or 0 money (%d).", amount);
    return (NULL);
  }
  if (amount == 1)
    sprintf(buf, "a %s coin", coin_types[type]);
  else if (amount <= 10)
    sprintf(buf, "a tiny pile of %s coins", coin_types[type]);
  else if (amount <= 20)
    sprintf(buf, "a handful of %s coins", coin_types[type]);
  else if (amount <= 75)
    sprintf(buf, "a little pile of %s coins", coin_types[type]);
  else if (amount <= 200)
    sprintf(buf, "a small pile of %s coins", coin_types[type]);
  else if (amount <= 1000)
    sprintf(buf, "a pile of %s coins", coin_types[type]);
  else if (amount <= 5000)
    sprintf(buf, "a big pile of %s coins", coin_types[type]);
  else if (amount <= 10000)
    sprintf(buf, "a large heap of %s coins", coin_types[type]);
  else if (amount <= 20000)
    sprintf(buf, "a huge mound of %s coins", coin_types[type]);
  else if (amount <= 75000)
    sprintf(buf, "an enormous mound of %s coins", coin_types[type]);
  else if (amount <= 150000)
    sprintf(buf, "a small mountain of %s coins", coin_types[type]);
  else if (amount <= 250000)
    sprintf(buf, "a mountain of %s coins", coin_types[type]);
  else if (amount <= 500000)
    sprintf(buf, "a huge mountain of %s coins", coin_types[type]);
  else if (amount <= 1000000)
    sprintf(buf, "an enormous mountain of %s coins", coin_types[type]);
  else
    sprintf(buf, "an absolutely colossal mountain of %s coins", coin_types[type]);
  
  return (buf);
}
   
int get_money(struct char_data *ch, int type) {

struct obj_data *obj, *next_obj;
int cur_amount = 0;

 /* Search through carried items for coins of proper type */

        for (obj = ch->carrying; obj; obj = next_obj) {
          next_obj = obj->next_content;

        if ((GET_OBJ_TYPE(obj) == ITEM_MONEY) &&
           (GET_OBJ_VAL(obj, type) > 0)) 
           cur_amount = GET_OBJ_VAL(obj, type);
        }

	return(cur_amount);
        }

/* give an object to the end of a char's inventory   */
void obj_to_eoi(struct obj_data *object, struct char_data *ch)
{
struct obj_data *last_obj;

  if (!object || !ch)
    return;

  /* Not carrying anything? */

   if (ch->carrying == NULL) {
     obj_to_char(object, ch);
     return; }

 /* Get last object in char's inventory */
   
     last_obj = ch->carrying;
     
     while (last_obj->next_content) {
      last_obj = last_obj->next_content;
                                }
 
    last_obj->next_content = object;
    object->next_content = NULL;
    object->carried_by = ch;
    object->in_room = NOWHERE; 
    IS_CARRYING_W(ch) += GET_OBJ_WEIGHT(object);
    IS_CARRYING_N(ch)++;

    /* set flag for crash-save system, but not on mobs! */
    if (!IS_NPC(ch))
      SET_BIT(PLR_FLAGS(ch), PLR_CRASH);

}


int value_in_copper(int amount, int type) {

int modifier = 0;

 switch (type) {

  case COIN_COPPER:
   modifier = COPPER_VALUE;
  break;
  case COIN_SILVER:
   modifier = SILVER_VALUE;
  break;
  case COIN_ELECTRUM:
   modifier = ELECTRUM_VALUE;
  break;
  case COIN_GOLD:
   modifier = GOLD_VALUE;
  break;
  case COIN_PLAT:
   modifier = PLAT_VALUE;
 break;
  default:
  /* Illegal coin type passed */
   return (0);
  break;
}
 
  return (amount * modifier);

}

void add_cash_from_copper(struct char_data *ch, int copper)
{
int plat = 0, gold = 0, electrum = 0, silver = 0, remainder = 0;

  if (copper <= 0)
   return;

  remainder = copper;

  plat = (remainder / PLAT_VALUE);

  if (plat > 0) {
  remainder -= (plat * PLAT_VALUE);
  add_cash_to_char(ch, plat, COIN_PLAT);
  }
 
 if (remainder > 0)
   gold = (remainder / GOLD_VALUE);

  if (gold > 0) {
  remainder -= (gold * GOLD_VALUE);
  add_cash_to_char(ch, gold, COIN_GOLD);
  }

   if (remainder > 0)
    electrum = (remainder / ELECTRUM_VALUE);

  if (electrum > 0) {
  remainder -= (electrum * ELECTRUM_VALUE);
  add_cash_to_char(ch, electrum, COIN_ELECTRUM);  
  }

   if (remainder > 0)
    silver = (remainder / SILVER_VALUE);

  if (silver > 0) {
  remainder -= (silver * SILVER_VALUE);
  add_cash_to_char(ch, silver, COIN_SILVER);
  }

  if (remainder > 0)
  add_cash_to_char(ch, remainder, COIN_COPPER);

}
void sub_cash_from_copper(struct char_data *ch, int copper)
{
   int plat = 0, gold = 0, elec = 0, silv = 0, copp = 0, total = 0;

   if (copper <= 0)
    return;

  total = GET_GOLD(ch);

  plat = get_money(ch, COIN_PLAT);
  if (plat > 0)
   sub_cash_from_char(ch, plat, COIN_PLAT);

  gold = get_money(ch, COIN_GOLD);
  if (gold > 0)
   sub_cash_from_char(ch, gold, COIN_GOLD);

  elec = get_money(ch, COIN_ELECTRUM);
  if (elec > 0)
   sub_cash_from_char(ch, elec, COIN_ELECTRUM);

  silv = get_money(ch, COIN_SILVER);
  if (silv > 0)
   sub_cash_from_char(ch, silv, COIN_SILVER);

  copp = get_money(ch, COIN_COPPER);
  if (copp > 0)
   sub_cash_from_char(ch, copp, COIN_COPPER);

  total -= copper;

  add_cash_from_copper(ch, total);

}

int money_obj_value(struct obj_data *obj) {

  int copper = 0;

   copper = (value_in_copper(GET_OBJ_VAL(obj, COIN_COPPER), COIN_COPPER) +
             value_in_copper(GET_OBJ_VAL(obj, COIN_SILVER), COIN_SILVER) +
             value_in_copper(GET_OBJ_VAL(obj, COIN_ELECTRUM), COIN_ELECTRUM) +
             value_in_copper(GET_OBJ_VAL(obj, COIN_GOLD), COIN_GOLD) +
             value_in_copper(GET_OBJ_VAL(obj, COIN_PLAT), COIN_PLAT));  

 return (copper);
}

int char_cash_in_copper(struct char_data *ch) {
   int copper;

   copper = (value_in_copper(get_money(ch, COIN_COPPER), COIN_COPPER) +
	    value_in_copper(get_money(ch, COIN_SILVER), COIN_SILVER) +
	    value_in_copper(get_money(ch, COIN_ELECTRUM), COIN_ELECTRUM) +
            value_in_copper(get_money(ch, COIN_GOLD), COIN_GOLD) +
            value_in_copper(get_money(ch, COIN_PLAT), COIN_PLAT) );

   return (copper);
}


int get_money_type(struct obj_data *obj) {

int type = -1;
int mixed = -1;

    if (GET_OBJ_TYPE(obj) != ITEM_MONEY)
     return -1;
    
     if (GET_OBJ_VAL(obj, COIN_COPPER) > 0) {
      type = 0;  
      mixed++; }

     if (GET_OBJ_VAL(obj, COIN_SILVER) > 0) {
      type = 1; 
      mixed++; }      

     if (GET_OBJ_VAL(obj, COIN_ELECTRUM) > 0) {
      type = 2; 
      mixed++; }

     if (GET_OBJ_VAL(obj, COIN_GOLD) > 0) {
      type = 3; 
      mixed++; }

     if (GET_OBJ_VAL(obj, COIN_PLAT) > 0) {
      type = 4;
      mixed++; }

     if (mixed > 0)
      type = 5;

     return (type);

}

char *expand_copper(int copper, int brief)
{
  static char buffer[128];
  int plat = 0, gold = 0, electrum = 0, silver = 0, remainder = 0;
    
  *buffer = '\0';
  remainder = copper;

  plat = (remainder / PLAT_VALUE);
  remainder -= (plat * PLAT_VALUE);

  if (remainder > 0)
   gold = (remainder / GOLD_VALUE);
   
  remainder -= (gold * GOLD_VALUE);

   if (remainder > 0)
    electrum = (remainder / ELECTRUM_VALUE);
   
  remainder -= (electrum * ELECTRUM_VALUE);

   if (remainder > 0)
    silver = (remainder / SILVER_VALUE);

  remainder -= (silver * SILVER_VALUE);

  if (brief == 1) {

    if (plat > 0)
     sprintf(buffer + strlen(buffer), " %dp", plat);
    if (gold > 0) 
     sprintf(buffer + strlen(buffer), " %dg", gold);
    if (electrum > 0)
     sprintf(buffer + strlen(buffer), " %de", electrum);
    if (silver > 0)
     sprintf(buffer + strlen(buffer), " %ds", silver);
    if (remainder > 0)
     sprintf(buffer + strlen(buffer), " %dc", remainder);

} else {
    if (plat > 0)
     sprintf(buffer + strlen(buffer), " %d platinum", plat);
    if (gold > 0)
     sprintf(buffer + strlen(buffer), " %d gold", gold);
    if (electrum > 0)
     sprintf(buffer + strlen(buffer), " %d electrum", electrum);
    if (silver > 0)
     sprintf(buffer + strlen(buffer), " %d silver", silver);
    if (remainder > 0)
     sprintf(buffer + strlen(buffer), " %d copper", remainder);
}
  return (buffer);
}

int parse_cash_type(const char *currency) {

int type = -1;

    if (!strcmp(currency, "platinum") || is_abbrev(currency, "platinum"))
       type = COIN_PLAT;
    else if (!strcmp(currency, "gold") || is_abbrev(currency, "gold"))
       type = COIN_GOLD;
    else if (!strcmp(currency, "electrum") || is_abbrev(currency, "electrum"))
       type = COIN_ELECTRUM;
    else if (!strcmp(currency, "silver") || is_abbrev(currency, "silver")) 
       type = COIN_SILVER;
    else if (!strcmp(currency, "copper") || is_abbrev(currency, "copper"))
       type = COIN_COPPER;

       return (type);
    }

struct obj_data *get_pile_in_list(struct obj_data *list) {

struct obj_data *pile;

  for (pile = list; pile; pile = pile->next_content) {
	if (GET_OBJ_TYPE(pile) == ITEM_MONEY)
	 return (pile);
}

return NULL;
}

void add_money_to_pile(struct obj_data *money, struct obj_data *pile) {

int value[NUM_COIN_TYPES], i, type, amount;

  /* Store value of currency going into the pile */
  for (i = 0; i < NUM_COIN_TYPES; i++)
   value[i] = GET_OBJ_VAL(money, i);

  /* Add it to the current pile */
  for (i = 0; i < NUM_COIN_TYPES; i++)
   GET_OBJ_VAL(pile, i) += value[i];

  /* Grab the new currency type */
  type = get_money_type(pile);

  /* And it's value */
  amount = money_obj_value(pile);

  /* Update the pile's strings */
  restring_money_obj(pile, amount, type);
 
  /* Discard the money going in */
  extract_obj(money);

 }


void restring_money_obj(struct obj_data *obj, int amount, int type)
{       
  char buf[200];

  /* Allocate extra description space if needed (new obj) */
       if (obj->ex_description == NULL) {
       CREATE(obj->ex_description, struct extra_descr_data, 1);
       obj->ex_description->next = NULL; }
      
  if (amount == 1) {
    sprintf(buf, "coin coins %s", coin_types[type]);
    obj->name = str_dup(buf);
    sprintf(buf, "%s %s coin", type != COIN_ELECTRUM ? "a" 
	    : "an" , coin_types[type]);
    obj->short_description = str_dup(buf);
    sprintf(buf, "One miserable %s coin is lying here.", coin_types[type]);
    obj->description = str_dup(buf);
    sprintf(buf, "coin coins %s", coin_types[type]);
    obj->ex_description->keyword = str_dup(buf);
    sprintf(buf, "It's just one miserable little %s coin.", coin_types[type]);
    obj->ex_description->description = str_dup(buf);
  } else {
    sprintf(buf, "coin coins %s", coin_types[type]);
    obj->name = str_dup(buf);
    obj->short_description = str_dup(money_desc(amount, type));
    sprintf(buf, "%s is lying here.", money_desc(amount, type));
    obj->description = str_dup(CAP(buf));
    sprintf(buf, "coins %s", coin_types[type]);
    obj->ex_description->keyword = str_dup(buf);
    if (amount < 10) {
      sprintf(buf, "There are %d %s coins.", amount, coin_types[type]);
      obj->ex_description->description = str_dup(buf);
    } else if (amount < 100) {
      sprintf(buf, "There are about %d %s coins.", 10 * (amount / 10), coin_types[type]);
      obj->ex_description->description = str_dup(buf);
    } else if (amount < 1000) {
      sprintf(buf, "It looks to be about %d %s coins.", 100 * (amount / 100), coin_types[type]);
      obj->ex_description->description = str_dup(buf);
    } else if (amount < 100000) {
      sprintf(buf, "You guess there are, maybe, %d %s coins.",
              1000 * ((amount / 1000) + number(0, (amount / 1000))), coin_types[type]);
      obj->ex_description->description = str_dup(buf);
    } else
      obj->ex_description->description = str_dup("There are a LOT of coins.");
  }

}
 
void sub_money_from_pile(struct obj_data *pile, int amount, int type) {
  
 int cur_amount;

   GET_OBJ_VAL(pile, type) -= amount;
    
  /* Grab the new currency type */
  type = get_money_type(pile);

  /* And it's value */
  cur_amount = money_obj_value(pile);

 /* Did we empty the pile out? */
  if (cur_amount == 0) {
   extract_obj(pile);
   return; }

  /* Update the pile's strings */
  restring_money_obj(pile, amount, type);

 }