Crossfire Server, Branch 1.12  R12190
shop.c
Go to the documentation of this file.
00001 /*
00002  * static char *rcsid_shop_c =
00003  *   "$Id: shop.c 11578 2009-02-23 22:02:27Z lalo $";
00004  */
00005 
00006 /*
00007   CrossFire, A Multiplayer game for X-windows
00008 
00009   Copyright (C) 2002 Mark Wedel & Crossfire Development Team
00010   Copyright (C) 1992 Frank Tore Johansen
00011 
00012   This program is free software; you can redistribute it and/or modify
00013   it under the terms of the GNU General Public License as published by
00014   the Free Software Foundation; either version 2 of the License, or
00015   (at your option) any later version.
00016 
00017   This program is distributed in the hope that it will be useful,
00018   but WITHOUT ANY WARRANTY; without even the implied warranty of
00019   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020   GNU General Public License for more details.
00021 
00022   You should have received a copy of the GNU General Public License
00023   along with this program; if not, write to the Free Software
00024   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00025 
00026   The authors can be reached via e-mail at crossfire-devel@real-time.com
00027 */
00028 
00036 #include <assert.h>
00037 #include <global.h>
00038 #include <spells.h>
00039 #include <skills.h>
00040 #include <living.h>
00041 #include <newclient.h>
00042 #ifndef __CEXTRACT__
00043 #include <sproto.h>
00044 #endif
00045 #include <math.h>
00046 
00055 #define SPECIALISATION_EFFECT 0.5
00056 
00058 #define DISAPPROVAL_RATIO 0.2
00059 
00061 #define NEUTRAL_RATIO 0.8
00062 
00063 static uint64 pay_from_container(object *pl, object *pouch, uint64 to_pay);
00064 static uint64 value_limit(uint64 val, int quantity, const object *who, int isshop);
00065 static double shop_specialisation_ratio(const object *item, const mapstruct *map);
00066 static double shop_greed(const mapstruct *map);
00067 
00068 #define NUM_COINS 5     
00070 #define LARGEST_COIN_GIVEN 2 
00073 static const char *const coins[] = {
00074     "ambercoin",
00075     "jadecoin",
00076     "platinacoin",
00077     "goldcoin",
00078     "silvercoin",
00079     NULL
00080 };
00081 
00121 uint64 query_cost(const object *tmp, object *who, int flag) {
00122     uint64 val;
00123     int number; /* used to better calculate value */
00124     int no_bargain;
00125     int identified;
00126     int not_cursed;
00127     int approximate;
00128     int shop;
00129     float diff;
00130     float ratio;
00131     const char *key;
00132 
00133     no_bargain = flag&F_NO_BARGAIN;
00134     identified = flag&F_IDENTIFIED;
00135     not_cursed = flag&F_NOT_CURSED;
00136     approximate = flag&F_APPROX;
00137     shop = flag&F_SHOP;
00138     flag &= ~(F_NO_BARGAIN|F_IDENTIFIED|F_NOT_CURSED|F_APPROX|F_SHOP);
00139 
00140     number = tmp->nrof;
00141     if (number == 0)
00142         number = 1;
00143 
00144     if ((key = get_ob_key_value(tmp, "price_adjustment")) != NULL) {
00145         ratio = atof(key);
00146         return tmp->value*number*ratio;
00147     }
00148     if ((flag == F_BUY) && ((key = get_ob_key_value(tmp, "price_adjustment_buy")) != NULL)) {
00149         ratio = atof(key);
00150         return tmp->value*number*ratio;
00151     }
00152     if ((flag == F_SELL) && ((key = get_ob_key_value(tmp, "price_adjustment_sell")) != NULL)) {
00153         ratio = atof(key);
00154         return tmp->value*number*ratio;
00155     }
00156 
00157     if (tmp->type == MONEY)
00158         return (tmp->nrof*tmp->value);
00159     if (tmp->type == GEM) {
00160         if (flag == F_TRUE)
00161             return number*tmp->value;
00162         if (flag == F_BUY)
00163             return (1.03*tmp->nrof*tmp->value);
00164         if (flag == F_SELL)
00165             return (0.97*tmp->nrof*tmp->value);
00166         LOG(llevError, "Query_cost: Gem type with unknown flag : %d\n", flag);
00167         return 0;
00168     }
00169     if (QUERY_FLAG(tmp, FLAG_IDENTIFIED)
00170     || !need_identify(tmp)
00171     || identified) {
00172         if (!not_cursed
00173         && (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED)))
00174             return 0;
00175         else
00176             val = tmp->value*number;
00177     /* This area deals with objects that are not identified, but can be */
00178     } else {
00179         if (tmp->arch != NULL) {
00180             if (flag == F_BUY) {
00181                 LOG(llevError, "Asking for buy-value of unidentified object.\n");
00182                 val = tmp->arch->clone.value*50*number;
00183             } else {     /* Trying to sell something, or get true value */
00184                 if (tmp->type == POTION)
00185                     val = number*1000; /* Don't want to give anything away */
00186                 else {
00187                     /* Get 2/3 value for applied objects, 1/3 for totally
00188                      * unknown objects
00189                      */
00190                     if (QUERY_FLAG(tmp, FLAG_BEEN_APPLIED))
00191                         val = number*tmp->arch->clone.value*2/3;
00192                     else
00193                         val = number*tmp->arch->clone.value/3;
00194                 }
00195             }
00196         } else { /* No archetype with this object */
00197             LOG(llevDebug, "In sell item: Have object with no archetype: %s\n", tmp->name);
00198             if (flag == F_BUY) {
00199                 LOG(llevError, "Asking for buy-value of unidentified object without arch.\n");
00200                 val = number*tmp->value*10;
00201             } else
00202                 val = number*tmp->value/5;
00203         }
00204     }
00205 
00206     /* If the item has been applied or identifed or does not need to be
00207      * identified, AND the object is magical and the archetype is non
00208      * magical, then change values accordingly.  The tmp->arch==NULL is
00209      * really just a check to prevent core dumps for when it checks
00210      * tmp->arch->clone.magic for any magic.  The check for archetype
00211      * magic is to not give extra money for archetypes that are by
00212      * default magical.  This is because the archetype value should have
00213      * already figured in that value.
00214      */
00215     if ((QUERY_FLAG(tmp, FLAG_IDENTIFIED) || !need_identify(tmp) || identified || QUERY_FLAG(tmp, FLAG_BEEN_APPLIED))
00216     && tmp->magic
00217     && (tmp->arch == NULL || !tmp->arch->clone.magic)) {
00218         if (tmp->magic > 0)
00219             val *= (3*tmp->magic*tmp->magic*tmp->magic);
00220         else
00221             /* Note that tmp->magic is negative, so that this
00222              * will actually be something like val /=2, /=3, etc.
00223              */
00224             val /= (1-tmp->magic);
00225     }
00226 
00227     if (tmp->type == WAND) {
00228         /* Value of the wand is multiplied by the number of
00229          * charges.  the treasure code already sets up the value
00230          * 50 charges is used as the baseline.
00231          */
00232         if (QUERY_FLAG(tmp, FLAG_IDENTIFIED)
00233         || !need_identify(tmp)
00234         || identified)
00235             val = (val*tmp->stats.food)/50;
00236         else /* if not identified, presume one charge */
00237             val /= 50;
00238     }
00239 
00240     /* Limit amount of money you can get for really great items. */
00241     if (flag == F_TRUE || flag == F_SELL)
00242         val = value_limit(val, number, who, shop);
00243 
00244     /* we need to multiply these by 4.0 to keep buy costs roughly the same
00245      * (otherwise, you could buy a potion of charisma for around 400 pp.
00246      * Arguable, the costs in the archetypes should be updated to better
00247      * reflect values (potion charisma list for 1250 gold)
00248      */
00249     val *= 4;
00250 
00251     /* This modification is for bargaining skill.
00252      * Now only players with max level in bargaining
00253      * AND Cha = 30 will get optimal price.
00254      * Thus charisma will never get useless.
00255      * -b.e. edler@heydernet.de
00256      */
00257 
00258     if (who != NULL && who->type == PLAYER) {
00259         int lev_bargain = 0;
00260         int lev_identify = 0;
00261         int idskill1 = 0;
00262         int idskill2 = 0;
00263         const typedata *tmptype;
00264 
00265         /* ratio determines how much of the price modification
00266          * will come from the basic stat charisma
00267          * the rest will come from the level in bargaining skill
00268          */
00269         ratio = 0.5;
00270         tmptype = get_typedata(tmp->type);
00271 
00272         if (find_skill_by_number(who, SK_BARGAINING)) {
00273             lev_bargain = find_skill_by_number(who, SK_BARGAINING)->level;
00274         }
00275         if (tmptype) {
00276             idskill1 = tmptype->identifyskill;
00277             if (idskill1) {
00278                 idskill2 = tmptype->identifyskill2;
00279                 if (find_skill_by_number(who, idskill1)) {
00280                     lev_identify = find_skill_by_number(who, idskill1)->level;
00281                 }
00282                 if (idskill2 && find_skill_by_number(who, idskill2)) {
00283                     lev_identify += find_skill_by_number(who, idskill2)->level;
00284                 }
00285             }
00286         } else
00287             LOG(llevError, "Query_cost: item %s hasn't got a valid type\n", tmp->name);
00288         if (!no_bargain && (lev_bargain > 0))
00289             diff = (0.8-0.6*((lev_bargain+settings.max_level*0.05)/(settings.max_level*1.05)));
00290         else
00291             diff = 0.8;
00292 
00293         diff *= 1-ratio;
00294 
00295         /* Diff is now a float between 0.2 and 0.8 */
00296         diff += (cha_bonus[who->stats.Cha]-1)/(1+cha_bonus[who->stats.Cha])*ratio;
00297 
00298         if (flag == F_BUY)
00299             val = (val*(long)(1000*(1+diff)))/1000;
00300         else if (flag == F_SELL)
00301             val = (val*(long)(1000*(1-diff)))/1000;
00302 
00303         /* If we are approximating, then the value returned should
00304          * be allowed to be wrong however merely using a random number
00305          * each time will not be sufficient, as then multiple examinations
00306          * would give different answers, so we'll use the count instead.
00307          * By taking the sine of the count, a value between -1 and 1 is
00308          * generated, we then divide by the square root of the bargaining
00309          * skill and the appropriate identification skills, so that higher
00310          * level players get better estimates. (We need a +1 there to
00311          * prevent dividing by zero.)
00312          */
00313         if (approximate)
00314             val = (sint64)val+(sint64)((sint64)val*(sin(tmp->count)/sqrt(lev_bargain+lev_identify*2+1.0)));
00315     }
00316 
00317     /* I don't think this should really happen - if it does,
00318      * it indicates an overflow of diff above.  That should only
00319      * happen if we are selling objects - in that case, the person
00320      * just gets no money.
00321      */
00322     if ((sint64)val < 0)
00323         val = 0;
00324 
00325     /* Unidentified stuff won't sell for more than 60gp */
00326     if (flag == F_SELL
00327     && !QUERY_FLAG(tmp, FLAG_IDENTIFIED)
00328     && need_identify(tmp)
00329     && !identified) {
00330         val = MIN(val, 600);
00331     }
00332 
00333     /* if in a shop, check how the type of shop should affect the price */
00334     if (shop && who) {
00335         if (flag == F_SELL)
00336             val = (sint64)val*shop_specialisation_ratio(tmp, who->map)
00337                 *shopkeeper_approval(who->map, who)/shop_greed(who->map);
00338         else if (flag == F_BUY) {
00339             /*
00340              * When buying, if the item was sold by another player, it is
00341              * ok to let the item be sold cheaper, according to the
00342              * specialisation of the shop. If a player sold an item here,
00343              * then his sale price was multiplied by the specialisation
00344              * ratio, to do the same to the buy price will not generate
00345              * extra money. However, the same is not true of generated
00346              * items, these have to /divide/ by the specialisation, so
00347              * that the price is never less than what they could
00348              * be sold for (otherwise players could camp map resets to
00349              * make money).
00350              * In game terms, a non-specialist shop might not recognise
00351              * the true value of the items it sells (much like how people
00352              * sometimes find antiques in a junk shop in real life).
00353              */
00354             if (QUERY_FLAG(tmp, FLAG_PLAYER_SOLD))
00355                 val = (sint64)val*shop_greed(who->map)
00356                     *shop_specialisation_ratio(tmp, who->map)
00357                     /shopkeeper_approval(who->map, who);
00358             else
00359                 val = (sint64)val*shop_greed(who->map)
00360                     /(shop_specialisation_ratio(tmp, who->map)
00361                       *shopkeeper_approval(who->map, who));
00362         }
00363         /* We will also have an extra 0-5% variation between shops of
00364          * the same type for valuable items (below a value of 50 this
00365          * effect wouldn't be very meaningful, and could give fun with
00366          * rounding.
00367          */
00368         if (who->map->path != NULL && val > 50)
00369             val = (sint64)val+0.05*(sint64)val*cos(tmp->count+strlen(who->map->path));
00370     }
00371     return val;
00372 }
00373 
00385 static archetype *find_next_coin(uint64 c, int *cointype) {
00386     archetype *coin;
00387 
00388     do {
00389         if (coins[*cointype] == NULL)
00390             return NULL;
00391         coin = find_archetype(coins[*cointype]);
00392         if (coin == NULL)
00393             return NULL;
00394         *cointype += 1;
00395     } while (coin->clone.value > c);
00396 
00397     return coin;
00398 }
00399 
00417 static StringBuffer *cost_string_from_value(uint64 cost, StringBuffer *buf) {
00418     archetype *coin, *next_coin;
00419     uint32 num;
00420     int cointype = LARGEST_COIN_GIVEN;
00421 
00422     if (!buf)
00423         buf = stringbuffer_new();
00424 
00425     coin = find_next_coin(cost, &cointype);
00426     if (coin == NULL) {
00427         stringbuffer_append_string(buf, "nothing");
00428         return buf;
00429     }
00430 
00431     num = cost/coin->clone.value;
00432     /* so long as nrof is 32 bit, this is true.
00433      * If it takes more coins than a person can possibly carry, this
00434      * is basically true.
00435      */
00436     if ((cost/coin->clone.value) > UINT32_MAX) {
00437         stringbuffer_append_string(buf, "an unimaginable sum of money.");
00438         return buf;
00439     }
00440 
00441     cost -= (uint64)num*(uint64)coin->clone.value;
00442     if (num == 1)
00443         stringbuffer_append_printf(buf, "1 %s", coin->clone.name);
00444     else
00445         stringbuffer_append_printf(buf, "%u %ss", num, coin->clone.name);
00446 
00447     next_coin = find_next_coin(cost, &cointype);
00448     if (next_coin == NULL)
00449         return buf;
00450 
00451     do {
00452         coin = next_coin;
00453         num = cost/coin->clone.value;
00454         cost -= (uint64)num*(uint64)coin->clone.value;
00455 
00456         if (cost == 0)
00457             next_coin = NULL;
00458         else
00459             next_coin = find_next_coin(cost, &cointype);
00460 
00461         if (next_coin) {
00462             /* There will be at least one more string to add to the list,
00463              * use a comma.
00464              */
00465             stringbuffer_append_string(buf, ", ");
00466         } else {
00467             stringbuffer_append_string(buf, " and ");
00468         }
00469         if (num == 1)
00470             stringbuffer_append_printf(buf, "1 %s", coin->clone.name);
00471         else
00472             stringbuffer_append_printf(buf, "%u %ss", num, coin->clone.name);
00473     } while (next_coin);
00474 
00475     return buf;
00476 }
00477 
00488 static StringBuffer *real_money_value(const object *coin, StringBuffer *buf) {
00489     assert(coin->type == MONEY);
00490     assert(buf);
00491 
00492     stringbuffer_append_printf(buf, "%ld %s", coin->nrof, coin->nrof == 1 ? coin->name : coin->name_pl);
00493     return buf;
00494 }
00495 
00511 StringBuffer *query_cost_string(const object *tmp, object *who, int flag, StringBuffer *buf) {
00512     uint64 real_value = query_cost(tmp, who, flag);
00513     int idskill1 = 0;
00514     int idskill2 = 0;
00515     const typedata *tmptype;
00516 
00517     if (!buf)
00518         buf = stringbuffer_new();
00519 
00520     /* money it's pretty hard to not give the exact price, so skip all logic and just return the real value. */
00521     if (tmp->type == MONEY) {
00522         return real_money_value(tmp, buf);
00523     }
00524 
00525     tmptype = get_typedata(tmp->type);
00526     if (tmptype) {
00527         idskill1 = tmptype->identifyskill;
00528         idskill2 = tmptype->identifyskill2;
00529     }
00530 
00531     /* we show an approximate price if
00532      * 1) we are approximating
00533      * 2) there either is no id skill(s) for the item, or we don't have them
00534      * 3) we don't have bargaining skill either
00535      */
00536     if (flag&F_APPROX) {
00537         if (!idskill1 || !find_skill_by_number(who, idskill1)) {
00538             if (!idskill2 || !find_skill_by_number(who, idskill2)) {
00539                 if (!find_skill_by_number(who, SK_BARGAINING)) {
00540                     int num;
00541                     int cointype = LARGEST_COIN_GIVEN;
00542                     archetype *coin = find_next_coin(real_value, &cointype);
00543 
00544                     if (coin == NULL) {
00545                         stringbuffer_append_string(buf, "nothing");
00546                         return buf;
00547                     }
00548 
00549                     num = real_value/coin->clone.value;
00550                     if (num == 1)
00551                         stringbuffer_append_printf(buf, "about one %s", coin->clone.name);
00552                     else if (num < 5)
00553                         stringbuffer_append_printf(buf, "a few %s", coin->clone.name_pl);
00554                     else if (num < 10)
00555                         stringbuffer_append_printf(buf, "several %s", coin->clone.name_pl);
00556                     else if (num < 25)
00557                         stringbuffer_append_printf(buf, "a moderate amount of %s", coin->clone.name_pl);
00558                     else if (num < 100)
00559                         stringbuffer_append_printf(buf, "lots of %s", coin->clone.name_pl);
00560                     else if (num < 1000)
00561                         stringbuffer_append_printf(buf, "a great many %s", coin->clone.name_pl);
00562                     else
00563                         stringbuffer_append_printf(buf, "a vast quantity of %s", coin->clone.name_pl);
00564                     return buf;
00565                 }
00566             }
00567         }
00568     }
00569     return cost_string_from_value(real_value, buf);
00570 }
00571 
00581 uint64 query_money(const object *op) {
00582     object *tmp;
00583     uint64 total = 0;
00584 
00585     if (op->type != PLAYER && op->type != CONTAINER) {
00586         LOG(llevError, "Query money called with non player/container\n");
00587         return 0;
00588     }
00589     for (tmp = op->inv; tmp; tmp = tmp->below) {
00590         if (tmp->type == MONEY) {
00591             total += (uint64)tmp->nrof*(uint64)tmp->value;
00592         } else if (tmp->type == CONTAINER
00593         && QUERY_FLAG(tmp, FLAG_APPLIED)
00594         && (tmp->race == NULL || strstr(tmp->race, "gold"))) {
00595             total += query_money(tmp);
00596         }
00597     }
00598     return total;
00599 }
00600 
00613 int pay_for_amount(uint64 to_pay, object *pl) {
00614     object *pouch;
00615 
00616     if (to_pay == 0)
00617         return 1;
00618     if (to_pay > query_money(pl))
00619         return 0;
00620 
00621     to_pay = pay_from_container(pl, pl, to_pay);
00622 
00623     for (pouch = pl->inv; (pouch != NULL) && (to_pay > 0); pouch = pouch->below) {
00624         if (pouch->type == CONTAINER
00625         && QUERY_FLAG(pouch, FLAG_APPLIED)
00626         && (pouch->race == NULL || strstr(pouch->race, "gold"))) {
00627             to_pay = pay_from_container(pl, pouch, to_pay);
00628         }
00629     }
00630     if (to_pay > 0) {
00631         LOG(llevError, "pay_for_amount: Cannot remove enough money -- %"FMT64U" remains\n", to_pay);
00632     }
00633 
00634     fix_object(pl);
00635     return 1;
00636 }
00637 
00652 int pay_for_item(object *op, object *pl) {
00653     uint64 to_pay = query_cost(op, pl, F_BUY|F_SHOP);
00654     object *pouch;
00655     uint64 saved_money;
00656 
00657     if (to_pay == 0)
00658         return 1;
00659     if (to_pay > query_money(pl))
00660         return 0;
00661 
00662     /* We compare the paid price with the one for a player
00663      * without bargaining skill.
00664      * This determins the amount of exp (if any) gained for bargaining.
00665      */
00666     saved_money = query_cost(op, pl, F_BUY|F_NO_BARGAIN|F_SHOP)-to_pay;
00667 
00668     if (saved_money > 0)
00669         change_exp(pl, saved_money, "bargaining", SK_EXP_NONE);
00670 
00671     to_pay = pay_from_container(pl, pl, to_pay);
00672 
00673     for (pouch = pl->inv; (pouch != NULL) && (to_pay > 0); pouch = pouch->below) {
00674         if (pouch->type == CONTAINER
00675         && QUERY_FLAG(pouch, FLAG_APPLIED)
00676         && (pouch->race == NULL || strstr(pouch->race, "gold"))) {
00677             to_pay = pay_from_container(pl, pouch, to_pay);
00678         }
00679     }
00680     if (to_pay > 0) {
00681         LOG(llevError, "pay_for_item: Cannot remove enough money -- %"FMT64U" remains\n", to_pay);
00682     }
00683     if (settings.real_wiz == FALSE && QUERY_FLAG(pl, FLAG_WAS_WIZ))
00684         SET_FLAG(op, FLAG_WAS_WIZ);
00685     fix_object(pl);
00686     return 1;
00687 }
00688 
00700 static sint64 remove_value(object *coin_objs[], sint64 remain) {
00701     int i;
00702 
00703     for (i = 0; i < NUM_COINS; i++) {
00704         int count;
00705         sint64 num_coins;
00706 
00707         if (coin_objs[i]->nrof*coin_objs[i]->value > remain) {
00708             num_coins = remain/coin_objs[i]->value;
00709             if ((uint64)num_coins*(uint64)coin_objs[i]->value < remain) {
00710                 num_coins++;
00711             }
00712         } else {
00713             num_coins = coin_objs[i]->nrof;
00714         }
00715         remain -= (sint64)num_coins*(sint64)coin_objs[i]->value;
00716         coin_objs[i]->nrof -= num_coins;
00717         /* Now start making change.  Start at the coin value
00718          * below the one we just did, and work down to
00719          * the lowest value.
00720          */
00721         count = i-1;
00722         while (remain < 0 && count >= 0) {
00723             num_coins = -remain/coin_objs[count]->value;
00724             coin_objs[count]->nrof += num_coins;
00725             remain += num_coins*coin_objs[count]->value;
00726             count--;
00727         }
00728     }
00729 
00730     return remain;
00731 }
00732 
00741 static void add_value(object *coin_objs[], sint64 value) {
00742     int i;
00743 
00744     for (i = NUM_COINS-LARGEST_COIN_GIVEN-1; i >= 0; i--) {
00745         uint32 nrof;
00746 
00747         nrof = (uint32)(value/coin_objs[i]->value);
00748         value -= nrof*coin_objs[i]->value;
00749         coin_objs[i]->nrof += nrof;
00750     }
00751 }
00752 
00765 static void insert_objects(object *pl, object *container, object *objects[], int objects_len) {
00766     int i, one = 0;
00767 
00768     for (i = 0; i < objects_len; i++) {
00769         if (objects[i]->nrof > 0) {
00770             insert_ob_in_ob(objects[i], container);
00771             one = 1;
00772         } else {
00773             free_object(objects[i]);
00774         }
00775     }
00776     if (one)
00777         esrv_update_item(UPD_WEIGHT, pl, container);
00778 }
00779 
00796 static uint64 pay_from_container(object *pl, object *pouch, uint64 to_pay) {
00797     int i;
00798     sint64 remain;
00799     object *tmp, *coin_objs[NUM_COINS], *next;
00800     object *other_money[16]; /* collects MONEY objects not matching coins[] */
00801     size_t other_money_len; /* number of allocated entries in other_money[] */
00802     archetype *at;
00803 
00804     if (pouch->type != PLAYER && pouch->type != CONTAINER)
00805         return to_pay;
00806 
00807     remain = to_pay;
00808     for (i = 0; i < NUM_COINS; i++)
00809         coin_objs[i] = NULL;
00810 
00811     /* This hunk should remove all the money objects from the player/container */
00812     other_money_len = 0;
00813     for (tmp = pouch->inv; tmp; tmp = next) {
00814         next = tmp->below;
00815         if (tmp->type == MONEY) {
00816             for (i = 0; i < NUM_COINS; i++) {
00817                 if (!strcmp(coins[NUM_COINS-1-i], tmp->arch->name)
00818                 && (tmp->value == tmp->arch->clone.value)) {
00819 
00820                     /* This should not happen, but if it does, just
00821                      * merge the two.
00822                      */
00823                     if (coin_objs[i] != NULL) {
00824                         LOG(llevError, "%s has two money entries of (%s)\n", pouch->name, coins[NUM_COINS-1-i]);
00825                         remove_ob(tmp);
00826                         coin_objs[i]->nrof += tmp->nrof;
00827                         free_object(tmp);
00828                     } else {
00829                         remove_ob(tmp);
00830                         coin_objs[i] = tmp;
00831                     }
00832                     break;
00833                 }
00834             }
00835             if (i == NUM_COINS) {
00836                 if (other_money_len >= sizeof(other_money)/sizeof(*other_money)) {
00837                     LOG(llevError, "pay_for_item: Cannot store non-standard money object %s\n", tmp->arch->name);
00838                 } else {
00839                     remove_ob(tmp);
00840                     other_money[other_money_len++] = tmp;
00841                 }
00842             }
00843         }
00844     }
00845 
00846     /* Fill in any gaps in the coin_objs array - needed to make change.      */
00847     /* Note that the coin_objs array goes from least value to greatest value */
00848     for (i = 0; i < NUM_COINS; i++)
00849         if (coin_objs[i] == NULL) {
00850             at = find_archetype(coins[NUM_COINS-1-i]);
00851             if (at == NULL)
00852                 LOG(llevError, "Could not find %s archetype\n", coins[NUM_COINS-1-i]);
00853             coin_objs[i] = get_object();
00854             copy_object(&at->clone, coin_objs[i]);
00855             coin_objs[i]->nrof = 0;
00856         }
00857 
00858     /* Try to pay from standard coins first. */
00859     remain = remove_value(coin_objs, remain);
00860 
00861     /* Now pay from non-standard coins until all is paid. */
00862     for (i = 0; i < other_money_len && remain > 0; i++) {
00863         uint32 nrof;
00864         object *coin;
00865 
00866         coin = other_money[i];
00867 
00868         /* Find the minimal number of coins to use. This prevents converting
00869          * excess non-standard coins to standard money.
00870          */
00871         nrof = (remain+coin->value-1)/coin->value;
00872         if (nrof > coin->nrof) {
00873             nrof = coin->nrof;
00874         }
00875         coin->nrof -= nrof;
00876         add_value(coin_objs, nrof*coin->value);
00877 
00878         remain = remove_value(coin_objs, remain);
00879     }
00880 
00881     /* re-insert remaining coins into player */
00882     insert_objects(pl, pouch, coin_objs, NUM_COINS);
00883     insert_objects(pl, pouch, other_money, other_money_len);
00884 
00885     return(remain);
00886 }
00887 
00904 static void count_unpaid(object *pl, object *item, int *unpaid_count, uint64 *unpaid_price, uint32 *coincount) {
00905     int i;
00906 
00907     for (; item; item = item->below) {
00908         if QUERY_FLAG(item, FLAG_UNPAID) {
00909             (*unpaid_count)++;
00910             (*unpaid_price) += query_cost(item, pl, F_BUY|F_SHOP);
00911         }
00912         /* Merely converting the player's monetary wealth won't do.
00913          * If we did that, we could print the wrong numbers for the
00914          * coins, so we count the money instead.
00915          */
00916         for (i = 0; i < NUM_COINS; i++)
00917             if (!strcmp(coins[i], item->arch->name)) {
00918                 coincount[i] += item->nrof;
00919                 break;
00920             }
00921         if (item->inv)
00922             count_unpaid(pl, item->inv, unpaid_count, unpaid_price, coincount);
00923     }
00924 }
00925 
00938 int can_pay(object *pl) {
00939     int unpaid_count = 0, i;
00940     uint64 unpaid_price = 0;
00941     uint64 player_wealth = query_money(pl);
00942     uint32 coincount[NUM_COINS];
00943 
00944     if (!pl || pl->type != PLAYER) {
00945         LOG(llevError, "can_pay(): called against something that isn't a player\n");
00946         return 0;
00947     }
00948 
00949     for (i = 0; i < NUM_COINS; i++)
00950         coincount[i] = 0;
00951 
00952     count_unpaid(pl, pl->inv, &unpaid_count, &unpaid_price, coincount);
00953 
00954     if (unpaid_price > player_wealth) {
00955         char buf[MAX_BUF], coinbuf[MAX_BUF];
00956         int denominations = 0;
00957         char *value = stringbuffer_finish(cost_string_from_value(unpaid_price, NULL));
00958 
00959         snprintf(buf, sizeof(buf), "You have %d unpaid items that would cost you %s, ", unpaid_count, value);
00960         free(value);
00961         for (i = 0; i < NUM_COINS; i++) {
00962             if (coincount[i] > 0 && coins[i]) {
00963                 if (denominations == 0)
00964                     snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "but you only have");
00965                 denominations++;
00966                 snprintf(coinbuf, sizeof(coinbuf), " %u %s,", coincount[i], find_archetype(coins[i])->clone.name_pl);
00967                 snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%s", coinbuf);
00968             }
00969         }
00970         if (denominations == 0)
00971             snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "but you don't have any money.");
00972         else if (denominations > 1)
00973             make_list_like(buf);
00974         draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_SHOP,
00975                       MSG_TYPE_SHOP_PAYMENT, buf, NULL);
00976         return 0;
00977     } else
00978         return 1;
00979 }
00980 
00992 int get_payment(object *pl, object *op) {
00993     char name_op[MAX_BUF];
00994     int ret = 1;
00995 
00996     if (op != NULL && op->inv)
00997         ret = get_payment(pl, op->inv);
00998 
00999     if (!ret)
01000         return 0;
01001 
01002     if (op != NULL && op->below)
01003         ret = get_payment(pl, op->below);
01004 
01005     if (!ret)
01006         return 0;
01007 
01008     if (op != NULL && QUERY_FLAG(op, FLAG_UNPAID)) {
01009         if (!pay_for_item(op, pl)) {
01010             uint64 i = query_cost(op, pl, F_BUY|F_SHOP)-query_money(pl);
01011             char *missing = stringbuffer_finish(cost_string_from_value(i, NULL));
01012 
01013             CLEAR_FLAG(op, FLAG_UNPAID);
01014             query_name(op, name_op, MAX_BUF);
01015             draw_ext_info_format(NDI_UNIQUE, 0, pl,
01016                                  MSG_TYPE_SHOP, MSG_TYPE_SHOP_PAYMENT,
01017                                  "You lack %s to buy %s.",
01018                                  "You lack %s to buy %s.",
01019                                  missing, name_op);
01020             free(missing);
01021             SET_FLAG(op, FLAG_UNPAID);
01022             return 0;
01023         } else {
01024             object *tmp;
01025             char *value = stringbuffer_finish(query_cost_string(op, pl, F_BUY|F_SHOP, NULL));
01026 
01027             CLEAR_FLAG(op, FLAG_UNPAID);
01028             CLEAR_FLAG(op, FLAG_PLAYER_SOLD);
01029             query_name(op, name_op, MAX_BUF);
01030             draw_ext_info_format(NDI_UNIQUE, 0, pl,
01031                                  MSG_TYPE_SHOP, MSG_TYPE_SHOP_PAYMENT,
01032                                  "You paid %s for %s.",
01033                                  "You paid %s for %s.",
01034                                  value, name_op);
01035             free(value);
01036             tmp = merge_ob(op, NULL);
01037             if (pl->type == PLAYER && !tmp) {
01038                 /* If item wasn't merged we update it. If merged, merge_ob handled everything for us. */
01039                 esrv_update_item(UPD_FLAGS|UPD_NAME, pl, op);
01040             }
01041         }
01042     }
01043     return 1;
01044 }
01045 
01059 void sell_item(object *op, object *pl) {
01060     uint64 i = query_cost(op, pl, F_SELL|F_SHOP), extra_gain;
01061     int count;
01062     object *tmp, *pouch;
01063     archetype *at;
01064     char name_op[MAX_BUF], *value;
01065 
01066     if (pl == NULL || pl->type != PLAYER) {
01067         LOG(llevDebug, "Object other than player tried to sell something.\n");
01068         return;
01069     }
01070 
01071     if (op->custom_name)
01072         FREE_AND_CLEAR_STR(op->custom_name);
01073 
01074     if (!i) {
01075         query_name(op, name_op, MAX_BUF);
01076         draw_ext_info_format(NDI_UNIQUE, 0, pl,
01077                              MSG_TYPE_SHOP, MSG_TYPE_SHOP_SELL,
01078                              "We're not interested in %s.",
01079                              "We're not interested in %s.",
01080                              name_op);
01081 
01082         /* Even if the character doesn't get anything for it, it may still be
01083          * worth something.  If so, make it unpaid
01084          */
01085         if (op->value) {
01086             SET_FLAG(op, FLAG_UNPAID);
01087             SET_FLAG(op, FLAG_PLAYER_SOLD);
01088         }
01089         identify(op);
01090         return;
01091     }
01092 
01093     /* We compare the price with the one for a player
01094      * without bargaining skill.
01095      * This determins the amount of exp (if any) gained for bargaining.
01096      * exp/10 -> 1 for each gold coin
01097      */
01098     extra_gain = i-query_cost(op, pl, F_SELL|F_NO_BARGAIN|F_SHOP);
01099 
01100     if (extra_gain > 0)
01101         change_exp(pl, extra_gain/10, "bargaining", SK_EXP_NONE);
01102 
01103     for (count = LARGEST_COIN_GIVEN; coins[count] != NULL; count++) {
01104         at = find_archetype(coins[count]);
01105         if (at == NULL)
01106             LOG(llevError, "Could not find %s archetype\n", coins[count]);
01107         else if ((i/at->clone.value) > 0) {
01108             for (pouch = pl->inv; pouch; pouch = pouch->below) {
01109                 if (pouch->type == CONTAINER
01110                 && QUERY_FLAG(pouch, FLAG_APPLIED)
01111                 && pouch->race
01112                 && strstr(pouch->race, "gold")) {
01113                     int w = at->clone.weight*(100-pouch->stats.Str)/100;
01114                     int n = i/at->clone.value;
01115 
01116                     if (w == 0)
01117                         w = 1;    /* Prevent divide by zero */
01118                     if (n > 0
01119                     && (!pouch->weight_limit || pouch->carrying+w <= pouch->weight_limit)) {
01120                         if (pouch->weight_limit
01121                         && (pouch->weight_limit-pouch->carrying)/w < n)
01122                             n = (pouch->weight_limit-pouch->carrying)/w;
01123 
01124                         tmp = get_object();
01125                         copy_object(&at->clone, tmp);
01126                         tmp->nrof = n;
01127                         i -= (uint64)tmp->nrof*(uint64)tmp->value;
01128                         tmp = insert_ob_in_ob(tmp, pouch);
01129                         esrv_update_item(UPD_WEIGHT, pl, pl);
01130                     }
01131                 }
01132             }
01133             if (i/at->clone.value > 0) {
01134                 tmp = get_object();
01135                 copy_object(&at->clone, tmp);
01136                 tmp->nrof = i/tmp->value;
01137                 i -= (uint64)tmp->nrof*(uint64)tmp->value;
01138                 tmp = insert_ob_in_ob(tmp, pl);
01139                 esrv_update_item(UPD_WEIGHT, pl, pl);
01140             }
01141         }
01142     }
01143 
01144     if (i != 0)
01145 #ifndef WIN32
01146         LOG(llevError, "Warning - payment not zero: %llu\n", i);
01147 #else
01148         LOG(llevError, "Warning - payment not zero: %I64u\n", i);
01149 #endif
01150 
01151     query_name(op, name_op, MAX_BUF);
01152     value = stringbuffer_finish(query_cost_string(op, pl, F_SELL|F_SHOP, NULL));
01153 
01154     draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_SHOP, MSG_TYPE_SHOP_SELL,
01155                          "You receive %s for %s.",
01156                          "You receive %s for %s.",
01157                          value,
01158                          name_op);
01159 
01160     free(value);
01161 
01162     SET_FLAG(op, FLAG_UNPAID);
01163     identify(op);
01164 }
01165 
01179 static double shop_specialisation_ratio(const object *item, const mapstruct *map) {
01180     shopitems *items = map->shopitems;
01181     double ratio = SPECIALISATION_EFFECT, likedness = 0.001;
01182     int i;
01183 
01184     if (item == NULL) {
01185         LOG(llevError, "shop_specialisation_ratio: passed a NULL item for map %s\n", map->path);
01186         return 0;
01187     }
01188     if (!item->type) {
01189         LOG(llevError, "shop_specialisation_ratio: passed an item with an invalid type\n");
01190         /*
01191          * I'm not really sure what the /right/ thing to do here is,
01192          * these types of item shouldn't exist anyway, but returning
01193          * the ratio is probably the best bet.."
01194          */
01195         return ratio;
01196     }
01197     if (map->shopitems) {
01198         for (i = 0; i < items[0].index; i++)
01199             if (items[i].typenum == item->type || (!items[i].typenum && likedness == 0.001))
01200                 likedness = items[i].strength/100.0;
01201     }
01202     if (likedness > 1.0) { /* someone has been rather silly with the map headers. */
01203         LOG(llevDebug, "shop_specialisation ratio: item type %d on map %s is above 100%%\n", item->type, map->path);
01204         likedness = 1.0;
01205     }
01206     if (likedness < -1.0) {
01207         LOG(llevDebug, "shop_specialisation ratio: item type %d on map %s is below -100%%\n", item->type, map->path);
01208         likedness = -1.0;
01209     }
01210     ratio = ratio+(1.0-ratio)*likedness;
01211     if (ratio <= 0.1)
01212         ratio = 0.1; /* if the ratio were much lower than this, we would get silly prices */
01213     return ratio;
01214 }
01215 
01224 static double shop_greed(const mapstruct *map) {
01225     double greed = 1.0;
01226 
01227     if (map->shopgreed)
01228         return map->shopgreed;
01229     return greed;
01230 }
01231 
01243 double shopkeeper_approval(const mapstruct *map, const object *player) {
01244     double approval = 1.0;
01245 
01246     if (map->shoprace) {
01247         approval = NEUTRAL_RATIO;
01248         if (player->race && !strcmp(player->race, map->shoprace))
01249             approval = 1.0;
01250     }
01251     return approval;
01252 }
01253 
01273 static uint64 value_limit(uint64 val, int quantity, const object *who, int isshop) {
01274     uint64 newval, unit_price;
01275     mapstruct *map;
01276 
01277     unit_price = val/quantity;
01278     if (!isshop || !who) {
01279         if (unit_price > 10000)
01280             newval = 8000+isqrt(unit_price)*20;
01281         else
01282             newval = unit_price;
01283     } else {
01284         if (!who->map) {
01285             LOG(llevError, "value_limit: asked shop price for ob %s on NULL map\n", who->name);
01286             return val;
01287         }
01288         map = who->map;
01289         if (map->shopmin && unit_price < map->shopmin)
01290             return 0;
01291         else if (map->shopmax && unit_price > map->shopmax/2)
01292             newval = MIN((map->shopmax/2)+isqrt(unit_price-map->shopmax/2), map->shopmax);
01293         else if (unit_price > 10000)
01294             newval = 8000+isqrt(unit_price)*20;
01295         else
01296             newval = unit_price;
01297     }
01298     newval *= quantity;
01299     return newval;
01300 }
01301 
01311 int describe_shop(const object *op) {
01312     mapstruct *map = op->map;
01313     /*shopitems *items=map->shopitems;*/
01314     int pos = 0, i;
01315     double opinion = 0;
01316     char tmp[MAX_BUF] = "\0", *value;
01317 
01318     if (op->type != PLAYER)
01319         return 0;
01320 
01321     /*check if there is a shop specified for this map */
01322     if (map->shopitems
01323     || map->shopgreed
01324     || map->shoprace
01325     || map->shopmin
01326     || map->shopmax) {
01327         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SHOP, MSG_TYPE_SHOP_LISTING,
01328                       "From looking at the nearby shop you determine that it trades in:",
01329                       NULL);
01330 
01331         if (map->shopitems) {
01332             for (i = 0; i < map->shopitems[0].index; i++) {
01333                 if (map->shopitems[i].name && map->shopitems[i].strength > 10) {
01334                     snprintf(tmp+pos, sizeof(tmp)-pos, "%s, ", map->shopitems[i].name_pl);
01335                     pos += strlen(tmp+pos);
01336                 }
01337             }
01338         }
01339         if (!pos)
01340             strcpy(tmp, "a little of everything.");
01341 
01342         /* format the string into a list */
01343         make_list_like(tmp);
01344         draw_ext_info(NDI_UNIQUE, 0, op,
01345                       MSG_TYPE_SHOP, MSG_TYPE_SHOP_LISTING, tmp, NULL);
01346 
01347         if (map->shopmax) {
01348             value = stringbuffer_finish(cost_string_from_value(map->shopmax, NULL));
01349             draw_ext_info_format(NDI_UNIQUE, 0, op,
01350                                  MSG_TYPE_SHOP, MSG_TYPE_SHOP_MISC,
01351                                  "It won't trade for items above %s.",
01352                                  "It won't trade for items above %s.",
01353                                  value);
01354             free(value);
01355         }
01356 
01357         if (map->shopmin) {
01358             value = stringbuffer_finish(cost_string_from_value(map->shopmin, NULL));
01359             draw_ext_info_format(NDI_UNIQUE, 0, op,
01360                                  MSG_TYPE_SHOP, MSG_TYPE_SHOP_MISC,
01361                                  "It won't trade in items worth less than %s.",
01362                                  "It won't trade in items worth less than %s.",
01363                                  value);
01364             free(value);
01365         }
01366 
01367         if (map->shopgreed) {
01368             if (map->shopgreed > 2.0)
01369                 draw_ext_info(NDI_UNIQUE, 0, op,
01370                               MSG_TYPE_SHOP, MSG_TYPE_SHOP_MISC,
01371                               "It tends to overcharge massively.", NULL);
01372             else if (map->shopgreed > 1.5)
01373                 draw_ext_info(NDI_UNIQUE, 0, op,
01374                               MSG_TYPE_SHOP, MSG_TYPE_SHOP_MISC,
01375                               "It tends to overcharge substantially.", NULL);
01376             else if (map->shopgreed > 1.1)
01377                 draw_ext_info(NDI_UNIQUE, 0, op,
01378                               MSG_TYPE_SHOP, MSG_TYPE_SHOP_MISC,
01379                               "It tends to overcharge slightly.", NULL);
01380             else if (map->shopgreed < 0.9)
01381                 draw_ext_info(NDI_UNIQUE, 0, op,
01382                               MSG_TYPE_SHOP, MSG_TYPE_SHOP_MISC,
01383                               "It tends to undercharge.", NULL);
01384         }
01385         if (map->shoprace) {
01386             opinion = shopkeeper_approval(map, op);
01387             if (opinion > 0.8)
01388                 draw_ext_info(NDI_UNIQUE, 0, op,
01389                               MSG_TYPE_SHOP, MSG_TYPE_SHOP_MISC,
01390                               "You think the shopkeeper likes you.", NULL);
01391             else if (opinion > 0.5)
01392                 draw_ext_info(NDI_UNIQUE, 0, op,
01393                               MSG_TYPE_SHOP, MSG_TYPE_SHOP_MISC,
01394                               "The shopkeeper seems unconcerned by you.", NULL);
01395             else
01396                 draw_ext_info(NDI_UNIQUE, 0, op,
01397                               MSG_TYPE_SHOP, MSG_TYPE_SHOP_MISC,
01398                               "The shopkeeper seems to have taken a dislike to you.", NULL);
01399         }
01400     } else draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SHOP, MSG_TYPE_SHOP_MISC,
01401                              "There is no shop nearby.", NULL);
01402 
01403     return 1;
01404 }
01405 
01414 int is_in_shop(object *ob) {
01415     if (!ob->map)
01416         return 0;
01417     return coords_in_shop(ob->map, ob->x, ob->y);
01418 }
01419 
01429 int coords_in_shop(mapstruct *map, int x, int y) {
01430     object *floor;
01431 
01432     for (floor = GET_MAP_OB(map, x, y); floor; floor = floor->above)
01433         if (floor->type == SHOP_FLOOR)
01434             return 1;
01435     return 0;
01436 }