/***************************************************************
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);
}