Crossfire Server, Branches 1.12  R18729
shop.c
Go to the documentation of this file.
1 /*
2  * static char *rcsid_shop_c =
3  * "$Id: shop.c 11578 2009-02-23 22:02:27Z lalo $";
4  */
5 
6 /*
7  CrossFire, A Multiplayer game for X-windows
8 
9  Copyright (C) 2002 Mark Wedel & Crossfire Development Team
10  Copyright (C) 1992 Frank Tore Johansen
11 
12  This program is free software; you can redistribute it and/or modify
13  it under the terms of the GNU General Public License as published by
14  the Free Software Foundation; either version 2 of the License, or
15  (at your option) any later version.
16 
17  This program is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  GNU General Public License for more details.
21 
22  You should have received a copy of the GNU General Public License
23  along with this program; if not, write to the Free Software
24  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 
26  The authors can be reached via e-mail at crossfire-devel@real-time.com
27 */
28 
36 #include <assert.h>
37 #include <global.h>
38 #include <spells.h>
39 #include <skills.h>
40 #include <living.h>
41 #include <newclient.h>
42 #ifndef __CEXTRACT__
43 #include <sproto.h>
44 #endif
45 #include <math.h>
46 
55 #define SPECIALISATION_EFFECT 0.5
56 
58 #define DISAPPROVAL_RATIO 0.2
59 
61 #define NEUTRAL_RATIO 0.8
62 
63 static uint64 pay_from_container(object *pl, object *pouch, uint64 to_pay);
64 static uint64 value_limit(uint64 val, int quantity, const object *who, int isshop);
65 static double shop_specialisation_ratio(const object *item, const mapstruct *map);
66 static double shop_greed(const mapstruct *map);
67 
68 #define NUM_COINS 5
70 #define LARGEST_COIN_GIVEN 2
73 static const char *const coins[] = {
74  "ambercoin",
75  "jadecoin",
76  "platinacoin",
77  "goldcoin",
78  "silvercoin",
79  NULL
80 };
81 
121 uint64 query_cost(const object *tmp, object *who, int flag) {
122  uint64 val;
123  int number; /* used to better calculate value */
124  int no_bargain;
125  int identified;
126  int not_cursed;
127  int approximate;
128  int shop;
129  float diff;
130  float ratio;
131  const char *key;
132 
133  no_bargain = flag&F_NO_BARGAIN;
134  identified = flag&F_IDENTIFIED;
135  not_cursed = flag&F_NOT_CURSED;
136  approximate = flag&F_APPROX;
137  shop = flag&F_SHOP;
138  flag &= ~(F_NO_BARGAIN|F_IDENTIFIED|F_NOT_CURSED|F_APPROX|F_SHOP);
139 
140  number = tmp->nrof;
141  if (number == 0)
142  number = 1;
143 
144  if ((key = get_ob_key_value(tmp, "price_adjustment")) != NULL) {
145  ratio = atof(key);
146  return tmp->value*number*ratio;
147  }
148  if ((flag == F_BUY) && ((key = get_ob_key_value(tmp, "price_adjustment_buy")) != NULL)) {
149  ratio = atof(key);
150  return tmp->value*number*ratio;
151  }
152  if ((flag == F_SELL) && ((key = get_ob_key_value(tmp, "price_adjustment_sell")) != NULL)) {
153  ratio = atof(key);
154  return tmp->value*number*ratio;
155  }
156 
157  if (tmp->type == MONEY)
158  return (tmp->nrof*tmp->value);
159  if (tmp->type == GEM) {
160  if (flag == F_TRUE)
161  return number*tmp->value;
162  if (flag == F_BUY)
163  return (1.03*tmp->nrof*tmp->value);
164  if (flag == F_SELL)
165  return (0.97*tmp->nrof*tmp->value);
166  LOG(llevError, "Query_cost: Gem type with unknown flag : %d\n", flag);
167  return 0;
168  }
169  if (QUERY_FLAG(tmp, FLAG_IDENTIFIED)
170  || !need_identify(tmp)
171  || identified) {
172  if (!not_cursed
173  && (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED)))
174  return 0;
175  else
176  val = tmp->value*number;
177  /* This area deals with objects that are not identified, but can be */
178  } else {
179  if (tmp->arch != NULL) {
180  if (flag == F_BUY) {
181  LOG(llevError, "Asking for buy-value of unidentified object.\n");
182  val = tmp->arch->clone.value*50*number;
183  } else { /* Trying to sell something, or get true value */
184  if (tmp->type == POTION)
185  val = number*1000; /* Don't want to give anything away */
186  else {
187  /* Get 2/3 value for applied objects, 1/3 for totally
188  * unknown objects
189  */
190  if (QUERY_FLAG(tmp, FLAG_BEEN_APPLIED))
191  val = number*tmp->arch->clone.value*2/3;
192  else
193  val = number*tmp->arch->clone.value/3;
194  }
195  }
196  } else { /* No archetype with this object */
197  LOG(llevDebug, "In sell item: Have object with no archetype: %s\n", tmp->name);
198  if (flag == F_BUY) {
199  LOG(llevError, "Asking for buy-value of unidentified object without arch.\n");
200  val = number*tmp->value*10;
201  } else
202  val = number*tmp->value/5;
203  }
204  }
205 
206  /* If the item has been applied or identifed or does not need to be
207  * identified, AND the object is magical and the archetype is non
208  * magical, then change values accordingly. The tmp->arch==NULL is
209  * really just a check to prevent core dumps for when it checks
210  * tmp->arch->clone.magic for any magic. The check for archetype
211  * magic is to not give extra money for archetypes that are by
212  * default magical. This is because the archetype value should have
213  * already figured in that value.
214  */
215  if ((QUERY_FLAG(tmp, FLAG_IDENTIFIED) || !need_identify(tmp) || identified || QUERY_FLAG(tmp, FLAG_BEEN_APPLIED))
216  && tmp->magic
217  && (tmp->arch == NULL || !tmp->arch->clone.magic)) {
218  if (tmp->magic > 0)
219  val *= (3*tmp->magic*tmp->magic*tmp->magic);
220  else
221  /* Note that tmp->magic is negative, so that this
222  * will actually be something like val /=2, /=3, etc.
223  */
224  val /= (1-tmp->magic);
225  }
226 
227  if (tmp->type == WAND) {
228  /* Value of the wand is multiplied by the number of
229  * charges. the treasure code already sets up the value
230  * 50 charges is used as the baseline.
231  */
232  if (QUERY_FLAG(tmp, FLAG_IDENTIFIED)
233  || !need_identify(tmp)
234  || identified)
235  val = (val*tmp->stats.food)/50;
236  else /* if not identified, presume one charge */
237  val /= 50;
238  }
239 
240  /* Limit amount of money you can get for really great items. */
241  if (flag == F_TRUE || flag == F_SELL)
242  val = value_limit(val, number, who, shop);
243 
244  /* we need to multiply these by 4.0 to keep buy costs roughly the same
245  * (otherwise, you could buy a potion of charisma for around 400 pp.
246  * Arguable, the costs in the archetypes should be updated to better
247  * reflect values (potion charisma list for 1250 gold)
248  */
249  val *= 4;
250 
251  /* This modification is for bargaining skill.
252  * Now only players with max level in bargaining
253  * AND Cha = 30 will get optimal price.
254  * Thus charisma will never get useless.
255  * -b.e. edler@heydernet.de
256  */
257 
258  if (who != NULL && who->type == PLAYER) {
259  int lev_bargain = 0;
260  int lev_identify = 0;
261  int idskill1 = 0;
262  int idskill2 = 0;
263  const typedata *tmptype;
264 
265  /* ratio determines how much of the price modification
266  * will come from the basic stat charisma
267  * the rest will come from the level in bargaining skill
268  */
269  ratio = 0.5;
270  tmptype = get_typedata(tmp->type);
271 
273  lev_bargain = find_skill_by_number(who, SK_BARGAINING)->level;
274  }
275  if (tmptype) {
276  idskill1 = tmptype->identifyskill;
277  if (idskill1) {
278  idskill2 = tmptype->identifyskill2;
279  if (find_skill_by_number(who, idskill1)) {
280  lev_identify = find_skill_by_number(who, idskill1)->level;
281  }
282  if (idskill2 && find_skill_by_number(who, idskill2)) {
283  lev_identify += find_skill_by_number(who, idskill2)->level;
284  }
285  }
286  } else
287  LOG(llevError, "Query_cost: item %s hasn't got a valid type\n", tmp->name);
288  if (!no_bargain && (lev_bargain > 0))
289  diff = (0.8-0.6*((lev_bargain+settings.max_level*0.05)/(settings.max_level*1.05)));
290  else
291  diff = 0.8;
292 
293  diff *= 1-ratio;
294 
295  /* Diff is now a float between 0.2 and 0.8 */
296  diff += (cha_bonus[who->stats.Cha]-1)/(1+cha_bonus[who->stats.Cha])*ratio;
297 
298  if (flag == F_BUY)
299  val = (val*(long)(1000*(1+diff)))/1000;
300  else if (flag == F_SELL)
301  val = (val*(long)(1000*(1-diff)))/1000;
302 
303  /* If we are approximating, then the value returned should
304  * be allowed to be wrong however merely using a random number
305  * each time will not be sufficient, as then multiple examinations
306  * would give different answers, so we'll use the count instead.
307  * By taking the sine of the count, a value between -1 and 1 is
308  * generated, we then divide by the square root of the bargaining
309  * skill and the appropriate identification skills, so that higher
310  * level players get better estimates. (We need a +1 there to
311  * prevent dividing by zero.)
312  */
313  if (approximate)
314  val = (sint64)val+(sint64)((sint64)val*(sin(tmp->count)/sqrt(lev_bargain+lev_identify*2+1.0)));
315  }
316 
317  /* I don't think this should really happen - if it does,
318  * it indicates an overflow of diff above. That should only
319  * happen if we are selling objects - in that case, the person
320  * just gets no money.
321  */
322  if ((sint64)val < 0)
323  val = 0;
324 
325  /* Unidentified stuff won't sell for more than 60gp */
326  if (flag == F_SELL
327  && !QUERY_FLAG(tmp, FLAG_IDENTIFIED)
328  && need_identify(tmp)
329  && !identified) {
330  val = MIN(val, 600);
331  }
332 
333  /* if in a shop, check how the type of shop should affect the price */
334  if (shop && who) {
335  if (flag == F_SELL)
336  val = (sint64)val*shop_specialisation_ratio(tmp, who->map)
337  *shopkeeper_approval(who->map, who)/shop_greed(who->map);
338  else if (flag == F_BUY) {
339  /*
340  * When buying, if the item was sold by another player, it is
341  * ok to let the item be sold cheaper, according to the
342  * specialisation of the shop. If a player sold an item here,
343  * then his sale price was multiplied by the specialisation
344  * ratio, to do the same to the buy price will not generate
345  * extra money. However, the same is not true of generated
346  * items, these have to /divide/ by the specialisation, so
347  * that the price is never less than what they could
348  * be sold for (otherwise players could camp map resets to
349  * make money).
350  * In game terms, a non-specialist shop might not recognise
351  * the true value of the items it sells (much like how people
352  * sometimes find antiques in a junk shop in real life).
353  */
354  if (QUERY_FLAG(tmp, FLAG_PLAYER_SOLD))
355  val = (sint64)val*shop_greed(who->map)
356  *shop_specialisation_ratio(tmp, who->map)
357  /shopkeeper_approval(who->map, who);
358  else
359  val = (sint64)val*shop_greed(who->map)
360  /(shop_specialisation_ratio(tmp, who->map)
361  *shopkeeper_approval(who->map, who));
362  }
363  /* We will also have an extra 0-5% variation between shops of
364  * the same type for valuable items (below a value of 50 this
365  * effect wouldn't be very meaningful, and could give fun with
366  * rounding.
367  */
368  if (who->map->path != NULL && val > 50)
369  val = (sint64)val+0.05*(sint64)val*cos(tmp->count+strlen(who->map->path));
370  }
371  return val;
372 }
373 
385 static archetype *find_next_coin(uint64 c, int *cointype) {
386  archetype *coin;
387 
388  do {
389  if (coins[*cointype] == NULL)
390  return NULL;
391  coin = find_archetype(coins[*cointype]);
392  if (coin == NULL)
393  return NULL;
394  *cointype += 1;
395  } while (coin->clone.value > c);
396 
397  return coin;
398 }
399 
418  archetype *coin, *next_coin;
419  uint32 num;
420  int cointype = LARGEST_COIN_GIVEN;
421 
422  if (!buf)
423  buf = stringbuffer_new();
424 
425  coin = find_next_coin(cost, &cointype);
426  if (coin == NULL) {
427  stringbuffer_append_string(buf, "nothing");
428  return buf;
429  }
430 
431  num = cost/coin->clone.value;
432  /* so long as nrof is 32 bit, this is true.
433  * If it takes more coins than a person can possibly carry, this
434  * is basically true.
435  */
436  if ((cost/coin->clone.value) > UINT32_MAX) {
437  stringbuffer_append_string(buf, "an unimaginable sum of money.");
438  return buf;
439  }
440 
441  cost -= (uint64)num*(uint64)coin->clone.value;
442  if (num == 1)
443  stringbuffer_append_printf(buf, "1 %s", coin->clone.name);
444  else
445  stringbuffer_append_printf(buf, "%u %ss", num, coin->clone.name);
446 
447  next_coin = find_next_coin(cost, &cointype);
448  if (next_coin == NULL)
449  return buf;
450 
451  do {
452  coin = next_coin;
453  num = cost/coin->clone.value;
454  cost -= (uint64)num*(uint64)coin->clone.value;
455 
456  if (cost == 0)
457  next_coin = NULL;
458  else
459  next_coin = find_next_coin(cost, &cointype);
460 
461  if (next_coin) {
462  /* There will be at least one more string to add to the list,
463  * use a comma.
464  */
465  stringbuffer_append_string(buf, ", ");
466  } else {
467  stringbuffer_append_string(buf, " and ");
468  }
469  if (num == 1)
470  stringbuffer_append_printf(buf, "1 %s", coin->clone.name);
471  else
472  stringbuffer_append_printf(buf, "%u %ss", num, coin->clone.name);
473  } while (next_coin);
474 
475  return buf;
476 }
477 
488 static StringBuffer *real_money_value(const object *coin, StringBuffer *buf) {
489  assert(coin->type == MONEY);
490  assert(buf);
491 
492  stringbuffer_append_printf(buf, "%ld %s", coin->nrof, coin->nrof == 1 ? coin->name : coin->name_pl);
493  return buf;
494 }
495 
511 StringBuffer *query_cost_string(const object *tmp, object *who, int flag, StringBuffer *buf) {
512  uint64 real_value = query_cost(tmp, who, flag);
513  int idskill1 = 0;
514  int idskill2 = 0;
515  const typedata *tmptype;
516 
517  if (!buf)
518  buf = stringbuffer_new();
519 
520  /* money it's pretty hard to not give the exact price, so skip all logic and just return the real value. */
521  if (tmp->type == MONEY) {
522  return real_money_value(tmp, buf);
523  }
524 
525  tmptype = get_typedata(tmp->type);
526  if (tmptype) {
527  idskill1 = tmptype->identifyskill;
528  idskill2 = tmptype->identifyskill2;
529  }
530 
531  /* we show an approximate price if
532  * 1) we are approximating
533  * 2) there either is no id skill(s) for the item, or we don't have them
534  * 3) we don't have bargaining skill either
535  */
536  if (flag&F_APPROX) {
537  if (!idskill1 || !find_skill_by_number(who, idskill1)) {
538  if (!idskill2 || !find_skill_by_number(who, idskill2)) {
539  if (!find_skill_by_number(who, SK_BARGAINING)) {
540  int num;
541  int cointype = LARGEST_COIN_GIVEN;
542  archetype *coin = find_next_coin(real_value, &cointype);
543 
544  if (coin == NULL) {
545  stringbuffer_append_string(buf, "nothing");
546  return buf;
547  }
548 
549  num = real_value/coin->clone.value;
550  if (num == 1)
551  stringbuffer_append_printf(buf, "about one %s", coin->clone.name);
552  else if (num < 5)
553  stringbuffer_append_printf(buf, "a few %s", coin->clone.name_pl);
554  else if (num < 10)
555  stringbuffer_append_printf(buf, "several %s", coin->clone.name_pl);
556  else if (num < 25)
557  stringbuffer_append_printf(buf, "a moderate amount of %s", coin->clone.name_pl);
558  else if (num < 100)
559  stringbuffer_append_printf(buf, "lots of %s", coin->clone.name_pl);
560  else if (num < 1000)
561  stringbuffer_append_printf(buf, "a great many %s", coin->clone.name_pl);
562  else
563  stringbuffer_append_printf(buf, "a vast quantity of %s", coin->clone.name_pl);
564  return buf;
565  }
566  }
567  }
568  }
569  return cost_string_from_value(real_value, buf);
570 }
571 
581 uint64 query_money(const object *op) {
582  object *tmp;
583  uint64 total = 0;
584 
585  if (op->type != PLAYER && op->type != CONTAINER) {
586  LOG(llevError, "Query money called with non player/container\n");
587  return 0;
588  }
589  for (tmp = op->inv; tmp; tmp = tmp->below) {
590  if (tmp->type == MONEY) {
591  total += (uint64)tmp->nrof*(uint64)tmp->value;
592  } else if (tmp->type == CONTAINER
593  && QUERY_FLAG(tmp, FLAG_APPLIED)
594  && (tmp->race == NULL || strstr(tmp->race, "gold"))) {
595  total += query_money(tmp);
596  }
597  }
598  return total;
599 }
600 
613 int pay_for_amount(uint64 to_pay, object *pl) {
614  object *pouch;
615 
616  if (to_pay == 0)
617  return 1;
618  if (to_pay > query_money(pl))
619  return 0;
620 
621  to_pay = pay_from_container(pl, pl, to_pay);
622 
623  for (pouch = pl->inv; (pouch != NULL) && (to_pay > 0); pouch = pouch->below) {
624  if (pouch->type == CONTAINER
625  && QUERY_FLAG(pouch, FLAG_APPLIED)
626  && (pouch->race == NULL || strstr(pouch->race, "gold"))) {
627  to_pay = pay_from_container(pl, pouch, to_pay);
628  }
629  }
630  if (to_pay > 0) {
631  LOG(llevError, "pay_for_amount: Cannot remove enough money -- %"FMT64U" remains\n", to_pay);
632  }
633 
634  fix_object(pl);
635  return 1;
636 }
637 
652 int pay_for_item(object *op, object *pl) {
653  uint64 to_pay = query_cost(op, pl, F_BUY|F_SHOP);
654  object *pouch;
655  uint64 saved_money;
656 
657  if (to_pay == 0)
658  return 1;
659  if (to_pay > query_money(pl))
660  return 0;
661 
662  /* We compare the paid price with the one for a player
663  * without bargaining skill.
664  * This determins the amount of exp (if any) gained for bargaining.
665  */
666  saved_money = query_cost(op, pl, F_BUY|F_NO_BARGAIN|F_SHOP)-to_pay;
667 
668  if (saved_money > 0)
669  change_exp(pl, saved_money, "bargaining", SK_EXP_NONE);
670 
671  to_pay = pay_from_container(pl, pl, to_pay);
672 
673  for (pouch = pl->inv; (pouch != NULL) && (to_pay > 0); pouch = pouch->below) {
674  if (pouch->type == CONTAINER
675  && QUERY_FLAG(pouch, FLAG_APPLIED)
676  && (pouch->race == NULL || strstr(pouch->race, "gold"))) {
677  to_pay = pay_from_container(pl, pouch, to_pay);
678  }
679  }
680  if (to_pay > 0) {
681  LOG(llevError, "pay_for_item: Cannot remove enough money -- %"FMT64U" remains\n", to_pay);
682  }
684  SET_FLAG(op, FLAG_WAS_WIZ);
685  fix_object(pl);
686  return 1;
687 }
688 
700 static sint64 remove_value(object *coin_objs[], sint64 remain) {
701  int i;
702 
703  for (i = 0; i < NUM_COINS; i++) {
704  int count;
705  sint64 num_coins;
706 
707  if (coin_objs[i]->nrof*coin_objs[i]->value > remain) {
708  num_coins = remain/coin_objs[i]->value;
709  if ((uint64)num_coins*(uint64)coin_objs[i]->value < remain) {
710  num_coins++;
711  }
712  } else {
713  num_coins = coin_objs[i]->nrof;
714  }
715  remain -= (sint64)num_coins*(sint64)coin_objs[i]->value;
716  coin_objs[i]->nrof -= num_coins;
717  /* Now start making change. Start at the coin value
718  * below the one we just did, and work down to
719  * the lowest value.
720  */
721  count = i-1;
722  while (remain < 0 && count >= 0) {
723  num_coins = -remain/coin_objs[count]->value;
724  coin_objs[count]->nrof += num_coins;
725  remain += num_coins*coin_objs[count]->value;
726  count--;
727  }
728  }
729 
730  return remain;
731 }
732 
741 static void add_value(object *coin_objs[], sint64 value) {
742  int i;
743 
744  for (i = NUM_COINS-LARGEST_COIN_GIVEN-1; i >= 0; i--) {
745  uint32 nrof;
746 
747  nrof = (uint32)(value/coin_objs[i]->value);
748  value -= nrof*coin_objs[i]->value;
749  coin_objs[i]->nrof += nrof;
750  }
751 }
752 
765 static void insert_objects(object *pl, object *container, object *objects[], int objects_len) {
766  int i, one = 0;
767 
768  for (i = 0; i < objects_len; i++) {
769  if (objects[i]->nrof > 0) {
770  insert_ob_in_ob(objects[i], container);
771  one = 1;
772  } else {
773  free_object(objects[i]);
774  }
775  }
776  if (one)
777  esrv_update_item(UPD_WEIGHT, pl, container);
778 }
779 
796 static uint64 pay_from_container(object *pl, object *pouch, uint64 to_pay) {
797  int i;
798  sint64 remain;
799  object *tmp, *coin_objs[NUM_COINS], *next;
800  object *other_money[16]; /* collects MONEY objects not matching coins[] */
801  size_t other_money_len; /* number of allocated entries in other_money[] */
802  archetype *at;
803 
804  if (pouch->type != PLAYER && pouch->type != CONTAINER)
805  return to_pay;
806 
807  remain = to_pay;
808  for (i = 0; i < NUM_COINS; i++)
809  coin_objs[i] = NULL;
810 
811  /* This hunk should remove all the money objects from the player/container */
812  other_money_len = 0;
813  for (tmp = pouch->inv; tmp; tmp = next) {
814  next = tmp->below;
815  if (tmp->type == MONEY) {
816  for (i = 0; i < NUM_COINS; i++) {
817  if (!strcmp(coins[NUM_COINS-1-i], tmp->arch->name)
818  && (tmp->value == tmp->arch->clone.value)) {
819 
820  /* This should not happen, but if it does, just
821  * merge the two.
822  */
823  if (coin_objs[i] != NULL) {
824  LOG(llevError, "%s has two money entries of (%s)\n", pouch->name, coins[NUM_COINS-1-i]);
825  remove_ob(tmp);
826  coin_objs[i]->nrof += tmp->nrof;
827  free_object(tmp);
828  } else {
829  remove_ob(tmp);
830  coin_objs[i] = tmp;
831  }
832  break;
833  }
834  }
835  if (i == NUM_COINS) {
836  if (other_money_len >= sizeof(other_money)/sizeof(*other_money)) {
837  LOG(llevError, "pay_for_item: Cannot store non-standard money object %s\n", tmp->arch->name);
838  } else {
839  remove_ob(tmp);
840  other_money[other_money_len++] = tmp;
841  }
842  }
843  }
844  }
845 
846  /* Fill in any gaps in the coin_objs array - needed to make change. */
847  /* Note that the coin_objs array goes from least value to greatest value */
848  for (i = 0; i < NUM_COINS; i++)
849  if (coin_objs[i] == NULL) {
850  at = find_archetype(coins[NUM_COINS-1-i]);
851  if (at == NULL)
852  LOG(llevError, "Could not find %s archetype\n", coins[NUM_COINS-1-i]);
853  coin_objs[i] = get_object();
854  copy_object(&at->clone, coin_objs[i]);
855  coin_objs[i]->nrof = 0;
856  }
857 
858  /* Try to pay from standard coins first. */
859  remain = remove_value(coin_objs, remain);
860 
861  /* Now pay from non-standard coins until all is paid. */
862  for (i = 0; i < other_money_len && remain > 0; i++) {
863  uint32 nrof;
864  object *coin;
865 
866  coin = other_money[i];
867 
868  /* Find the minimal number of coins to use. This prevents converting
869  * excess non-standard coins to standard money.
870  */
871  nrof = (remain+coin->value-1)/coin->value;
872  if (nrof > coin->nrof) {
873  nrof = coin->nrof;
874  }
875  coin->nrof -= nrof;
876  add_value(coin_objs, nrof*coin->value);
877 
878  remain = remove_value(coin_objs, remain);
879  }
880 
881  /* re-insert remaining coins into player */
882  insert_objects(pl, pouch, coin_objs, NUM_COINS);
883  insert_objects(pl, pouch, other_money, other_money_len);
884 
885  return(remain);
886 }
887 
904 static void count_unpaid(object *pl, object *item, int *unpaid_count, uint64 *unpaid_price, uint32 *coincount) {
905  int i;
906 
907  for (; item; item = item->below) {
908  if QUERY_FLAG(item, FLAG_UNPAID) {
909  (*unpaid_count)++;
910  (*unpaid_price) += query_cost(item, pl, F_BUY|F_SHOP);
911  }
912  /* Merely converting the player's monetary wealth won't do.
913  * If we did that, we could print the wrong numbers for the
914  * coins, so we count the money instead.
915  */
916  for (i = 0; i < NUM_COINS; i++)
917  if (!strcmp(coins[i], item->arch->name)) {
918  coincount[i] += item->nrof;
919  break;
920  }
921  if (item->inv)
922  count_unpaid(pl, item->inv, unpaid_count, unpaid_price, coincount);
923  }
924 }
925 
938 int can_pay(object *pl) {
939  int unpaid_count = 0, i;
940  uint64 unpaid_price = 0;
941  uint64 player_wealth = query_money(pl);
942  uint32 coincount[NUM_COINS];
943 
944  if (!pl || pl->type != PLAYER) {
945  LOG(llevError, "can_pay(): called against something that isn't a player\n");
946  return 0;
947  }
948 
949  for (i = 0; i < NUM_COINS; i++)
950  coincount[i] = 0;
951 
952  count_unpaid(pl, pl->inv, &unpaid_count, &unpaid_price, coincount);
953 
954  if (unpaid_price > player_wealth) {
955  char buf[MAX_BUF], coinbuf[MAX_BUF];
956  int denominations = 0;
957  char *value = stringbuffer_finish(cost_string_from_value(unpaid_price, NULL));
958 
959  snprintf(buf, sizeof(buf), "You have %d unpaid items that would cost you %s, ", unpaid_count, value);
960  free(value);
961  for (i = 0; i < NUM_COINS; i++) {
962  if (coincount[i] > 0 && coins[i]) {
963  if (denominations == 0)
964  snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "but you only have");
965  denominations++;
966  snprintf(coinbuf, sizeof(coinbuf), " %u %s,", coincount[i], find_archetype(coins[i])->clone.name_pl);
967  snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%s", coinbuf);
968  }
969  }
970  if (denominations == 0)
971  snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "but you don't have any money.");
972  else if (denominations > 1)
973  make_list_like(buf);
975  MSG_TYPE_SHOP_PAYMENT, buf, NULL);
976  return 0;
977  } else
978  return 1;
979 }
980 
992 int get_payment(object *pl, object *op) {
993  char name_op[MAX_BUF];
994  int ret = 1;
995 
996  if (op != NULL && op->inv)
997  ret = get_payment(pl, op->inv);
998 
999  if (!ret)
1000  return 0;
1001 
1002  if (op != NULL && op->below)
1003  ret = get_payment(pl, op->below);
1004 
1005  if (!ret)
1006  return 0;
1007 
1008  if (op != NULL && QUERY_FLAG(op, FLAG_UNPAID)) {
1009  if (!pay_for_item(op, pl)) {
1010  uint64 i = query_cost(op, pl, F_BUY|F_SHOP)-query_money(pl);
1011  char *missing = stringbuffer_finish(cost_string_from_value(i, NULL));
1012 
1013  CLEAR_FLAG(op, FLAG_UNPAID);
1014  query_name(op, name_op, MAX_BUF);
1017  "You lack %s to buy %s.",
1018  "You lack %s to buy %s.",
1019  missing, name_op);
1020  free(missing);
1021  SET_FLAG(op, FLAG_UNPAID);
1022  return 0;
1023  } else {
1024  object *tmp;
1025  char *value = stringbuffer_finish(query_cost_string(op, pl, F_BUY|F_SHOP, NULL));
1026 
1027  CLEAR_FLAG(op, FLAG_UNPAID);
1029  query_name(op, name_op, MAX_BUF);
1032  "You paid %s for %s.",
1033  "You paid %s for %s.",
1034  value, name_op);
1035  free(value);
1036  tmp = merge_ob(op, NULL);
1037  if (pl->type == PLAYER && !tmp) {
1038  /* If item wasn't merged we update it. If merged, merge_ob handled everything for us. */
1040  }
1041  }
1042  }
1043  return 1;
1044 }
1045 
1059 void sell_item(object *op, object *pl) {
1060  uint64 i = query_cost(op, pl, F_SELL|F_SHOP), extra_gain;
1061  int count;
1062  object *tmp, *pouch;
1063  archetype *at;
1064  char name_op[MAX_BUF], *value;
1065 
1066  if (pl == NULL || pl->type != PLAYER) {
1067  LOG(llevDebug, "Object other than player tried to sell something.\n");
1068  return;
1069  }
1070 
1071  if (op->custom_name)
1073 
1074  if (!i) {
1075  query_name(op, name_op, MAX_BUF);
1078  "We're not interested in %s.",
1079  "We're not interested in %s.",
1080  name_op);
1081 
1082  /* Even if the character doesn't get anything for it, it may still be
1083  * worth something. If so, make it unpaid
1084  */
1085  if (op->value) {
1086  SET_FLAG(op, FLAG_UNPAID);
1088  }
1089  identify(op);
1090  return;
1091  }
1092 
1093  /* We compare the price with the one for a player
1094  * without bargaining skill.
1095  * This determins the amount of exp (if any) gained for bargaining.
1096  * exp/10 -> 1 for each gold coin
1097  */
1098  extra_gain = i-query_cost(op, pl, F_SELL|F_NO_BARGAIN|F_SHOP);
1099 
1100  if (extra_gain > 0)
1101  change_exp(pl, extra_gain/10, "bargaining", SK_EXP_NONE);
1102 
1103  for (count = LARGEST_COIN_GIVEN; coins[count] != NULL; count++) {
1104  at = find_archetype(coins[count]);
1105  if (at == NULL)
1106  LOG(llevError, "Could not find %s archetype\n", coins[count]);
1107  else if ((i/at->clone.value) > 0) {
1108  for (pouch = pl->inv; pouch; pouch = pouch->below) {
1109  if (pouch->type == CONTAINER
1110  && QUERY_FLAG(pouch, FLAG_APPLIED)
1111  && pouch->race
1112  && strstr(pouch->race, "gold")) {
1113  int w = at->clone.weight*(100-pouch->stats.Str)/100;
1114  int n = i/at->clone.value;
1115 
1116  if (w == 0)
1117  w = 1; /* Prevent divide by zero */
1118  if (n > 0
1119  && (!pouch->weight_limit || pouch->carrying+w <= pouch->weight_limit)) {
1120  if (pouch->weight_limit
1121  && (pouch->weight_limit-pouch->carrying)/w < n)
1122  n = (pouch->weight_limit-pouch->carrying)/w;
1123 
1124  tmp = get_object();
1125  copy_object(&at->clone, tmp);
1126  tmp->nrof = n;
1127  i -= (uint64)tmp->nrof*(uint64)tmp->value;
1128  tmp = insert_ob_in_ob(tmp, pouch);
1129  esrv_update_item(UPD_WEIGHT, pl, pl);
1130  }
1131  }
1132  }
1133  if (i/at->clone.value > 0) {
1134  tmp = get_object();
1135  copy_object(&at->clone, tmp);
1136  tmp->nrof = i/tmp->value;
1137  i -= (uint64)tmp->nrof*(uint64)tmp->value;
1138  tmp = insert_ob_in_ob(tmp, pl);
1139  esrv_update_item(UPD_WEIGHT, pl, pl);
1140  }
1141  }
1142  }
1143 
1144  if (i != 0)
1145 #ifndef WIN32
1146  LOG(llevError, "Warning - payment not zero: %llu\n", i);
1147 #else
1148  LOG(llevError, "Warning - payment not zero: %I64u\n", i);
1149 #endif
1150 
1151  query_name(op, name_op, MAX_BUF);
1152  value = stringbuffer_finish(query_cost_string(op, pl, F_SELL|F_SHOP, NULL));
1153 
1155  "You receive %s for %s.",
1156  "You receive %s for %s.",
1157  value,
1158  name_op);
1159 
1160  free(value);
1161 
1162  SET_FLAG(op, FLAG_UNPAID);
1163  identify(op);
1164 }
1165 
1179 static double shop_specialisation_ratio(const object *item, const mapstruct *map) {
1180  shopitems *items = map->shopitems;
1181  double ratio = SPECIALISATION_EFFECT, likedness = 0.001;
1182  int i;
1183 
1184  if (item == NULL) {
1185  LOG(llevError, "shop_specialisation_ratio: passed a NULL item for map %s\n", map->path);
1186  return 0;
1187  }
1188  if (!item->type) {
1189  LOG(llevError, "shop_specialisation_ratio: passed an item with an invalid type\n");
1190  /*
1191  * I'm not really sure what the /right/ thing to do here is,
1192  * these types of item shouldn't exist anyway, but returning
1193  * the ratio is probably the best bet.."
1194  */
1195  return ratio;
1196  }
1197  if (map->shopitems) {
1198  for (i = 0; i < items[0].index; i++)
1199  if (items[i].typenum == item->type || (!items[i].typenum && likedness == 0.001))
1200  likedness = items[i].strength/100.0;
1201  }
1202  if (likedness > 1.0) { /* someone has been rather silly with the map headers. */
1203  LOG(llevDebug, "shop_specialisation ratio: item type %d on map %s is above 100%%\n", item->type, map->path);
1204  likedness = 1.0;
1205  }
1206  if (likedness < -1.0) {
1207  LOG(llevDebug, "shop_specialisation ratio: item type %d on map %s is below -100%%\n", item->type, map->path);
1208  likedness = -1.0;
1209  }
1210  ratio = ratio+(1.0-ratio)*likedness;
1211  if (ratio <= 0.1)
1212  ratio = 0.1; /* if the ratio were much lower than this, we would get silly prices */
1213  return ratio;
1214 }
1215 
1224 static double shop_greed(const mapstruct *map) {
1225  double greed = 1.0;
1226 
1227  if (map->shopgreed)
1228  return map->shopgreed;
1229  return greed;
1230 }
1231 
1243 double shopkeeper_approval(const mapstruct *map, const object *player) {
1244  double approval = 1.0;
1245 
1246  if (map->shoprace) {
1247  approval = NEUTRAL_RATIO;
1248  if (player->race && !strcmp(player->race, map->shoprace))
1249  approval = 1.0;
1250  }
1251  return approval;
1252 }
1253 
1273 static uint64 value_limit(uint64 val, int quantity, const object *who, int isshop) {
1274  uint64 newval, unit_price;
1275  mapstruct *map;
1276 
1277  unit_price = val/quantity;
1278  if (!isshop || !who) {
1279  if (unit_price > 10000)
1280  newval = 8000+isqrt(unit_price)*20;
1281  else
1282  newval = unit_price;
1283  } else {
1284  if (!who->map) {
1285  LOG(llevError, "value_limit: asked shop price for ob %s on NULL map\n", who->name);
1286  return val;
1287  }
1288  map = who->map;
1289  if (map->shopmin && unit_price < map->shopmin)
1290  return 0;
1291  else if (map->shopmax && unit_price > map->shopmax/2)
1292  newval = MIN((map->shopmax/2)+isqrt(unit_price-map->shopmax/2), map->shopmax);
1293  else if (unit_price > 10000)
1294  newval = 8000+isqrt(unit_price)*20;
1295  else
1296  newval = unit_price;
1297  }
1298  newval *= quantity;
1299  return newval;
1300 }
1301 
1311 int describe_shop(const object *op) {
1312  mapstruct *map = op->map;
1313  /*shopitems *items=map->shopitems;*/
1314  int pos = 0, i;
1315  double opinion = 0;
1316  char tmp[MAX_BUF] = "\0", *value;
1317 
1318  if (op->type != PLAYER)
1319  return 0;
1320 
1321  /*check if there is a shop specified for this map */
1322  if (map->shopitems
1323  || map->shopgreed
1324  || map->shoprace
1325  || map->shopmin
1326  || map->shopmax) {
1328  "From looking at the nearby shop you determine that it trades in:",
1329  NULL);
1330 
1331  if (map->shopitems) {
1332  for (i = 0; i < map->shopitems[0].index; i++) {
1333  if (map->shopitems[i].name && map->shopitems[i].strength > 10) {
1334  snprintf(tmp+pos, sizeof(tmp)-pos, "%s, ", map->shopitems[i].name_pl);
1335  pos += strlen(tmp+pos);
1336  }
1337  }
1338  }
1339  if (!pos)
1340  strcpy(tmp, "a little of everything.");
1341 
1342  /* format the string into a list */
1343  make_list_like(tmp);
1344  draw_ext_info(NDI_UNIQUE, 0, op,
1345  MSG_TYPE_SHOP, MSG_TYPE_SHOP_LISTING, tmp, NULL);
1346 
1347  if (map->shopmax) {
1348  value = stringbuffer_finish(cost_string_from_value(map->shopmax, NULL));
1351  "It won't trade for items above %s.",
1352  "It won't trade for items above %s.",
1353  value);
1354  free(value);
1355  }
1356 
1357  if (map->shopmin) {
1358  value = stringbuffer_finish(cost_string_from_value(map->shopmin, NULL));
1361  "It won't trade in items worth less than %s.",
1362  "It won't trade in items worth less than %s.",
1363  value);
1364  free(value);
1365  }
1366 
1367  if (map->shopgreed) {
1368  if (map->shopgreed > 2.0)
1369  draw_ext_info(NDI_UNIQUE, 0, op,
1371  "It tends to overcharge massively.", NULL);
1372  else if (map->shopgreed > 1.5)
1373  draw_ext_info(NDI_UNIQUE, 0, op,
1375  "It tends to overcharge substantially.", NULL);
1376  else if (map->shopgreed > 1.1)
1377  draw_ext_info(NDI_UNIQUE, 0, op,
1379  "It tends to overcharge slightly.", NULL);
1380  else if (map->shopgreed < 0.9)
1381  draw_ext_info(NDI_UNIQUE, 0, op,
1383  "It tends to undercharge.", NULL);
1384  }
1385  if (map->shoprace) {
1386  opinion = shopkeeper_approval(map, op);
1387  if (opinion > 0.8)
1388  draw_ext_info(NDI_UNIQUE, 0, op,
1390  "You think the shopkeeper likes you.", NULL);
1391  else if (opinion > 0.5)
1392  draw_ext_info(NDI_UNIQUE, 0, op,
1394  "The shopkeeper seems unconcerned by you.", NULL);
1395  else
1396  draw_ext_info(NDI_UNIQUE, 0, op,
1398  "The shopkeeper seems to have taken a dislike to you.", NULL);
1399  }
1401  "There is no shop nearby.", NULL);
1402 
1403  return 1;
1404 }
1405 
1414 int is_in_shop(object *ob) {
1415  if (!ob->map)
1416  return 0;
1417  return coords_in_shop(ob->map, ob->x, ob->y);
1418 }
1419 
1429 int coords_in_shop(mapstruct *map, int x, int y) {
1430  object *floor;
1431 
1432  for (floor = GET_MAP_OB(map, x, y); floor; floor = floor->above)
1433  if (floor->type == SHOP_FLOOR)
1434  return 1;
1435  return 0;
1436 }
#define SK_BARGAINING
Definition: skills.h:56
#define UPD_FLAGS
Definition: newclient.h:255
char path[HUGE_BUF]
Definition: map.h:384
uint64 shopmax
Definition: map.h:379
Definition: player.h:146
#define FLAG_PLAYER_SOLD
Definition: define.h:548
double shopgreed
Definition: map.h:377
archetype * find_archetype(const char *name)
Definition: arch.c:700
#define FLAG_DAMNED
Definition: define.h:614
#define FLAG_UNPAID
Definition: define.h:532
int get_payment(object *pl, object *op)
Definition: shop.c:992
#define FALSE
Definition: exp.c:42
const char * get_ob_key_value(const object *op, const char *const key)
Definition: object.c:3701
static const char *const coins[]
Definition: shop.c:73
int is_in_shop(object *ob)
Definition: shop.c:1414
void change_exp(object *op, sint64 exp, const char *skill_name, int flag)
Definition: living.c:2015
static StringBuffer * real_money_value(const object *coin, StringBuffer *buf)
Definition: shop.c:488
const char * race
Definition: object.h:171
#define SET_FLAG(xyz, p)
Definition: define.h:510
static StringBuffer * cost_string_from_value(uint64 cost, StringBuffer *buf)
Definition: shop.c:417
int identifyskill
Definition: define.h:381
#define F_SELL
Definition: define.h:776
#define NUM_COINS
Definition: shop.c:68
#define WAND
Definition: define.h:291
#define UPD_NAME
Definition: newclient.h:258
#define MONEY
Definition: define.h:148
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.c:64
int coords_in_shop(mapstruct *map, int x, int y)
Definition: shop.c:1429
static double shop_specialisation_ratio(const object *item, const mapstruct *map)
Definition: shop.c:1179
void esrv_update_item(int flags, object *pl, object *op)
Definition: standalone.c:200
sint16 max_level
Definition: global.h:391
object clone
Definition: object.h:326
#define POTION
Definition: define.h:117
object * merge_ob(object *op, object *top)
Definition: object.c:1724
void draw_ext_info(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *message, const char *oldmessage)
Definition: standalone.c:171
struct obj * above
Definition: object.h:146
static uint64 value_limit(uint64 val, int quantity, const object *who, int isshop)
Definition: shop.c:1273
const char * name
Definition: map.h:327
static void insert_objects(object *pl, object *container, object *objects[], int objects_len)
Definition: shop.c:765
sint16 x
Definition: object.h:179
#define F_TRUE
Definition: define.h:777
#define MSG_TYPE_SHOP_LISTING
Definition: newclient.h:426
void draw_ext_info_format(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *new_format, const char *old_format,...)
Definition: standalone.c:175
#define F_BUY
Definition: define.h:775
Definition: object.h:321
#define F_NOT_CURSED
Definition: define.h:780
int describe_shop(const object *op)
Definition: shop.c:1311
#define PLAYER
Definition: define.h:113
int typenum
Definition: map.h:329
int can_pay(object *pl)
Definition: shop.c:938
uint64 query_cost(const object *tmp, object *who, int flag)
Definition: shop.c:121
const typedata * get_typedata(int itemtype)
Definition: item.c:352
void make_list_like(char *input)
Definition: utils.c:485
void remove_ob(object *op)
Definition: object.c:1515
int pay_for_item(object *op, object *pl)
Definition: shop.c:652
#define F_IDENTIFIED
Definition: define.h:779
#define SHOP_FLOOR
Definition: define.h:230
sint32 weight_limit
Definition: object.h:217
const char * name_pl
Definition: object.h:168
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Definition: stringbuffer.c:97
#define MSG_TYPE_SHOP_MISC
Definition: newclient.h:431
int index
Definition: map.h:332
#define MSG_TYPE_SHOP
Definition: newclient.h:325
StringBuffer * query_cost_string(const object *tmp, object *who, int flag, StringBuffer *buf)
Definition: shop.c:511
sint32 weight
Definition: object.h:216
struct mapdef * map
Definition: object.h:155
#define FLAG_IDENTIFIED
Definition: define.h:557
void identify(object *op)
Definition: item.c:1447
#define F_SHOP
Definition: define.h:782
sint32 carrying
Definition: object.h:218
object * objects
Definition: object.c:70
const char * name
Definition: object.h:167
static double shop_greed(const mapstruct *map)
Definition: shop.c:1224
struct obj * below
Definition: object.h:145
uint32 nrof
Definition: object.h:184
sint8 Cha
Definition: living.h:78
const float cha_bonus[MAX_STAT+1]
Definition: living.c:94
#define MSG_TYPE_SHOP_PAYMENT
Definition: newclient.h:428
sint16 y
Definition: object.h:179
#define FREE_AND_CLEAR_STR(xyz)
Definition: global.h:283
sint8 strength
Definition: map.h:330
#define QUERY_FLAG(xyz, p)
Definition: define.h:514
#define CLEAR_FLAG(xyz, p)
Definition: define.h:512
#define GEM
Definition: define.h:202
#define FLAG_BEEN_APPLIED
Definition: define.h:620
object * insert_ob_in_ob(object *op, object *where)
Definition: object.c:2510
#define MAX_BUF
Definition: define.h:81
static void count_unpaid(object *pl, object *item, int *unpaid_count, uint64 *unpaid_price, uint32 *coincount)
Definition: shop.c:904
object * get_object(void)
Definition: object.c:921
int identifyskill2
Definition: define.h:382
#define MIN(x, y)
Definition: define.h:67
sint8 Str
Definition: living.h:78
#define F_APPROX
Definition: define.h:781
int need_identify(const object *op)
Definition: item.c:1401
#define FLAG_CURSED
Definition: define.h:613
int snprintf(char *dest, int max, const char *format,...)
Definition: porting.c:498
double shopkeeper_approval(const mapstruct *map, const object *player)
Definition: shop.c:1243
#define CONTAINER
Definition: define.h:306
static uint64 pay_from_container(object *pl, object *pouch, uint64 to_pay)
Definition: shop.c:796
const char * custom_name
Definition: object.h:285
tag_t count
Definition: object.h:157
const char * name_pl
Definition: map.h:328
living stats
Definition: object.h:219
struct archt * arch
Definition: object.h:263
#define LARGEST_COIN_GIVEN
Definition: shop.c:70
struct Settings settings
Definition: init.c:48
int isqrt(int n)
Definition: porting.c:573
#define SK_EXP_NONE
Definition: skills.h:105
#define UINT32_MAX
Definition: global.h:61
Definition: map.h:326
#define FLAG_APPLIED
Definition: define.h:531
void sell_item(object *op, object *pl)
Definition: shop.c:1059
const uint32 weight_limit[MAX_STAT+1]
Definition: living.c:143
#define MSG_TYPE_SHOP_SELL
Definition: newclient.h:430
#define SPECIALISATION_EFFECT
Definition: shop.c:55
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Definition: stringbuffer.c:106
#define UPD_WEIGHT
Definition: newclient.h:256
#define GET_MAP_OB(M, X, Y)
Definition: map.h:193
struct obj * inv
Definition: object.h:148
#define NDI_UNIQUE
Definition: newclient.h:219
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:63
unsigned int uint32
Definition: global.h:58
#define FLAG_WAS_WIZ
Definition: define.h:530
uint64 query_money(const object *op)
Definition: shop.c:581
struct shopitem * shopitems
Definition: map.h:375
static archetype * find_next_coin(uint64 c, int *cointype)
Definition: shop.c:385
void copy_object(object *op2, object *op)
Definition: object.c:758
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:628
char * shoprace
Definition: map.h:376
static sint64 remove_value(object *coin_objs[], sint64 remain)
Definition: shop.c:700
object * find_skill_by_number(object *who, int skillno)
Definition: standalone.c:209
void free_object(object *ob)
Definition: object.c:1238
uint64 shopmin
Definition: map.h:378
Definition: map.h:346
#define F_NO_BARGAIN
Definition: define.h:778
#define NEUTRAL_RATIO
Definition: shop.c:61
sint16 level
Definition: object.h:202
void fix_object(object *op)
Definition: living.c:900
uint8 real_wiz
Definition: global.h:359
sint32 value
Definition: object.h:201
sint8 magic
Definition: object.h:199
const char * name
Definition: object.h:322
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.c:78
int pay_for_amount(uint64 to_pay, object *pl)
Definition: shop.c:613
uint8 type
Definition: object.h:189
sint32 food
Definition: living.h:89
static void add_value(object *coin_objs[], sint64 value)
Definition: shop.c:741