--- deliantra/server/server/shop.C 2006/09/07 10:01:58 1.9 +++ deliantra/server/server/shop.C 2006/09/10 15:59:57 1.10 @@ -1,6 +1,7 @@ + /* * static char *rcsid_shop_c = - * "$Id: shop.C,v 1.9 2006/09/07 10:01:58 pippijn Exp $"; + * "$Id: shop.C,v 1.10 2006/09/10 15:59:57 root Exp $"; */ /* @@ -32,7 +33,7 @@ #include #include #ifndef __CEXTRACT__ -#include +# include #endif #include @@ -48,13 +49,13 @@ /* price a shopkeeper will give someone they neither like nor dislike */ #define NEUTRAL_RATIO 0.8 -static uint64 pay_from_container(object *pl, object *pouch, uint64 to_pay); -static uint64 value_limit(uint64 val, int quantity, const object *who, int isshop); -static double shop_specialisation_ratio(const object *item, const mapstruct *map); -static double shop_greed(const mapstruct *map); +static uint64 pay_from_container (object *pl, object *pouch, uint64 to_pay); +static uint64 value_limit (uint64 val, int quantity, const object *who, int isshop); +static double shop_specialisation_ratio (const object *item, const mapstruct *map); +static double shop_greed (const mapstruct *map); -#define NUM_COINS 4 /* number of coin types */ -static const char* const coins[] = {"royalty", "platinacoin", "goldcoin", "silvercoin", NULL}; +#define NUM_COINS 4 /* number of coin types */ +static const char *const coins[] = { "royalty", "platinacoin", "goldcoin", "silvercoin", NULL }; /* Added F_TRUE flag to define.h to mean that the price should not * be adjusted by players charisma. With F_TRUE, it returns the amount @@ -83,241 +84,261 @@ static uint64 approx_range; -uint64 query_cost(const object *tmp, object *who, int flag) { - double val; - int number; /* used to better calculate value */ - int no_bargain; - int identified; - int not_cursed; - int approximate; - int shop; - double diff; - - approx_range = 0; - - no_bargain = flag & F_NO_BARGAIN; - identified = flag & F_IDENTIFIED; - not_cursed = flag & F_NOT_CURSED; - approximate = flag & F_APPROX; - shop = flag & F_SHOP; - flag &= ~(F_NO_BARGAIN|F_IDENTIFIED|F_NOT_CURSED|F_APPROX|F_SHOP); - - if (tmp->type==MONEY) return (tmp->nrof * tmp->value); - if (tmp->type==GEM) { - if (flag==F_TRUE) return (tmp->nrof * tmp->value); - if (flag==F_BUY) return (uint64) (1.03 * tmp->nrof * tmp->value); - if (flag==F_SELL) return (uint64) (0.97 * tmp->nrof * tmp->value); - LOG(llevError,"Query_cost: Gem type with unknown flag : %d\n", flag); +uint64 +query_cost (const object *tmp, object *who, int flag) +{ + double val; + int number; /* used to better calculate value */ + int no_bargain; + int identified; + int not_cursed; + int approximate; + int shop; + double diff; + + approx_range = 0; + + no_bargain = flag & F_NO_BARGAIN; + identified = flag & F_IDENTIFIED; + not_cursed = flag & F_NOT_CURSED; + approximate = flag & F_APPROX; + shop = flag & F_SHOP; + flag &= ~(F_NO_BARGAIN | F_IDENTIFIED | F_NOT_CURSED | F_APPROX | F_SHOP); + + if (tmp->type == MONEY) + return (tmp->nrof * tmp->value); + if (tmp->type == GEM) + { + if (flag == F_TRUE) + return (tmp->nrof * tmp->value); + if (flag == F_BUY) + return (uint64) (1.03 * tmp->nrof * tmp->value); + if (flag == F_SELL) + return (uint64) (0.97 * tmp->nrof * tmp->value); + LOG (llevError, "Query_cost: Gem type with unknown flag : %d\n", flag); + return 0; + } + number = tmp->nrof; + if (number == 0) + number = 1; + if (QUERY_FLAG (tmp, FLAG_IDENTIFIED) || !need_identify (tmp) || identified) + { + if (!not_cursed && (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED))) return 0; + else + val = tmp->value * number; } - number = tmp->nrof; - if (number==0) number=1; - if (QUERY_FLAG(tmp, FLAG_IDENTIFIED) || !need_identify(tmp) || identified) { - if (!not_cursed && (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED))) - return 0; - else - val=tmp->value * number; - } - /* This area deals with objects that are not identified, but can be */ - else { - if (tmp->arch != NULL) { - if (flag == F_BUY) { - LOG(llevError, "Asking for buy-value of unidentified object.\n"); - val = tmp->arch->clone.value * 50 * number; + /* This area deals with objects that are not identified, but can be */ + else + { + if (tmp->arch != NULL) + { + if (flag == F_BUY) + { + LOG (llevError, "Asking for buy-value of unidentified object.\n"); + val = tmp->arch->clone.value * 50 * number; } - else { /* Trying to sell something, or get true value */ - if (tmp->type == POTION) - val = number * 40; /* Don't want to give anything away */ - else { - /* Get 2/3'rd value for applied objects, 1/3'rd for totally - * unknown objects - */ - if (QUERY_FLAG(tmp, FLAG_BEEN_APPLIED)) - val = number * tmp->arch->clone.value *2 / 3; - else - val = number * tmp->arch->clone.value / 3; + else + { /* Trying to sell something, or get true value */ + if (tmp->type == POTION) + val = number * 40; /* Don't want to give anything away */ + else + { + /* Get 2/3'rd value for applied objects, 1/3'rd for totally + * unknown objects + */ + if (QUERY_FLAG (tmp, FLAG_BEEN_APPLIED)) + val = number * tmp->arch->clone.value * 2 / 3; + else + val = number * tmp->arch->clone.value / 3; } } - } else { /* No archetype with this object */ - LOG(llevDebug,"In sell item: Have object with no archetype: %s\n", &tmp->name); - if (flag == F_BUY) { - LOG(llevError, "Asking for buy-value of unidentified object without arch.\n"); - val = number * tmp->value * 10; + } + else + { /* No archetype with this object */ + LOG (llevDebug, "In sell item: Have object with no archetype: %s\n", &tmp->name); + if (flag == F_BUY) + { + LOG (llevError, "Asking for buy-value of unidentified object without arch.\n"); + val = number * tmp->value * 10; } - else - val = number * tmp->value / 5; + else + val = number * tmp->value / 5; } } - /* If the item has been applied or identifed or does not need to be - * identified, AND the object is magical and the archetype is non - * magical, then change values accordingly. The tmp->arch==NULL is - * really just a check to prevent core dumps for when it checks - * tmp->arch->clone.magic for any magic. The check for archetype - * magic is to not give extra money for archetypes that are by - * default magical. This is because the archetype value should have - * already figured in that value. - */ - if((QUERY_FLAG(tmp, FLAG_IDENTIFIED)||!need_identify(tmp)||identified|| - QUERY_FLAG(tmp, FLAG_BEEN_APPLIED)) && - tmp->magic&&(tmp->arch==NULL||!tmp->arch->clone.magic)) { - if(tmp->magic>0) - val*=(3*tmp->magic*tmp->magic*tmp->magic); - else - /* Note that tmp->magic is negative, so that this - * will actually be something like val /=2, /=3, etc. - */ - val/=(1-tmp->magic); - } - - if (tmp->type==WAND) { - /* Value of the wand is multiplied by the number of - * charges. the treasure code already sets up the value - * 50 charges is used as the baseline. + /* If the item has been applied or identifed or does not need to be + * identified, AND the object is magical and the archetype is non + * magical, then change values accordingly. The tmp->arch==NULL is + * really just a check to prevent core dumps for when it checks + * tmp->arch->clone.magic for any magic. The check for archetype + * magic is to not give extra money for archetypes that are by + * default magical. This is because the archetype value should have + * already figured in that value. + */ + if ((QUERY_FLAG (tmp, FLAG_IDENTIFIED) || !need_identify (tmp) || identified || + QUERY_FLAG (tmp, FLAG_BEEN_APPLIED)) && tmp->magic && (tmp->arch == NULL || !tmp->arch->clone.magic)) + { + if (tmp->magic > 0) + val *= (3 * tmp->magic * tmp->magic * tmp->magic); + else + /* Note that tmp->magic is negative, so that this + * will actually be something like val /=2, /=3, etc. */ - if (QUERY_FLAG(tmp, FLAG_IDENTIFIED) || !need_identify(tmp) || identified) - val=(val*tmp->stats.food) / 50; - else /* if not identified, presume one charge */ - val/=50; - } - - /* Limit amount of money you can get for really great items. */ - if (flag==F_SELL) - val=value_limit((uint64)val, number, who, shop); - - // use a nonlinear price adjustment. as my predecessor said, don't change - // the archetypes, its work required for balancing, and we don't care. - //val = pow (val, 1.05); - - /* This modification is for bargaining skill. - * Now only players with max level in bargaining - * AND Cha = 30 will get optimal price. - * Thus charisma will never get useless. - * -b.e. edler@heydernet.de - */ - - if (who!=NULL && who->type==PLAYER) { - int lev_bargain = 0; - int lev_identify = 0; - int idskill1=0; - int idskill2=0; - const typedata *tmptype; - - tmptype=get_typedata(tmp->type); - - if (find_skill_by_number(who,SK_BARGAINING)) { - lev_bargain = find_skill_by_number(who,SK_BARGAINING)->level; - } - if (tmptype) { - idskill1=tmptype->identifyskill; - if (idskill1) { - idskill2=tmptype->identifyskill2; - if (find_skill_by_number(who,idskill1)) { - lev_identify = find_skill_by_number(who,idskill1)->level; - } - if (idskill2 && find_skill_by_number(who,idskill2)) { - lev_identify += find_skill_by_number(who,idskill2)->level; - } + val /= (1 - tmp->magic); + } + + if (tmp->type == WAND) + { + /* Value of the wand is multiplied by the number of + * charges. the treasure code already sets up the value + * 50 charges is used as the baseline. + */ + if (QUERY_FLAG (tmp, FLAG_IDENTIFIED) || !need_identify (tmp) || identified) + val = (val * tmp->stats.food) / 50; + else /* if not identified, presume one charge */ + val /= 50; + } + + /* Limit amount of money you can get for really great items. */ + if (flag == F_SELL) + val = value_limit ((uint64) val, number, who, shop); + + // use a nonlinear price adjustment. as my predecessor said, don't change + // the archetypes, its work required for balancing, and we don't care. + //val = pow (val, 1.05); + + /* This modification is for bargaining skill. + * Now only players with max level in bargaining + * AND Cha = 30 will get optimal price. + * Thus charisma will never get useless. + * -b.e. edler@heydernet.de + */ + + if (who != NULL && who->type == PLAYER) + { + int lev_bargain = 0; + int lev_identify = 0; + int idskill1 = 0; + int idskill2 = 0; + const typedata *tmptype; + + tmptype = get_typedata (tmp->type); + + if (find_skill_by_number (who, SK_BARGAINING)) + { + lev_bargain = find_skill_by_number (who, SK_BARGAINING)->level; + } + if (tmptype) + { + idskill1 = tmptype->identifyskill; + if (idskill1) + { + idskill2 = tmptype->identifyskill2; + if (find_skill_by_number (who, idskill1)) + { + lev_identify = find_skill_by_number (who, idskill1)->level; + } + if (idskill2 && find_skill_by_number (who, idskill2)) + { + lev_identify += find_skill_by_number (who, idskill2)->level; + } } } - else LOG(llevError, "Query_cost: item %s hasn't got a valid type\n", &tmp->name); + else + LOG (llevError, "Query_cost: item %s hasn't got a valid type\n", &tmp->name); - /* ratio determines how much of the price modification - * will come from the basic stat charisma - * the rest will come from the level in bargaining skill - */ - const double cha_ratio = 0.40; + /* ratio determines how much of the price modification + * will come from the basic stat charisma + * the rest will come from the level in bargaining skill + */ + const double cha_ratio = 0.40; - diff = no_bargain ? 1.0 : 1. - pow (lev_bargain / (double)settings.max_level, 0.25); - - diff = (1. - cha_ratio) * diff - + cha_ratio * (cha_bonus[who->stats.Cha] - 1.) / (cha_bonus[who->stats.Cha] + 1.); - - diff = .02 + (.80 - .02) * diff; - - if (flag == F_BUY) val += (val * diff); - else if (flag == F_SELL) val -= (val * diff); - - // now find a price range. the less good we can judge, the larger the range is - // then the range is adjusted randomly around the correct value - if (approximate) - approx_range = uint64 (val / sqrt (lev_identify * 3 + 1)); - } - - /* I don't think this should really happen - if it does, it indicates and - * overflow of diff above. That shoudl only happen if - * we are selling objects - in that case, the person just - * gets no money. - */ - if((sint64)val<0) - val=0; - - /* Unidentified stuff won't sell for more than 60gp */ - if(flag==F_SELL && !QUERY_FLAG(tmp, FLAG_IDENTIFIED) && need_identify(tmp) && !identified) { - val = (val > 600)? 600:val; - } - - /* if we are in a shop, check how the type of shop should affect the price */ - if (shop && who) { - if (flag==F_SELL) - val= ( - val - * shop_specialisation_ratio(tmp, who->map) - * shopkeeper_approval(who->map, who) - / shop_greed(who->map) - ); - else if (flag==F_BUY) { - /* - * when buying, if the item was sold by another player, it is ok to - * let the item be sold cheaper, according to the specialisation of - * the shop. If a player sold an item here, then his sale price was - * multiplied by the specialisation ratio, to do the same to the buy - * price will not generate extra money. However, the - * same is not true of generated items, these have to /divide/ by the - * specialisation, so that the price is never less than what they could - * be sold for (otherwise players could camp map resets to make money). - * In game terms, a non-specialist shop, might not recognise the true - * value of the items they sell (much like how people sometimes find - * antiques in a junk shop in real life). - */ - if (QUERY_FLAG(tmp, FLAG_PLAYER_SOLD)) - val= ( - val - * shop_greed(who->map) - * shop_specialisation_ratio(tmp, who->map) - / shopkeeper_approval(who->map, who) - ); - else - val= ( - val - * shop_greed(who->map) - / (shop_specialisation_ratio(tmp, who->map)*shopkeeper_approval(who->map, who)) - ); - } - /* we will also have an extra 0-5% variation between shops of the same type - * for valuable items (below a value of 50 this effect wouldn't be very - * pointful, and could give fun with rounding. - */ - if(who->map->path!=NULL && val > 50) - val= (val+0.05*(sint64)val*cos(tmp->count+strlen(who->map->path))); + diff = no_bargain ? 1.0 : 1. - pow (lev_bargain / (double) settings.max_level, 0.25); + + diff = (1. - cha_ratio) * diff + cha_ratio * (cha_bonus[who->stats.Cha] - 1.) / (cha_bonus[who->stats.Cha] + 1.); + + diff = .02 + (.80 - .02) * diff; + + if (flag == F_BUY) + val += (val * diff); + else if (flag == F_SELL) + val -= (val * diff); + + // now find a price range. the less good we can judge, the larger the range is + // then the range is adjusted randomly around the correct value + if (approximate) + approx_range = uint64 (val / sqrt (lev_identify * 3 + 1)); } - return (uint64)val; + + /* I don't think this should really happen - if it does, it indicates and + * overflow of diff above. That shoudl only happen if + * we are selling objects - in that case, the person just + * gets no money. + */ + if ((sint64) val < 0) + val = 0; + + /* Unidentified stuff won't sell for more than 60gp */ + if (flag == F_SELL && !QUERY_FLAG (tmp, FLAG_IDENTIFIED) && need_identify (tmp) && !identified) + { + val = (val > 600) ? 600 : val; + } + + /* if we are in a shop, check how the type of shop should affect the price */ + if (shop && who) + { + if (flag == F_SELL) + val = (val * shop_specialisation_ratio (tmp, who->map) * shopkeeper_approval (who->map, who) / shop_greed (who->map)); + else if (flag == F_BUY) + { + /* + * when buying, if the item was sold by another player, it is ok to + * let the item be sold cheaper, according to the specialisation of + * the shop. If a player sold an item here, then his sale price was + * multiplied by the specialisation ratio, to do the same to the buy + * price will not generate extra money. However, the + * same is not true of generated items, these have to /divide/ by the + * specialisation, so that the price is never less than what they could + * be sold for (otherwise players could camp map resets to make money). + * In game terms, a non-specialist shop, might not recognise the true + * value of the items they sell (much like how people sometimes find + * antiques in a junk shop in real life). + */ + if (QUERY_FLAG (tmp, FLAG_PLAYER_SOLD)) + val = (val * shop_greed (who->map) * shop_specialisation_ratio (tmp, who->map) / shopkeeper_approval (who->map, who)); + else + val = (val * shop_greed (who->map) / (shop_specialisation_ratio (tmp, who->map) * shopkeeper_approval (who->map, who))); + } + /* we will also have an extra 0-5% variation between shops of the same type + * for valuable items (below a value of 50 this effect wouldn't be very + * pointful, and could give fun with rounding. + */ + if (who->map->path != NULL && val > 50) + val = (val + 0.05 * (sint64) val * cos (tmp->count + strlen (who->map->path))); + } + return (uint64) val; } /* Find the coin type that is worth more the 'c'. Starts at the * cointype placement. */ -static archetype *find_next_coin(uint64 c, int *cointype) { +static archetype * +find_next_coin (uint64 c, int *cointype) +{ archetype *coin; do - { - if (coins[*cointype] == NULL) return NULL; - coin = find_archetype(coins[*cointype]); - if (coin == NULL) return NULL; - *cointype += 1; - } while ((uint64) coin->clone.value > c); + { + if (coins[*cointype] == NULL) + return NULL; + coin = find_archetype (coins[*cointype]); + if (coin == NULL) + return NULL; + *cointype += 1; + } + while ((uint64) coin->clone.value > c); return coin; } @@ -332,150 +353,171 @@ * time is to add a higher denomination (mithril piece with * 10,000 silver or something) */ -const char *cost_string_from_value(uint64 cost, int approx) +const char * +cost_string_from_value (uint64 cost, int approx) { - static char buf[MAX_BUF]; - archetype *coin, *next_coin; - int num, cointype = 0; - - coin = find_next_coin(cost, &cointype); - if (coin == NULL) - return "nothing"; - - num = cost / coin->clone.value; - /* so long as nrof is 32 bit, this is true. - * If it takes more coins than a person can possibly carry, this - * is basically true. - */ - if ( (cost / coin->clone.value) > UINT32_MAX) { - strcpy(buf,"an unimaginable sum of money"); - return buf; - } - - cost -= (uint64)num * (uint64)coin->clone.value; - sprintf(buf, "%d %s", num, num > 1 ? &coin->clone.name_pl : &coin->clone.name); - - next_coin = find_next_coin(cost, &cointype); - if (next_coin == NULL || approx) - return buf; - - coin = next_coin; - num = cost / coin->clone.value; - cost -= (uint64)num * (uint64)coin->clone.value; + static char buf[MAX_BUF]; + archetype *coin, *next_coin; + int num, cointype = 0; + + coin = find_next_coin (cost, &cointype); + if (coin == NULL) + return "nothing"; + + num = cost / coin->clone.value; + /* so long as nrof is 32 bit, this is true. + * If it takes more coins than a person can possibly carry, this + * is basically true. + */ + if ((cost / coin->clone.value) > UINT32_MAX) + { + strcpy (buf, "an unimaginable sum of money"); + return buf; + } + + cost -= (uint64) num *(uint64) coin->clone.value; - sprintf (buf + strlen (buf), " and %d %s", num, num > 1 ? &coin->clone.name_pl : &coin->clone.name); - + sprintf (buf, "%d %s", num, num > 1 ? &coin->clone.name_pl : &coin->clone.name); + + next_coin = find_next_coin (cost, &cointype); + if (next_coin == NULL || approx) return buf; + + coin = next_coin; + num = cost / coin->clone.value; + cost -= (uint64) num *(uint64) coin->clone.value; + + sprintf (buf + strlen (buf), " and %d %s", num, num > 1 ? &coin->clone.name_pl : &coin->clone.name); + + return buf; } -const char *query_cost_string(const object *tmp,object *who,int flag) { - uint64 real_value = query_cost(tmp,who,flag); - int idskill1=0; - int idskill2=0; - const typedata *tmptype; - - tmptype=get_typedata(tmp->type); - if (tmptype) { - idskill1=tmptype->identifyskill; - idskill2=tmptype->identifyskill2; - } - - /* we show an approximate price if - * 1) we are approximating - * 2) there either is no id skill(s) for the item, or we don't have them - * 3) we don't have bargaining skill either - */ - if (flag & F_APPROX) { - if (!idskill1 || !find_skill_by_number(who, idskill1)) { - if (!idskill2 || !find_skill_by_number(who, idskill2)) { - if (!find_skill_by_number(who,SK_BARGAINING)) { - static char buf[MAX_BUF]; - int num, cointype = 0; - archetype *coin = find_next_coin(real_value, &cointype); - - if (coin == NULL) return "nothing"; - - num = real_value / coin->clone.value; - if (num == 1) - sprintf(buf, "about one %s", &coin->clone.name); - else if (num < 5) - sprintf(buf, "a few %s", &coin->clone.name_pl); - else if (num < 10) - sprintf(buf, "several %s", &coin->clone.name_pl); - else if (num < 25) - sprintf(buf, "a moderate amount of %s", &coin->clone.name_pl); - else if (num < 100) - sprintf(buf, "lots of %s", &coin->clone.name_pl); - else if (num < 1000) - sprintf(buf, "a great many %s", &coin->clone.name_pl); - else - sprintf(buf, "a vast quantity of %s", &coin->clone.name_pl); - return buf; +const char * +query_cost_string (const object *tmp, object *who, int flag) +{ + uint64 real_value = query_cost (tmp, who, flag); + int idskill1 = 0; + int idskill2 = 0; + const typedata *tmptype; + + tmptype = get_typedata (tmp->type); + if (tmptype) + { + idskill1 = tmptype->identifyskill; + idskill2 = tmptype->identifyskill2; + } + + /* we show an approximate price if + * 1) we are approximating + * 2) there either is no id skill(s) for the item, or we don't have them + * 3) we don't have bargaining skill either + */ + if (flag & F_APPROX) + { + if (!idskill1 || !find_skill_by_number (who, idskill1)) + { + if (!idskill2 || !find_skill_by_number (who, idskill2)) + { + if (!find_skill_by_number (who, SK_BARGAINING)) + { + static char buf[MAX_BUF]; + int num, cointype = 0; + archetype *coin = find_next_coin (real_value, &cointype); + + if (coin == NULL) + return "nothing"; + + num = real_value / coin->clone.value; + if (num == 1) + sprintf (buf, "about one %s", &coin->clone.name); + else if (num < 5) + sprintf (buf, "a few %s", &coin->clone.name_pl); + else if (num < 10) + sprintf (buf, "several %s", &coin->clone.name_pl); + else if (num < 25) + sprintf (buf, "a moderate amount of %s", &coin->clone.name_pl); + else if (num < 100) + sprintf (buf, "lots of %s", &coin->clone.name_pl); + else if (num < 1000) + sprintf (buf, "a great many %s", &coin->clone.name_pl); + else + sprintf (buf, "a vast quantity of %s", &coin->clone.name_pl); + return buf; } } } - int hash = ((unsigned int)tmp->count * 174364621) & 1023; + int hash = ((unsigned int) tmp->count * 174364621) & 1023; - if (approx_range) - { - uint64 lo = (sint64)real_value - (approx_range * hash >> 10); - static char buf[MAX_BUF]; + if (approx_range) + { + uint64 lo = (sint64) real_value - (approx_range * hash >> 10); + static char buf[MAX_BUF]; - sprintf (buf, "between %s", cost_string_from_value (lo, 1)); - sprintf (buf + strlen (buf), " and %s", cost_string_from_value (lo + approx_range, 1)); + sprintf (buf, "between %s", cost_string_from_value (lo, 1)); + sprintf (buf + strlen (buf), " and %s", cost_string_from_value (lo + approx_range, 1)); - return buf; - } + return buf; + } } - return cost_string_from_value (real_value, 0); + return cost_string_from_value (real_value, 0); } /* This function finds out how much money the player is carrying, * including what is in containers. */ -uint64 query_money(const object *op) { - object *tmp; - uint64 total=0; +uint64 +query_money (const object *op) +{ + object *tmp; + uint64 total = 0; - if (op->type!=PLAYER && op->type!=CONTAINER) { - LOG(llevError, "Query money called with non player/container\n"); - return 0; + if (op->type != PLAYER && op->type != CONTAINER) + { + LOG (llevError, "Query money called with non player/container\n"); + return 0; } - for (tmp = op->inv; tmp; tmp= tmp->below) { - if (tmp->type==MONEY) { - total += (uint64)tmp->nrof * (uint64)tmp->value; - } else if (tmp->type==CONTAINER && - QUERY_FLAG(tmp,FLAG_APPLIED) && - (tmp->race==NULL || strstr(tmp->race,"gold"))) { - total += query_money(tmp); + for (tmp = op->inv; tmp; tmp = tmp->below) + { + if (tmp->type == MONEY) + { + total += (uint64) tmp->nrof * (uint64) tmp->value; + } + else if (tmp->type == CONTAINER && QUERY_FLAG (tmp, FLAG_APPLIED) && (tmp->race == NULL || strstr (tmp->race, "gold"))) + { + total += query_money (tmp); } } - return total; + return total; } + /* TCHIZE: This function takes the amount of money from the * the player inventory and from it's various pouches using the * pay_from_container function. * returns 0 if not possible. 1 if success */ -int pay_for_amount(uint64 to_pay,object *pl) { - object *pouch; +int +pay_for_amount (uint64 to_pay, object *pl) +{ + object *pouch; - if (to_pay==0) return 1; - if (to_pay > query_money(pl)) return 0; + if (to_pay == 0) + return 1; + if (to_pay > query_money (pl)) + return 0; - to_pay = pay_from_container(pl, pl, to_pay); + to_pay = pay_from_container (pl, pl, to_pay); - for (pouch=pl->inv; (pouch!=NULL) && (to_pay>0); pouch=pouch->below) { - if (pouch->type == CONTAINER - && QUERY_FLAG(pouch, FLAG_APPLIED) - && (pouch->race == NULL || strstr(pouch->race, "gold"))) { - to_pay = pay_from_container(pl, pouch, to_pay); + for (pouch = pl->inv; (pouch != NULL) && (to_pay > 0); pouch = pouch->below) + { + if (pouch->type == CONTAINER && QUERY_FLAG (pouch, FLAG_APPLIED) && (pouch->race == NULL || strstr (pouch->race, "gold"))) + { + to_pay = pay_from_container (pl, pouch, to_pay); } } - fix_player(pl); - return 1; + fix_player (pl); + return 1; } /* DAMN: This is now a wrapper for pay_from_container, which is @@ -483,36 +525,40 @@ * money until op is paid for. Change will be left wherever the last * of the price was paid from. */ -int pay_for_item(object *op,object *pl) { - uint64 to_pay = query_cost(op,pl,F_BUY | F_SHOP); - object *pouch; - uint64 saved_money; - - if (to_pay==0) return 1; - if (to_pay>query_money(pl)) return 0; - - /* We compare the paid price with the one for a player - * without bargaining skill. - * This determins the amount of exp (if any) gained for bargaining. - */ - saved_money = query_cost(op,pl,F_BUY | F_NO_BARGAIN | F_SHOP) - to_pay; - - if (saved_money > 0) - change_exp(pl,saved_money,"bargaining",SK_EXP_NONE); - - to_pay = pay_from_container(pl, pl, to_pay); - - for (pouch=pl->inv; (pouch!=NULL) && (to_pay>0); pouch=pouch->below) { - if (pouch->type == CONTAINER - && QUERY_FLAG(pouch, FLAG_APPLIED) - && (pouch->race == NULL || strstr(pouch->race, "gold"))) { - to_pay = pay_from_container(pl, pouch, to_pay); - } - } - if (settings.real_wiz == FALSE && QUERY_FLAG(pl, FLAG_WAS_WIZ)) - SET_FLAG(op, FLAG_WAS_WIZ); - fix_player(pl); +int +pay_for_item (object *op, object *pl) +{ + uint64 to_pay = query_cost (op, pl, F_BUY | F_SHOP); + object *pouch; + uint64 saved_money; + + if (to_pay == 0) return 1; + if (to_pay > query_money (pl)) + return 0; + + /* We compare the paid price with the one for a player + * without bargaining skill. + * This determins the amount of exp (if any) gained for bargaining. + */ + saved_money = query_cost (op, pl, F_BUY | F_NO_BARGAIN | F_SHOP) - to_pay; + + if (saved_money > 0) + change_exp (pl, saved_money, "bargaining", SK_EXP_NONE); + + to_pay = pay_from_container (pl, pl, to_pay); + + for (pouch = pl->inv; (pouch != NULL) && (to_pay > 0); pouch = pouch->below) + { + if (pouch->type == CONTAINER && QUERY_FLAG (pouch, FLAG_APPLIED) && (pouch->race == NULL || strstr (pouch->race, "gold"))) + { + to_pay = pay_from_container (pl, pouch, to_pay); + } + } + if (settings.real_wiz == FALSE && QUERY_FLAG (pl, FLAG_WAS_WIZ)) + SET_FLAG (op, FLAG_WAS_WIZ); + fix_player (pl); + return 1; } /* This pays for the item, and takes the proper amount of money off @@ -529,97 +575,121 @@ * to_pay is the required amount. * returns the amount still missing after using "pouch". */ -static uint64 pay_from_container(object *pl, object *pouch, uint64 to_pay) { - int count, i; - uint64 remain; - object *tmp, *coin_objs[NUM_COINS], *next; - archetype *at; - - if (pouch->type != PLAYER && pouch->type != CONTAINER) return to_pay; - - remain = to_pay; - for (i=0; iinv; tmp; tmp=next) { - next = tmp->below; - - if (tmp->type == MONEY) { - for (i=0; iarch->name) && - (tmp->value == tmp->arch->clone.value) ) { - - /* This should not happen, but if it does, just * - * merge the two. */ - if (coin_objs[i]!=NULL) { - LOG(llevError,"%s has two money entries of (%s)\n", - &pouch->name, coins[NUM_COINS-1-i]); - remove_ob(tmp); - coin_objs[i]->nrof += tmp->nrof; - esrv_del_item(pl->contr, tmp->count); - free_object(tmp); +static uint64 +pay_from_container (object *pl, object *pouch, uint64 to_pay) +{ + int count, i; + uint64 remain; + object *tmp, *coin_objs[NUM_COINS], *next; + archetype *at; + + if (pouch->type != PLAYER && pouch->type != CONTAINER) + return to_pay; + + remain = to_pay; + for (i = 0; i < NUM_COINS; i++) + coin_objs[i] = NULL; + + /* This hunk should remove all the money objects from the player/container */ + for (tmp = pouch->inv; tmp; tmp = next) + { + next = tmp->below; + + if (tmp->type == MONEY) + { + for (i = 0; i < NUM_COINS; i++) + { + if (!strcmp (coins[NUM_COINS - 1 - i], tmp->arch->name) && (tmp->value == tmp->arch->clone.value)) + { + + /* This should not happen, but if it does, just * + * merge the two. */ + if (coin_objs[i] != NULL) + { + LOG (llevError, "%s has two money entries of (%s)\n", &pouch->name, coins[NUM_COINS - 1 - i]); + remove_ob (tmp); + coin_objs[i]->nrof += tmp->nrof; + esrv_del_item (pl->contr, tmp->count); + free_object (tmp); } - else { - remove_ob(tmp); - if(pouch->type==PLAYER) esrv_del_item(pl->contr, tmp->count); - coin_objs[i] = tmp; + else + { + remove_ob (tmp); + if (pouch->type == PLAYER) + esrv_del_item (pl->contr, tmp->count); + coin_objs[i] = tmp; } - break; + break; } } - if (i==NUM_COINS) - LOG(llevError,"in pay_for_item: Did not find string match for %s\n", &tmp->arch->name); + if (i == NUM_COINS) + LOG (llevError, "in pay_for_item: Did not find string match for %s\n", &tmp->arch->name); } } - /* Fill in any gaps in the coin_objs array - needed to make change. */ - /* Note that the coin_objs array goes from least value to greatest value */ - for (i=0; inrof = 0; - } - - for (i=0; inrof*coin_objs[i]->value> remain) { - num_coins = remain / coin_objs[i]->value; - if ( (uint64) num_coins * (uint64) coin_objs[i]->value < remain ) num_coins++; - } else { - num_coins = coin_objs[i]->nrof; - } - remain -= (sint64) num_coins * (sint64)coin_objs[i]->value; - coin_objs[i]->nrof -= num_coins; - /* Now start making change. Start at the coin value - * below the one we just did, and work down to - * the lowest value. - */ - count=i-1; - while (remain<0 && count>=0) { - num_coins = -remain/ coin_objs[count]->value; - coin_objs[count]->nrof += num_coins; - remain += num_coins * coin_objs[count]->value; - count--; - } - } - for (i=0; inrof) { - object *tmp = insert_ob_in_ob(coin_objs[i], pouch); - - esrv_send_item(pl, tmp); - esrv_send_item (pl, pouch); - if (pl != pouch) esrv_update_item (UPD_WEIGHT, pl, pouch); - if (pl->type != PLAYER) { - esrv_send_item (pl, pl); + /* Fill in any gaps in the coin_objs array - needed to make change. */ + /* Note that the coin_objs array goes from least value to greatest value */ + for (i = 0; i < NUM_COINS; i++) + if (coin_objs[i] == NULL) + { + at = find_archetype (coins[NUM_COINS - 1 - i]); + if (at == NULL) + LOG (llevError, "Could not find %s archetype\n", coins[NUM_COINS - 1 - i]); + coin_objs[i] = arch_to_object (at); + coin_objs[i]->nrof = 0; + } + + for (i = 0; i < NUM_COINS; i++) + { + int num_coins; + + if (coin_objs[i]->nrof * coin_objs[i]->value > remain) + { + num_coins = remain / coin_objs[i]->value; + if ((uint64) num_coins * (uint64) coin_objs[i]->value < remain) + num_coins++; + } + else + { + num_coins = coin_objs[i]->nrof; + } + remain -= (sint64) num_coins *(sint64) coin_objs[i]->value; + + coin_objs[i]->nrof -= num_coins; + /* Now start making change. Start at the coin value + * below the one we just did, and work down to + * the lowest value. + */ + count = i - 1; + while (remain < 0 && count >= 0) + { + num_coins = -remain / coin_objs[count]->value; + coin_objs[count]->nrof += num_coins; + remain += num_coins * coin_objs[count]->value; + count--; + } + } + for (i = 0; i < NUM_COINS; i++) + { + if (coin_objs[i]->nrof) + { + object *tmp = insert_ob_in_ob (coin_objs[i], pouch); + + esrv_send_item (pl, tmp); + esrv_send_item (pl, pouch); + if (pl != pouch) + esrv_update_item (UPD_WEIGHT, pl, pouch); + if (pl->type != PLAYER) + { + esrv_send_item (pl, pl); } - } else { - free_object(coin_objs[i]); + } + else + { + free_object (coin_objs[i]); } } - return(remain); + return (remain); } /* Checks all unpaid items in op's inventory, adds up all the money they @@ -628,47 +698,61 @@ * to the player */ -int can_pay(object *pl) { - int unpaid_count = 0, i; - uint64 unpaid_price = 0; - uint64 player_wealth = query_money(pl); - object *item; - uint32 coincount[NUM_COINS]; - if (!pl || pl->type != PLAYER) { - LOG(llevError, "can_pay(): called against something that isn't a player\n"); - return 0; +int +can_pay (object *pl) +{ + int unpaid_count = 0, i; + uint64 unpaid_price = 0; + uint64 player_wealth = query_money (pl); + object *item; + uint32 coincount[NUM_COINS]; + + if (!pl || pl->type != PLAYER) + { + LOG (llevError, "can_pay(): called against something that isn't a player\n"); + return 0; } - for (i=0; i< NUM_COINS; i++) coincount[i] = 0; - for (item = pl->inv;item;) { - if QUERY_FLAG(item, FLAG_UNPAID) { - unpaid_count++; - unpaid_price += query_cost(item, pl, F_BUY | F_SHOP); + for (i = 0; i < NUM_COINS; i++) + coincount[i] = 0; + for (item = pl->inv; item;) + { + if QUERY_FLAG + (item, FLAG_UNPAID) + { + unpaid_count++; + unpaid_price += query_cost (item, pl, F_BUY | F_SHOP); } - /* merely converting the player's monetary wealth won't do, if we did that, - * we could print the wrong numbers for the coins, so we count the money instead - */ - for (i=0; i< NUM_COINS; i++) - if (!strcmp(coins[i], item->arch->name)) - coincount[i] += item->nrof; - if (item->inv) item = item->inv; - else if (item->below) item = item->below; - else if (item->env && item->env != pl && item->env->below) item = item->env->below; - else item = NULL; - } - if (unpaid_price > player_wealth) { - char buf[MAX_BUF]; - char cost[MAX_BUF]; - char missing[MAX_BUF]; - - sprintf(cost, "%s", cost_string_from_value (unpaid_price, 0)); - sprintf(missing, "%s", cost_string_from_value (unpaid_price - player_wealth, 0)); - - sprintf(buf, "You have %d unpaid items that would cost you %s. You need another %s to be able to afford that.", - unpaid_count, cost, missing); - new_draw_info(NDI_UNIQUE, 0, pl, buf); - return 0; + /* merely converting the player's monetary wealth won't do, if we did that, + * we could print the wrong numbers for the coins, so we count the money instead + */ + for (i = 0; i < NUM_COINS; i++) + if (!strcmp (coins[i], item->arch->name)) + coincount[i] += item->nrof; + if (item->inv) + item = item->inv; + else if (item->below) + item = item->below; + else if (item->env && item->env != pl && item->env->below) + item = item->env->below; + else + item = NULL; } - else return 1; + if (unpaid_price > player_wealth) + { + char buf[MAX_BUF]; + char cost[MAX_BUF]; + char missing[MAX_BUF]; + + sprintf (cost, "%s", cost_string_from_value (unpaid_price, 0)); + sprintf (missing, "%s", cost_string_from_value (unpaid_price - player_wealth, 0)); + + sprintf (buf, "You have %d unpaid items that would cost you %s. You need another %s to be able to afford that.", + unpaid_count, cost, missing); + new_draw_info (NDI_UNIQUE, 0, pl, buf); + return 0; + } + else + return 1; } @@ -681,52 +765,58 @@ * and inventory, we examine that. IF there are objects * below op, we descend down. */ -int get_payment(object *pl, object *op) { - char buf[MAX_BUF]; - int ret=1; +int +get_payment (object *pl, object *op) +{ + char buf[MAX_BUF]; + int ret = 1; - if (op!=NULL&&op->inv) - ret = get_payment(pl, op->inv); + if (op != NULL && op->inv) + ret = get_payment (pl, op->inv); - if (!ret) - return 0; + if (!ret) + return 0; - if (op!=NULL&&op->below) - ret = get_payment (pl, op->below); + if (op != NULL && op->below) + ret = get_payment (pl, op->below); - if (!ret) - return 0; - - if(op!=NULL&&QUERY_FLAG(op,FLAG_UNPAID)) { - strncpy(buf,query_cost_string(op,pl,F_BUY | F_SHOP),MAX_BUF); - buf[MAX_BUF-1] = '\0'; - if(!pay_for_item(op,pl)) { - uint64 i=query_cost(op,pl,F_BUY | F_SHOP) - query_money(pl); - CLEAR_FLAG(op, FLAG_UNPAID); - new_draw_info_format(NDI_UNIQUE, 0, pl, - "You lack %s to buy %s.", cost_string_from_value (i, 0), - query_name(op)); - SET_FLAG(op, FLAG_UNPAID); - return 0; - } else { - object *tmp; - tag_t c = op->count; - - CLEAR_FLAG(op, FLAG_UNPAID); - CLEAR_FLAG(op, FLAG_PLAYER_SOLD); - new_draw_info_format(NDI_UNIQUE, 0, op, - "You paid %s for %s.",buf,query_name(op)); - tmp=merge_ob(op,NULL); - if (pl->type == PLAYER) { - if (tmp) { /* it was merged */ - esrv_del_item (pl->contr, c); - op = tmp; + if (!ret) + return 0; + + if (op != NULL && QUERY_FLAG (op, FLAG_UNPAID)) + { + strncpy (buf, query_cost_string (op, pl, F_BUY | F_SHOP), MAX_BUF); + buf[MAX_BUF - 1] = '\0'; + if (!pay_for_item (op, pl)) + { + uint64 i = query_cost (op, pl, F_BUY | F_SHOP) - query_money (pl); + + CLEAR_FLAG (op, FLAG_UNPAID); + new_draw_info_format (NDI_UNIQUE, 0, pl, "You lack %s to buy %s.", cost_string_from_value (i, 0), query_name (op)); + SET_FLAG (op, FLAG_UNPAID); + return 0; + } + else + { + object *tmp; + tag_t c = op->count; + + CLEAR_FLAG (op, FLAG_UNPAID); + CLEAR_FLAG (op, FLAG_PLAYER_SOLD); + new_draw_info_format (NDI_UNIQUE, 0, op, "You paid %s for %s.", buf, query_name (op)); + tmp = merge_ob (op, NULL); + if (pl->type == PLAYER) + { + if (tmp) + { /* it was merged */ + esrv_del_item (pl->contr, c); + op = tmp; } - esrv_send_item(pl, op); + esrv_send_item (pl, op); } } } - return 1; + return 1; } /* written by elmex: @@ -740,7 +830,9 @@ * go somewhere and unload the money at a safe place. * */ -void pay_player (object *pl, uint64 amount) { +void +pay_player (object *pl, uint64 amount) +{ int count = 0; archetype *at = 0; object *pouch = 0, *tmp = 0; @@ -750,21 +842,18 @@ at = find_archetype (coins[count]); if (at == NULL) - LOG(llevError, "Could not find %s archetype\n", coins[count]); + LOG (llevError, "Could not find %s archetype\n", coins[count]); else if ((amount / at->clone.value) > 0) { - for (pouch=pl->inv; pouch; pouch=pouch->below) + for (pouch = pl->inv; pouch; pouch = pouch->below) { - if (pouch->type == CONTAINER - && QUERY_FLAG (pouch, FLAG_APPLIED) - && pouch->race - && strstr (pouch->race, "gold")) + if (pouch->type == CONTAINER && QUERY_FLAG (pouch, FLAG_APPLIED) && pouch->race && strstr (pouch->race, "gold")) { int w = at->clone.weight * (100 - pouch->stats.Str) / 100; int n = amount / at->clone.value; if (w == 0) - w = 1; /* Prevent divide by zero */ + w = 1; /* Prevent divide by zero */ if (n > 0 && (!pouch->weight_limit || pouch->carrying + w <= pouch->weight_limit)) { @@ -773,7 +862,7 @@ tmp = arch_to_object (at); tmp->nrof = n; - amount -= (uint64)tmp->nrof * (uint64)tmp->value; + amount -= (uint64) tmp->nrof * (uint64) tmp->value; tmp = insert_ob_in_ob (tmp, pouch); esrv_send_item (pl, tmp); esrv_send_item (pl, pouch); @@ -787,7 +876,7 @@ { tmp = arch_to_object (at); tmp->nrof = amount / tmp->value; - amount -= (uint64)tmp->nrof * (uint64)tmp->value; + amount -= (uint64) tmp->nrof * (uint64) tmp->value; tmp = insert_ob_in_ob (tmp, pl); esrv_send_item (pl, tmp); esrv_send_item (pl, pl); @@ -795,16 +884,18 @@ } } - if (amount != 0) + if (amount != 0) #ifndef WIN32 - LOG (llevError,"Warning - payment in pay_player () not zero: %llu\n", amount); + LOG (llevError, "Warning - payment in pay_player () not zero: %llu\n", amount); #else - LOG (llevError,"Warning - payment in pay_player () not zero: %I64u\n", amount); + LOG (llevError, "Warning - payment in pay_player () not zero: %I64u\n", amount); #endif } /* elmex: this is for the bank plugin :( */ -uint64 pay_player_arch (object *pl, const char *arch, uint64 amount) { +uint64 +pay_player_arch (object *pl, const char *arch, uint64 amount) +{ archetype *at = find_archetype (arch); object *tmp = NULL; @@ -830,29 +921,30 @@ * Modified to fill available race: gold containers before dumping * remaining coins in character's inventory. */ -void sell_item(object *op, object *pl) { - uint64 amount = query_cost (op,pl,F_SELL | F_SHOP), extra_gain; +void +sell_item (object *op, object *pl) +{ + uint64 amount = query_cost (op, pl, F_SELL | F_SHOP), extra_gain; - if(pl==NULL || pl->type != PLAYER) + if (pl == NULL || pl->type != PLAYER) { - LOG(llevDebug,"Object other than player tried to sell something.\n"); + LOG (llevDebug, "Object other than player tried to sell something.\n"); return; } op->custom_name = 0; - if(!amount) + if (!amount) { - new_draw_info_format (NDI_UNIQUE, 0, pl, - "We're not interested in %s.", query_name (op)); + new_draw_info_format (NDI_UNIQUE, 0, pl, "We're not interested in %s.", query_name (op)); /* Even if the character doesn't get anything for it, it may still be * worth something. If so, make it unpaid */ if (op->value) { - SET_FLAG(op, FLAG_UNPAID); - SET_FLAG(op, FLAG_PLAYER_SOLD); + SET_FLAG (op, FLAG_UNPAID); + SET_FLAG (op, FLAG_PLAYER_SOLD); } identify (op); @@ -867,13 +959,11 @@ extra_gain = amount - query_cost (op, pl, F_SELL | F_NO_BARGAIN | F_SHOP); if (extra_gain > 0) - change_exp(pl, extra_gain / 10, "bargaining", SK_EXP_NONE); + change_exp (pl, extra_gain / 10, "bargaining", SK_EXP_NONE); pay_player (pl, amount); - new_draw_info_format (NDI_UNIQUE, 0, pl, - "You receive %s for %s.", query_cost_string (op, pl, F_SELL | F_SHOP), - query_name (op)); + new_draw_info_format (NDI_UNIQUE, 0, pl, "You receive %s for %s.", query_cost_string (op, pl, F_SELL | F_SHOP), query_name (op)); SET_FLAG (op, FLAG_UNPAID); identify (op); @@ -885,62 +975,75 @@ * returned value is between (2*SPECIALISATION_EFFECT-1) and 1 and in any * event is never less than 0.1 (calling functions divide by it) */ -static double shop_specialisation_ratio(const object *item, const mapstruct *map) { - shopitems *items=map->shopitems; - double ratio = SPECIALISATION_EFFECT, likedness=0.001; - int i; +static double +shop_specialisation_ratio (const object *item, const mapstruct *map) +{ + shopitems *items = map->shopitems; + double ratio = SPECIALISATION_EFFECT, likedness = 0.001; + int i; - if (item==NULL) { - LOG(llevError, "shop_specialisation_ratio: passed a NULL item for map %s\n", map->path); - return 0; + if (item == NULL) + { + LOG (llevError, "shop_specialisation_ratio: passed a NULL item for map %s\n", map->path); + return 0; } - if (!item->type) { - LOG(llevError, "shop_specialisation_ratio: passed an item with an invalid type\n"); - /* - * I'm not really sure what the /right/ thing to do here is, these types of - * item shouldn't exist anyway, but returning the ratio is probably the best bet.." - */ - return ratio; + if (!item->type) + { + LOG (llevError, "shop_specialisation_ratio: passed an item with an invalid type\n"); + /* + * I'm not really sure what the /right/ thing to do here is, these types of + * item shouldn't exist anyway, but returning the ratio is probably the best bet.." + */ + return ratio; + } + if (map->shopitems) + { + for (i = 0; i < items[0].index; i++) + if (items[i].typenum == item->type || (!items[i].typenum && likedness == 0.001)) + likedness = items[i].strength / 100.0; + } + if (likedness > 1.0) + { /* someone has been rather silly with the map headers. */ + LOG (llevDebug, "shop_specialisation ratio: item type %d on map %s is above 100%%\n", item->type, map->path); + likedness = 1.0; + } + if (likedness < -1.0) + { + LOG (llevDebug, "shop_specialisation ratio: item type %d on map %s is below -100%%\n", item->type, map->path); + likedness = -1.0; } - if (map->shopitems) { - for (i=0; itype || (!items[i].typenum && likedness == 0.001)) - likedness = items[i].strength/100.0; - } - if (likedness > 1.0) { /* someone has been rather silly with the map headers. */ - LOG(llevDebug, "shop_specialisation ratio: item type %d on map %s is above 100%%\n", - item->type, map->path); - likedness = 1.0; - } - if (likedness < -1.0) { - LOG(llevDebug, "shop_specialisation ratio: item type %d on map %s is below -100%%\n", - item->type, map->path); - likedness = -1.0; - } - ratio = ratio + (1.0-ratio) * likedness; - if (ratio <= 0.1) ratio=0.1; /* if the ratio were much lower than this, we would get silly prices */ - return ratio; + ratio = ratio + (1.0 - ratio) * likedness; + if (ratio <= 0.1) + ratio = 0.1; /* if the ratio were much lower than this, we would get silly prices */ + return ratio; } /*returns the greed of the shop on map, or 1 if it isn't specified. */ -static double shop_greed(const mapstruct *map) { - double greed=1.0; - if (map->shopgreed) - return map->shopgreed; - return greed; +static double +shop_greed (const mapstruct *map) +{ + double greed = 1.0; + + if (map->shopgreed) + return map->shopgreed; + return greed; } /* Returns a double based on how much the shopkeeper approves of the player. * this is based on the race of the shopkeeper and that of the player. */ -double shopkeeper_approval(const mapstruct *map, const object *player) { - double approval=1.0; +double +shopkeeper_approval (const mapstruct *map, const object *player) +{ + double approval = 1.0; - if (map->shoprace) { - approval=NEUTRAL_RATIO; - if (player->race && !strcmp(player->race, map->shoprace)) approval = 1.0; + if (map->shoprace) + { + approval = NEUTRAL_RATIO; + if (player->race && !strcmp (player->race, map->shoprace)) + approval = 1.0; } - return approval; + return approval; } /* limit the value of items based on the wealth of the shop. If the item is close @@ -950,7 +1053,9 @@ * value reduction. * */ -static uint64 value_limit (uint64 val, int quantity, const object *who, int isshop) { +static uint64 +value_limit (uint64 val, int quantity, const object *who, int isshop) +{ uint64 newval, unit_price, tmpshopmax; mapstruct *map; @@ -967,20 +1072,20 @@ { if (!who->map) { - LOG(llevError, "value_limit: asked shop price for ob %s on NULL map\n", &who->name); + LOG (llevError, "value_limit: asked shop price for ob %s on NULL map\n", &who->name); return val; } map = who->map; - tmpshopmax = map->shopmax ? map->shopmax : 100000; // 20 royalties default + tmpshopmax = map->shopmax ? map->shopmax : 100000; // 20 royalties default if (map->shopmin && unit_price < map->shopmin) return 0; else if (unit_price > tmpshopmax / 2) newval = MIN ((tmpshopmax / 2) + isqrt (unit_price - tmpshopmax / 2), tmpshopmax); else - newval=unit_price; + newval = unit_price; } newval *= quantity; @@ -989,66 +1094,78 @@ } /* gives a desciption of the shop on their current map to the player op. */ -int describe_shop(const object *op) { - mapstruct *map = op->map; - /*shopitems *items=map->shopitems;*/ - int pos=0, i; - double opinion=0; - char tmp[MAX_BUF]="\0"; - if (op->type != PLAYER) return 0; - - /*check if there is a shop specified for this map */ - if (map->shopitems || map->shopgreed || map->shoprace || map->shopmin || map->shopmax) { - new_draw_info(NDI_UNIQUE,0,op,"From looking at the nearby shop you determine that it trades in:"); - if (map->shopitems) { - for (i=0; i < map->shopitems[0].index; i++) { - if (map->shopitems[i].name && map->shopitems[i].strength > 10) { - snprintf(tmp+pos, sizeof(tmp)-pos, "%s, ", map->shopitems[i].name_pl); - pos += strlen(tmp+pos); +int +describe_shop (const object *op) +{ + mapstruct *map = op->map; + + /*shopitems *items=map->shopitems; */ + int pos = 0, i; + double opinion = 0; + char tmp[MAX_BUF] = "\0"; + + if (op->type != PLAYER) + return 0; + + /*check if there is a shop specified for this map */ + if (map->shopitems || map->shopgreed || map->shoprace || map->shopmin || map->shopmax) + { + new_draw_info (NDI_UNIQUE, 0, op, "From looking at the nearby shop you determine that it trades in:"); + if (map->shopitems) + { + for (i = 0; i < map->shopitems[0].index; i++) + { + if (map->shopitems[i].name && map->shopitems[i].strength > 10) + { + snprintf (tmp + pos, sizeof (tmp) - pos, "%s, ", map->shopitems[i].name_pl); + pos += strlen (tmp + pos); } } } - if (!pos) strcat(tmp, "a little of everything."); + if (!pos) + strcat (tmp, "a little of everything."); - /* format the string into a list */ - make_list_like(tmp); - new_draw_info_format(NDI_UNIQUE, 0, op, "%s", tmp); - - if (map->shopmax) - new_draw_info_format(NDI_UNIQUE,0,op,"It won't trade for items above %s.", - cost_string_from_value(map->shopmax, 0)); - if (map->shopmin) - new_draw_info_format(NDI_UNIQUE,0,op,"It won't trade in items worth less than %s.", - cost_string_from_value(map->shopmin, 0)); - if (map->shopgreed) { - if (map->shopgreed >2.0) - new_draw_info(NDI_UNIQUE,0,op,"It tends to overcharge massively."); - else if (map->shopgreed >1.5) - new_draw_info(NDI_UNIQUE,0,op,"It tends to overcharge substantially."); - else if (map->shopgreed >1.1) - new_draw_info(NDI_UNIQUE,0,op,"It tends to overcharge slightly."); - else if (map->shopgreed <0.9) - new_draw_info(NDI_UNIQUE,0,op,"It tends to undercharge."); - } - if (map->shoprace) { - opinion=shopkeeper_approval(map, op); - if (opinion > 0.8) - new_draw_info(NDI_UNIQUE,0,op,"You think the shopkeeper likes you."); - else if (opinion > 0.5) - new_draw_info(NDI_UNIQUE,0,op,"The shopkeeper seems unconcerned by you."); - else - new_draw_info(NDI_UNIQUE,0,op,"The shopkeeper seems to have taken a dislike to you."); + /* format the string into a list */ + make_list_like (tmp); + new_draw_info_format (NDI_UNIQUE, 0, op, "%s", tmp); + + if (map->shopmax) + new_draw_info_format (NDI_UNIQUE, 0, op, "It won't trade for items above %s.", cost_string_from_value (map->shopmax, 0)); + if (map->shopmin) + new_draw_info_format (NDI_UNIQUE, 0, op, "It won't trade in items worth less than %s.", cost_string_from_value (map->shopmin, 0)); + if (map->shopgreed) + { + if (map->shopgreed > 2.0) + new_draw_info (NDI_UNIQUE, 0, op, "It tends to overcharge massively."); + else if (map->shopgreed > 1.5) + new_draw_info (NDI_UNIQUE, 0, op, "It tends to overcharge substantially."); + else if (map->shopgreed > 1.1) + new_draw_info (NDI_UNIQUE, 0, op, "It tends to overcharge slightly."); + else if (map->shopgreed < 0.9) + new_draw_info (NDI_UNIQUE, 0, op, "It tends to undercharge."); + } + if (map->shoprace) + { + opinion = shopkeeper_approval (map, op); + if (opinion > 0.8) + new_draw_info (NDI_UNIQUE, 0, op, "You think the shopkeeper likes you."); + else if (opinion > 0.5) + new_draw_info (NDI_UNIQUE, 0, op, "The shopkeeper seems unconcerned by you."); + else + new_draw_info (NDI_UNIQUE, 0, op, "The shopkeeper seems to have taken a dislike to you."); } } - else new_draw_info(NDI_UNIQUE,0,op,"There is no shop nearby."); + else + new_draw_info (NDI_UNIQUE, 0, op, "There is no shop nearby."); - return 1; + return 1; } -typedef struct shopinv { - char *item_sort; - char *item_real; - uint16 type; - uint32 nrof; +typedef struct shopinv +{ + char *item_sort; + char *item_real; + uint16 type; + uint32 nrof; } shopinv; /* There are a lot fo extra casts in here just to suppress warnings - it @@ -1056,37 +1173,43 @@ * The format of the strings we get is type:name. So we first want to * sort by type (numerical) - if the same type, then sort by name. */ -static int shop_sort(const void *a1, const void *a2) +static int +shop_sort (const void *a1, const void *a2) { - shopinv *s1 = (shopinv*)a1, *s2= (shopinv*)a2; + shopinv *s1 = (shopinv *) a1, *s2 = (shopinv *) a2; - if (s1->typetype) return -1; - if (s1->type>s2->type) return 1; - /* the type is the same (what atoi gets), so do a strcasecmp to sort - * via alphabetical order - */ - return strcasecmp(s1->item_sort, s2->item_sort); + if (s1->type < s2->type) + return -1; + if (s1->type > s2->type) + return 1; + /* the type is the same (what atoi gets), so do a strcasecmp to sort + * via alphabetical order + */ + return strcasecmp (s1->item_sort, s2->item_sort); } -static void add_shop_item(object *tmp, shopinv *items, int *numitems, int *numallocated) +static void +add_shop_item (object *tmp, shopinv * items, int *numitems, int *numallocated) { #if 0 - char buf[MAX_BUF]; + char buf[MAX_BUF]; #endif - /* clear unpaid flag so that doesn't come up in query - * string. We clear nrof so that we can better sort - * the object names. - */ - - CLEAR_FLAG(tmp, FLAG_UNPAID); - items[*numitems].nrof=tmp->nrof; - /* Non mergable items have nrof of 0, but count them as one - * so the display is properly. - */ - if (tmp->nrof == 0) items[*numitems].nrof++; - items[*numitems].type=tmp->type; + /* clear unpaid flag so that doesn't come up in query + * string. We clear nrof so that we can better sort + * the object names. + */ - switch (tmp->type) { + CLEAR_FLAG (tmp, FLAG_UNPAID); + items[*numitems].nrof = tmp->nrof; + /* Non mergable items have nrof of 0, but count them as one + * so the display is properly. + */ + if (tmp->nrof == 0) + items[*numitems].nrof++; + items[*numitems].type = tmp->type; + + switch (tmp->type) + { #if 0 case BOOTS: case GLOVES: @@ -1094,93 +1217,107 @@ case AMULET: case BRACERS: case GIRDLE: - sprintf(buf,"%s %s",query_base_name(tmp,0),describe_item(tmp, NULL)); - items[*numitems].item_sort = strdup_local(buf); - sprintf(buf,"%s %s",query_name(tmp),describe_item(tmp, NULL)); - items[*numitems].item_real = strdup_local(buf); - (*numitems)++; - break; + sprintf (buf, "%s %s", query_base_name (tmp, 0), describe_item (tmp, NULL)); + items[*numitems].item_sort = strdup_local (buf); + sprintf (buf, "%s %s", query_name (tmp), describe_item (tmp, NULL)); + items[*numitems].item_real = strdup_local (buf); + (*numitems)++; + break; #endif default: - items[*numitems].item_sort = strdup_local(query_base_name(tmp, 0)); - items[*numitems].item_real = strdup_local(query_base_name(tmp, 1)); - (*numitems)++; - break; - } - SET_FLAG(tmp, FLAG_UNPAID); -} - -void shop_listing(object *op) -{ - int i,j,numitems=0,numallocated=0, nx, ny; - char *map_mark = (char *) calloc(MAGIC_MAP_SIZE * MAGIC_MAP_SIZE,1); - object *stack; - shopinv *items; - - /* Should never happen, but just in case a monster does apply a sign */ - if (op->type!=PLAYER) return; - - new_draw_info(NDI_UNIQUE, 0, op, "\nThe shop contains:"); - - magic_mapping_mark(op, map_mark, 3); - items=(shopinv*)malloc(40*sizeof(shopinv)); - numallocated=40; - - /* Find all the appropriate items */ - for (i=0; imap); i++) { - for (j=0; jmap); j++) { - /* magic map code now centers the map on the object at MAGIC_MAP_HALF. - * - */ - nx = i - op->x + MAGIC_MAP_HALF; - ny = j - op->y + MAGIC_MAP_HALF; - /* unlikely, but really big shops could run into this issue */ - if (nx < 0 || ny < 0 || nx > MAGIC_MAP_SIZE || ny > MAGIC_MAP_SIZE) continue; - - if (map_mark[nx + MAGIC_MAP_SIZE * ny] & FACE_FLOOR) { - stack =get_map_ob(op->map,i,j); - - while (stack) { - if (QUERY_FLAG(stack, FLAG_UNPAID)) { - if (numitems==numallocated) { - items=(shopinv*)realloc(items, sizeof(shopinv)*(numallocated+10)); - numallocated+=10; + items[*numitems].item_sort = strdup_local (query_base_name (tmp, 0)); + items[*numitems].item_real = strdup_local (query_base_name (tmp, 1)); + (*numitems)++; + break; + } + SET_FLAG (tmp, FLAG_UNPAID); +} + +void +shop_listing (object *op) +{ + int i, j, numitems = 0, numallocated = 0, nx, ny; + char *map_mark = (char *) calloc (MAGIC_MAP_SIZE * MAGIC_MAP_SIZE, 1); + object *stack; + shopinv *items; + + /* Should never happen, but just in case a monster does apply a sign */ + if (op->type != PLAYER) + return; + + new_draw_info (NDI_UNIQUE, 0, op, "\nThe shop contains:"); + + magic_mapping_mark (op, map_mark, 3); + items = (shopinv *) malloc (40 * sizeof (shopinv)); + numallocated = 40; + + /* Find all the appropriate items */ + for (i = 0; i < MAP_WIDTH (op->map); i++) + { + for (j = 0; j < MAP_HEIGHT (op->map); j++) + { + /* magic map code now centers the map on the object at MAGIC_MAP_HALF. + * + */ + nx = i - op->x + MAGIC_MAP_HALF; + ny = j - op->y + MAGIC_MAP_HALF; + /* unlikely, but really big shops could run into this issue */ + if (nx < 0 || ny < 0 || nx > MAGIC_MAP_SIZE || ny > MAGIC_MAP_SIZE) + continue; + + if (map_mark[nx + MAGIC_MAP_SIZE * ny] & FACE_FLOOR) + { + stack = get_map_ob (op->map, i, j); + + while (stack) + { + if (QUERY_FLAG (stack, FLAG_UNPAID)) + { + if (numitems == numallocated) + { + items = (shopinv *) realloc (items, sizeof (shopinv) * (numallocated + 10)); + numallocated += 10; } - add_shop_item(stack, items, &numitems, &numallocated); + add_shop_item (stack, items, &numitems, &numallocated); } - stack = stack->above; + stack = stack->above; } } } } - free(map_mark); - if (numitems == 0) { - new_draw_info(NDI_UNIQUE, 0, op, "The shop is currently empty.\n"); - free(items); - return; - } - qsort(items, numitems, sizeof(shopinv), (int (*)(const void*, const void*))shop_sort); - - for (i=0; imap) return false; @@ -1189,7 +1326,8 @@ } /* elmex: this function checks whether we are in a shop or not */ -bool is_in_shop (mapstruct *map, int x, int y) +bool +is_in_shop (mapstruct *map, int x, int y) { for (object *floor = get_map_ob (map, x, y); floor; floor = floor->above) if (floor->type == SHOP_FLOOR)