Crossfire Server, Trunk
shop.cpp
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
21 #include "global.h"
22 
23 #include <assert.h>
24 #include <math.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include "shop.h"
29 #include "sproto.h"
30 
39 #define SPECIALISATION_EFFECT 0.5
40 
42 #define DISAPPROVAL_RATIO 0.2
43 
45 #define NEUTRAL_RATIO 0.8
46 
48 #define MAX_BUY_REDUCTION 0.1f
49 
50 #define MAX_SELL_EXTRA 0.1f
51 
52 static uint64_t pay_from_container(object *pl, object *pouch, uint64_t to_pay);
53 static uint64_t value_limit(uint64_t val, int quantity, const object *who, int isshop);
54 static double shop_specialisation_ratio(const object *item, const mapstruct *map);
55 static double shop_greed(const mapstruct *map);
56 
57 #define NUM_COINS 5
59 #define LARGEST_COIN_GIVEN 2
62 static const char *const coins[] = {
63  "ambercoin",
64  "jadecoin",
65  "platinacoin",
66  "goldcoin",
67  "silvercoin",
68  NULL
69 };
70 
75 uint64_t price_base(const object *obj) {
76  // When there are zero objects, there is really one.
77  const int number = NROF(obj);
78  const bool identified = is_identified(obj);
79  uint64_t val = (uint64_t)obj->value * number;
80 
81  // Objects with price adjustments skip the rest of the calculations.
82  const char *key = object_get_value(obj, "price_adjustment");
83  if (key != NULL) {
84  float ratio = atof(key);
85  return val * ratio;
86  }
87 
88  // Money and gems have fixed prices at shops.
89  if (obj->type == MONEY || obj->type == GEM) {
90  return val;
91  }
92 
93  // If unidentified, price item based on its archetype.
94  if (!identified && obj->arch) {
95  val = obj->arch->clone.value * number;
96  }
97 
103  if (QUERY_FLAG(obj, FLAG_BLESSED)){
104  val *= 1.15;
105  } else if (QUERY_FLAG(obj, FLAG_CURSED)) {
106  val *= 0.8;
107  } else if (QUERY_FLAG(obj, FLAG_DAMNED)) {
108  val *= 0.6;
109  }
110 
111  // If an item is identified to have an enchantment above its archetype
112  // enchantment, increase price exponentially.
113  if (obj->arch != NULL && identified) {
114  int diff = obj->magic - obj->arch->clone.magic;
115  val *= pow(1.15, diff);
116  }
117 
118  // FIXME: Is the 'baseline' 50 charges per wand?
119  if (obj->type == WAND) {
120  val *= obj->stats.food / 50.0;
121  }
122 
123  /* we need to multiply these by 4.0 to keep buy costs roughly the same
124  * (otherwise, you could buy a potion of charisma for around 400 pp.
125  * Arguable, the costs in the archetypes should be updated to better
126  * reflect values (potion charisma list for 1250 gold)
127  */
128  val *= 4; // FIXME
129 
130  return val;
131 }
132 
133 uint64_t price_approx(const object *tmp, object *who) {
134  uint64_t val = price_base(tmp);
135 
136  /* If we are approximating, then the value returned should
137  * be allowed to be wrong however merely using a random number
138  * each time will not be sufficient, as then multiple examinations
139  * would give different answers, so we'll use the count instead.
140  * By taking the sine of the count, a value between -1 and 1 is
141  * generated, we then divide by the square root of the bargaining
142  * skill and the appropriate identification skills, so that higher
143  * level players get better estimates. (We need a +1 there to
144  * prevent dividing by zero.)
145  */
146  const typedata *tmptype = get_typedata(tmp->type);
147  int lev_identify = 0;
148 
149  if (tmptype) {
150  int idskill1 = tmptype->identifyskill;
151  if (idskill1) {
152  int idskill2 = tmptype->identifyskill2;
153  if (find_skill_by_number(who, idskill1)) {
154  lev_identify = find_skill_by_number(who, idskill1)->level;
155  }
156  if (idskill2 && find_skill_by_number(who, idskill2)) {
157  lev_identify += find_skill_by_number(who, idskill2)->level;
158  }
159  }
160  } else {
161  LOG(llevError, "Query_cost: item %s hasn't got a valid type\n", tmp->name);
162  }
163  val += val * (sin(tmp->count) / sqrt(lev_identify * 3 + 1.0));
164 
165  return val;
166 }
167 
173 static float shop_cha_modifier(int charisma) {
174  return tanh((charisma+15.0)/20);
175 }
176 
184 float shop_efficiency(const object *player) {
185  return shop_greed(player->map)
186  * shop_approval(player->map, player)
187  * shop_cha_modifier(player->stats.Cha);
188 }
189 
190 uint64_t shop_price_buy(const object *tmp, object *who) {
191  assert(who != NULL && who->type == PLAYER);
192  const uint64_t val = price_base(tmp);
193  const char *key = object_get_value(tmp, "price_adjustment_buy");
194  float adj = 1;
195  if (key != NULL) {
196  adj = atof(key);
197  }
198  float E = shop_efficiency(who);
199  const float adj_val = val * adj / E;
200  if (getenv("CF_DEBUG_SHOP")) {
201  LOG(llevDebug, "price_buy %s %lu*adj(%.2f)/E(%.2f) = %.2f\n",
202  tmp->arch->name, val, adj, E, adj_val);
203  }
204  if (isfinite(adj_val)) {
205  return adj_val;
206  } else {
207  return UINT64_MAX;
208  }
209 }
210 
211 uint64_t shop_price_sell(const object *tmp, object *who) {
212  assert(who != NULL && who->type == PLAYER);
213  const uint64_t val = price_base(tmp);
214  const char *key = object_get_value(tmp, "price_adjustment_sell");
215  float adj = 1;
216  if (key != NULL) {
217  adj = atof(key);
218  }
219  float spec = shop_specialisation_ratio(tmp, who->map);
220  float E = shop_efficiency(who);
221  const uint64_t adj_val = val * adj * spec * E;
222 
223  /* Limit amount of money you can get for really great items. */
224  int number = NROF(tmp);
225  uint64_t limval = value_limit(adj_val, number, who, 1);
226 
227  if (getenv("CF_DEBUG_SHOP")) {
228  LOG(llevDebug, "price_sell %s %lu*adj(%.2f)*s(%.2f)*E(%.2f) = %lu limited to %lu\n",
229  tmp->arch->name, val, adj, spec, E, adj_val, limval);
230  }
231  return limval;
232 }
233 
245 static archetype *find_next_coin(uint64_t c, int *cointype) {
246  archetype *coin;
247 
248  do {
249  if (coins[*cointype] == NULL)
250  return NULL;
251  coin = find_archetype(coins[*cointype]);
252  if (coin == NULL)
253  return NULL;
254  *cointype += 1;
255  } while (coin->clone.value > (int64_t) c);
256 
257  return coin;
258 }
259 
277 char* cost_string_from_value(uint64_t cost, int largest_coin) {
278  archetype *coin, *next_coin;
279  uint32_t num;
280  int cointype = largest_coin;
281 
282  if (cointype < 0)
283  cointype = 0;
284  else if (cointype >= NUM_COINS)
285  cointype = NUM_COINS - 1;
286 
288  if (cost == UINT64_MAX) {
289  stringbuffer_append_string(buf, "an unimaginable sum of money");
290  goto done;
291  }
292 
293  coin = find_next_coin(cost, &cointype);
294  if (coin == NULL) {
295  stringbuffer_append_string(buf, "nothing");
296  goto done;
297  }
298 
299  num = cost/coin->clone.value;
300  /* so long as nrof is 32 bit, this is true.
301  * If it takes more coins than a person can possibly carry, this
302  * is basically true.
303  */
304  if ((cost/coin->clone.value) > UINT32_MAX) {
305  stringbuffer_append_string(buf, "an unimaginable sum of money");
306  goto done;
307  }
308 
309  cost -= (uint64_t)num*(uint64_t)coin->clone.value;
310  if (num == 1)
311  stringbuffer_append_printf(buf, "1 %s", coin->clone.name);
312  else
313  stringbuffer_append_printf(buf, "%u %ss", num, coin->clone.name);
314 
315  next_coin = find_next_coin(cost, &cointype);
316  if (next_coin == NULL)
317  goto done;
318 
319  do {
320  coin = next_coin;
321  num = cost/coin->clone.value;
322  cost -= (uint64_t)num*(uint64_t)coin->clone.value;
323 
324  if (cost == 0)
325  next_coin = NULL;
326  else
327  next_coin = find_next_coin(cost, &cointype);
328 
329  if (next_coin) {
330  /* There will be at least one more string to add to the list,
331  * use a comma.
332  */
334  } else {
336  }
337  if (num == 1)
338  stringbuffer_append_printf(buf, "1 %s", coin->clone.name);
339  else
340  stringbuffer_append_printf(buf, "%u %ss", num, coin->clone.name);
341  } while (next_coin);
342 
343 done:
344  return stringbuffer_finish(buf);
345 }
346 
357 static StringBuffer *real_money_value(const object *coin, StringBuffer *buf) {
358  assert(coin->type == MONEY);
359  assert(buf);
360 
361  stringbuffer_append_printf(buf, "%ld %s", (long)coin->nrof, coin->nrof == 1 ? coin->name : coin->name_pl);
362  return buf;
363 }
364 
365 char *cost_str(uint64_t cost) {
367 }
368 
369 char *cost_approx_str(const object *tmp, object *who) {
370  uint64_t approx_val = price_approx(tmp, who);
371  int idskill1 = 0;
372  int idskill2 = 0;
373  const typedata *tmptype;
374 
376 
377  /* money it's pretty hard to not give the exact price, so skip all logic and just return the real value. */
378  if (tmp->type == MONEY) {
380  }
381 
382  tmptype = get_typedata(tmp->type);
383  if (tmptype) {
384  idskill1 = tmptype->identifyskill;
385  idskill2 = tmptype->identifyskill2;
386  }
387 
388  /* we show an approximate price if
389  * 1) we are approximating
390  * 2) there either is no id skill(s) for the item, or we don't have them
391  * 3) we don't have bargaining skill either
392  */
393  if (!idskill1 || !find_skill_by_number(who, idskill1)) {
394  if (!idskill2 || !find_skill_by_number(who, idskill2)) {
396  int num;
398  archetype *coin = find_next_coin(approx_val, &cointype);
399 
400  if (coin == NULL) {
401  stringbuffer_append_string(buf, "nothing");
402  return stringbuffer_finish(buf);
403  }
404 
405  num = approx_val/coin->clone.value;
406  if (num == 1)
407  stringbuffer_append_printf(buf, "about one %s", coin->clone.name);
408  else if (num < 5)
409  stringbuffer_append_printf(buf, "a few %s", coin->clone.name_pl);
410  else if (num < 10)
411  stringbuffer_append_printf(buf, "several %s", coin->clone.name_pl);
412  else if (num < 25)
413  stringbuffer_append_printf(buf, "a moderate amount of %s", coin->clone.name_pl);
414  else if (num < 100)
415  stringbuffer_append_printf(buf, "lots of %s", coin->clone.name_pl);
416  else if (num < 1000)
417  stringbuffer_append_printf(buf, "a great many %s", coin->clone.name_pl);
418  else
419  stringbuffer_append_printf(buf, "a vast quantity of %s", coin->clone.name_pl);
420  return stringbuffer_finish(buf);
421  }
422  }
423  }
424 
425  // If we get here, return the price we guessed.
427  return cost_str(approx_val);
428 }
429 
430 uint64_t query_money(const object *op) {
431  uint64_t total = 0;
432 
433  if (op->type != PLAYER && op->type != CONTAINER) {
434  LOG(llevError, "Query money called with non player/container\n");
435  return 0;
436  }
438  if (tmp->type == MONEY) {
439  total += (uint64_t)tmp->nrof*(uint64_t)tmp->value;
440  } else if (tmp->type == CONTAINER
442  && (tmp->race == NULL || strstr(tmp->race, "gold"))) {
443  total += query_money(tmp);
444  }
445  } FOR_INV_FINISH();
446  return total;
447 }
448 
461 int pay_for_amount(uint64_t to_pay, object *pl) {
462  if (to_pay == 0)
463  return 1;
464  if (to_pay > query_money(pl))
465  return 0;
466 
467  to_pay = pay_from_container(pl, pl, to_pay);
468 
469  FOR_INV_PREPARE(pl, pouch) {
470  if (to_pay <= 0)
471  break;
472  if (pouch->type == CONTAINER
473  && QUERY_FLAG(pouch, FLAG_APPLIED)
474  && (pouch->race == NULL || strstr(pouch->race, "gold"))) {
475  to_pay = pay_from_container(pl, pouch, to_pay);
476  }
477  } FOR_INV_FINISH();
478  if (to_pay > 0) {
479  LOG(llevError, "pay_for_amount: Cannot remove enough money -- %" FMT64U " remains\n", to_pay);
480  }
481 
482  fix_object(pl);
483  return 1;
484 }
485 
501 int pay_for_item(object *op, object *pl, uint64_t reduction) {
502  uint64_t to_pay = shop_price_buy(op, pl);
503  assert(to_pay >= reduction);
504  to_pay -= reduction;
505 
506  if (to_pay == 0)
507  return 1;
508  if (to_pay > query_money(pl))
509  return 0;
510 
511  to_pay = pay_from_container(pl, pl, to_pay);
512 
513  FOR_INV_PREPARE(pl, pouch) {
514  if (to_pay <= 0)
515  break;
516  if (pouch->type == CONTAINER
517  && QUERY_FLAG(pouch, FLAG_APPLIED)
518  && (pouch->race == NULL || strstr(pouch->race, "gold"))) {
519  to_pay = pay_from_container(pl, pouch, to_pay);
520  }
521  } FOR_INV_FINISH();
522  if (to_pay > 0) {
523  LOG(llevError, "pay_for_item: Cannot remove enough money -- %" FMT64U " remains\n", to_pay);
524  }
527  fix_object(pl);
528  return 1;
529 }
530 
542 static int64_t remove_value(object *coin_objs[], int64_t remain) {
543  int i;
544 
545  for (i = 0; i < NUM_COINS; i++) {
546  int count;
547  int64_t num_coins;
548 
549  if ((int64_t)coin_objs[i]->nrof * coin_objs[i]->value > remain) {
550  num_coins = remain/coin_objs[i]->value;
551  if ((uint64_t)num_coins*(uint64_t)coin_objs[i]->value < (uint64_t) remain) {
552  num_coins++;
553  }
554  } else {
555  num_coins = coin_objs[i]->nrof;
556  }
557  remain -= (int64_t)num_coins*(int64_t)coin_objs[i]->value;
558  coin_objs[i]->nrof -= num_coins;
559  /* Now start making change. Start at the coin value
560  * below the one we just did, and work down to
561  * the lowest value.
562  */
563  count = i-1;
564  while (remain < 0 && count >= 0) {
565  num_coins = -remain/coin_objs[count]->value;
566  coin_objs[count]->nrof += num_coins;
567  remain += num_coins*coin_objs[count]->value;
568  count--;
569  }
570  }
571 
572  return remain;
573 }
574 
583 static void add_value(object *coin_objs[], int64_t value) {
584  int i;
585 
586  for (i = NUM_COINS-LARGEST_COIN_GIVEN-1; i >= 0; i--) {
587  uint32_t nrof;
588 
589  nrof = (uint32_t)(value/coin_objs[i]->value);
590  value -= nrof*coin_objs[i]->value;
591  coin_objs[i]->nrof += nrof;
592  }
593 }
594 
607 static void insert_objects(object *pl, object *container, object *objects[], int objects_len) {
608  int i, one = 0;
609 
610  for (i = 0; i < objects_len; i++) {
611  if (objects[i]->nrof > 0) {
612  object_insert_in_ob(objects[i], container);
613  one = 1;
614  } else {
616  }
617  }
618  if (one)
619  esrv_update_item(UPD_WEIGHT, pl, container);
620 }
621 
635 static uint64_t pay_from_container(object *pl, object *pouch, uint64_t to_pay) {
636  size_t i;
637  int64_t remain;
638  object *coin_objs[NUM_COINS];
639  object *other_money[16]; /* collects MONEY objects not matching coins[] */
640  size_t other_money_len; /* number of allocated entries in other_money[] */
641  archetype *at;
642 
643  if (pouch->type != PLAYER && pouch->type != CONTAINER)
644  return to_pay;
645 
646  remain = to_pay;
647  for (i = 0; i < NUM_COINS; i++)
648  coin_objs[i] = NULL;
649 
650  /* This hunk should remove all the money objects from the player/container */
651  other_money_len = 0;
652  FOR_INV_PREPARE(pouch, tmp) {
653  if (tmp->type == MONEY) {
654  for (i = 0; i < NUM_COINS; i++) {
655  if (!strcmp(coins[NUM_COINS-1-i], tmp->arch->name)
656  && (tmp->value == tmp->arch->clone.value)) {
657  /* This should not happen, but if it does, just
658  * merge the two.
659  */
660  if (coin_objs[i] != NULL) {
661  LOG(llevError, "%s has two money entries of (%s)\n", pouch->name, coins[NUM_COINS-1-i]);
663  coin_objs[i]->nrof += tmp->nrof;
665  } else {
667  coin_objs[i] = tmp;
668  }
669  break;
670  }
671  }
672  if (i == NUM_COINS) {
673  if (other_money_len >= sizeof(other_money)/sizeof(*other_money)) {
674  LOG(llevError, "pay_for_item: Cannot store non-standard money object %s\n", tmp->arch->name);
675  } else {
677  other_money[other_money_len++] = tmp;
678  }
679  }
680  }
681  } FOR_INV_FINISH();
682 
683  /* Fill in any gaps in the coin_objs array - needed to make change. */
684  /* Note that the coin_objs array goes from least value to greatest value */
685  for (i = 0; i < NUM_COINS; i++)
686  if (coin_objs[i] == NULL) {
687  at = find_archetype(coins[NUM_COINS-1-i]);
688  if (at == NULL) {
689  continue;
690  }
691  coin_objs[i] = object_new();
692  object_copy(&at->clone, coin_objs[i]);
693  coin_objs[i]->nrof = 0;
694  }
695 
696  /* Try to pay from standard coins first. */
697  remain = remove_value(coin_objs, remain);
698 
699  /* Now pay from non-standard coins until all is paid. */
700  for (i = 0; i < other_money_len && remain > 0; i++) {
701  uint32_t nrof;
702  object *coin;
703 
704  coin = other_money[i];
705 
706  /* Find the minimal number of coins to use. This prevents converting
707  * excess non-standard coins to standard money.
708  */
709  nrof = (remain+coin->value-1)/coin->value;
710  if (nrof > coin->nrof) {
711  nrof = coin->nrof;
712  }
713  coin->nrof -= nrof;
714  add_value(coin_objs, nrof*coin->value);
715 
716  remain = remove_value(coin_objs, remain);
717  }
718 
719  /* re-insert remaining coins into player */
720  insert_objects(pl, pouch, coin_objs, NUM_COINS);
721  insert_objects(pl, pouch, other_money, other_money_len);
722 
723  return(remain);
724 }
725 
726 uint64_t add_with_overflow(uint64_t a, uint64_t b) {
727  if (a == UINT64_MAX) {
728  return a;
729  }
730 
731  if (UINT64_MAX - a < b) {
732  // Overflow
733  return UINT64_MAX;
734  } else {
735  return a + b;
736  }
737 }
738 
739 struct unpaid_count {
740  object *pl;
741  int count;
742  uint64_t price;
743 };
744 
752 static void unpaid_iter(object *item, void (*callback)(object *item, void *data), void *data) {
754  if (QUERY_FLAG(item, FLAG_UNPAID)) {
755  callback(item, data);
756  }
757  if (item->inv) {
758  unpaid_iter(item->inv, callback, data);
759  }
761 }
762 
763 static void count_unpaid_callback(object *item, void *data) {
764  struct unpaid_count *args = (struct unpaid_count *)data;
765  args->count++;
766  args->price = add_with_overflow(args->price, shop_price_buy(item, args->pl));
767 }
768 
781 static void count_unpaid(object *pl, object *item, int *unpaid_count, uint64_t *unpaid_price) {
782  struct unpaid_count args = {pl, 0, 0};
784  *unpaid_count = args.count;
785  *unpaid_price = args.price;
786 }
787 
795 static void count_coins(object *item, uint32_t *coincount) {
797  /* Merely converting the player's monetary wealth won't do.
798  * If we did that, we could print the wrong numbers for the
799  * coins, so we count the money instead.
800  */
801  for (int i = 0; i < NUM_COINS; i++) {
802  if (!strcmp(coins[i], item->arch->name)) {
803  coincount[i] += item->nrof;
804  break;
805  }
806  }
807  if (item->inv) {
808  count_coins(item->inv, coincount);
809  }
811 }
812 
821 static uint64_t compute_price_variation_with_bargaining(object *pl, uint64_t price, float max_variation) {
822  object *skill = find_skill_by_number(pl, SK_BARGAINING);
823  if (skill && skill->level > 0) {
824  return rndm(0, price * (max_variation * skill->level / settings.max_level));
825  }
826  return 0;
827 }
828 
841 int can_pay(object *pl) {
842  int unpaid_count = 0, i;
843  uint64_t unpaid_price = 0;
844  uint32_t coincount[NUM_COINS];
845 
846  if (!pl || pl->type != PLAYER) {
847  LOG(llevError, "can_pay(): called against something that isn't a player\n");
848  return 0;
849  }
850  uint64_t player_wealth = query_money(pl);
851 
852  for (i = 0; i < NUM_COINS; i++)
853  coincount[i] = 0;
854 
855  count_unpaid(pl, pl->inv, &unpaid_count, &unpaid_price);
856  count_coins(pl->inv, coincount);
857 
858  if (unpaid_price > player_wealth) {
859  char buf[MAX_BUF], coinbuf[MAX_BUF];
860  int denominations = 0;
861  char *value = cost_str(unpaid_price);
862 
863  snprintf(buf, sizeof(buf), "You have %d unpaid items that would cost you %s, ", unpaid_count, value);
864  free(value);
865  for (i = 0; i < NUM_COINS; i++) {
866  if (coincount[i] > 0 && coins[i]) {
867  if (denominations == 0)
868  snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "but you only have");
869  denominations++;
871  if (arch != NULL)
872  {
873  snprintf(coinbuf, sizeof(coinbuf), " %u %s,", coincount[i], arch->clone.name_pl);
874  snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%s", coinbuf);
875  }
876  }
877  }
878  if (denominations == 0)
879  snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "but you don't have any money.");
880  else if (denominations > 1)
884  return 0;
885  } else
886  return 1;
887 }
888 
889 static void shop_pay_unpaid_callback(object *op, void *data) {
890  object *pl = (object *)data;
891  char name_op[MAX_BUF];
892  uint64_t price = shop_price_buy(op, pl);
894  if (!pay_for_item(op, pl, reduction)) {
895  uint64_t i = price - query_money(pl);
896  char *missing = cost_str(i);
897 
899  query_name(op, name_op, MAX_BUF);
902  "You lack %s to buy %s.",
903  missing, name_op);
904  free(missing);
906  return;
907  } else {
908  // TODO: Figure out how to pass in the shop owner for player shops.
910  return;
911  object *tmp;
912  char *value = cost_str(price - reduction);
913 
916  query_name(op, name_op, MAX_BUF);
917 
918  if (reduction > 0) {
919  char *reduction_str = cost_str(reduction);
922  "You paid %s for %s after bargaining a reduction of %s.",
923  value, name_op, reduction_str);
924  change_exp(pl, reduction, "bargaining", SK_EXP_NONE);
925  free(reduction_str);
926  } else {
929  "You paid %s for %s.",
930  value, name_op);
931  }
932  free(value);
933  tmp = object_merge(op, NULL);
934  if (pl->type == PLAYER && !tmp) {
935  /* If item wasn't merged we update it. If merged, object_merge() handled everything for us. */
937  }
938  }
939 }
940 
947 int shop_pay_unpaid(object *pl, object *op) {
948  if (!op) {
949  return 1;
950  }
952  return 1;
953 }
954 
966 void sell_item(object *op, object *pl) {
967  object *tmp;
968  archetype *at;
969  char obj_name[MAX_BUF];
970 
971  query_name(op, obj_name, MAX_BUF);
972 
973  if (pl == NULL || pl->type != PLAYER) {
974  LOG(llevDebug, "Object other than player tried to sell something.\n");
975  return;
976  }
977 
979  return;
980 
982 
983  uint64_t price = shop_price_sell(op, pl);
984  if (price == 0) {
987  "We're not interested in %s.",
988  obj_name);
989  return;
990  }
991 
993  char *value_str = cost_str(price + extra_gain);
994 
995  if (extra_gain > 0) {
996  change_exp(pl, extra_gain, "bargaining", SK_EXP_NONE);
997  char *extra_str = cost_str(extra_gain);
999  "You receive %s for %s, after bargaining for %s more than proposed.", value_str, obj_name, extra_str);
1000  free(extra_str);
1001  price += extra_gain;
1002  } else {
1004  "You receive %s for %s.", value_str, obj_name);
1005  }
1006  free(value_str);
1007 
1008  for (int count = LARGEST_COIN_GIVEN; coins[count] != NULL; count++) {
1009  at = find_archetype(coins[count]);
1010  if (at == NULL)
1011  LOG(llevError, "Could not find %s archetype\n", coins[count]);
1012  else if ((price/at->clone.value) > 0) {
1013  FOR_INV_PREPARE(pl, pouch) {
1014  if (pouch->type == CONTAINER
1015  && QUERY_FLAG(pouch, FLAG_APPLIED)
1016  && pouch->race
1017  && strstr(pouch->race, "gold")) {
1018  int w = at->clone.weight*(100-pouch->stats.Str)/100;
1019  int n = price/at->clone.value;
1020 
1021  if (w == 0)
1022  w = 1; /* Prevent divide by zero */
1023  if (n > 0
1024  && (!pouch->weight_limit || pouch->carrying+w <= pouch->weight_limit)) {
1025  if (pouch->weight_limit
1026  && (pouch->weight_limit-pouch->carrying)/w < n)
1027  n = (pouch->weight_limit-pouch->carrying)/w;
1028 
1029  tmp = object_new();
1030  object_copy(&at->clone, tmp);
1031  tmp->nrof = n;
1032  price -= (uint64_t)tmp->nrof*(uint64_t)tmp->value;
1033  tmp = object_insert_in_ob(tmp, pouch);
1035  }
1036  }
1037  } FOR_INV_FINISH();
1038  if (price/at->clone.value > 0) {
1039  tmp = object_new();
1040  object_copy(&at->clone, tmp);
1041  tmp->nrof = price/tmp->value;
1042  price -= (uint64_t)tmp->nrof*(uint64_t)tmp->value;
1045  }
1046  }
1047  }
1048 
1049  if (price != 0) {
1050  LOG(llevError, "Warning - payment not zero: %" PRIo64 "\n", price);
1051  }
1052 
1054  identify(op);
1055 }
1056 
1072 static double shop_specialisation_ratio(const object *item, const mapstruct *map) {
1073  shopitems *items = map->shopitems;
1074  double ratio = SPECIALISATION_EFFECT, likedness = 0.001;
1075  int i;
1076 
1077  if (item == NULL) {
1078  LOG(llevError, "shop_specialisation_ratio: passed a NULL item for map %s\n", map->path);
1079  return 0;
1080  }
1081  if (item->type == (uint8_t)-1) {
1082  LOG(llevError, "shop_specialisation_ratio: passed an item with an invalid type\n");
1083  /*
1084  * I'm not really sure what the /right/ thing to do here is,
1085  * these types of item shouldn't exist anyway, but returning
1086  * the ratio is probably the best bet.."
1087  */
1088  return ratio;
1089  }
1090  if (map->shopitems) {
1091  for (i = 0; i < items[0].index; i++)
1092  if (items[i].typenum == item->type || (items[i].typenum == -1 && likedness == 0.001))
1093  likedness = items[i].strength/100.0;
1094  }
1095  if (likedness > 1.0) { /* someone has been rather silly with the map headers. */
1096  LOG(llevDebug, "shop_specialisation ratio: item type %d on map %s is above 100%%\n", item->type, map->path);
1097  likedness = 1.0;
1098  }
1099  if (likedness < -1.0) {
1100  LOG(llevDebug, "shop_specialisation ratio: item type %d on map %s is below -100%%\n", item->type, map->path);
1101  likedness = -1.0;
1102  }
1103  ratio = ratio+(1.0-ratio)*likedness;
1104  if (ratio <= 0.1)
1105  ratio = 0.1; /* if the ratio were much lower than this, we would get silly prices */
1106  return ratio;
1107 }
1108 
1123 static double shop_greed(const mapstruct *map) {
1124  float greed = map->shopgreed;
1125  if (greed == 0) {
1126  greed = 1;
1127  }
1128  return tanh(-greed+2.0)/2 + 0.5;
1129 }
1130 
1131 double shop_approval(const mapstruct *map, const object *player) {
1132  double approval = 1.0;
1133  if (map->shoprace) {
1134  approval = NEUTRAL_RATIO;
1135  if (player->race && !strcmp(player->race, map->shoprace))
1136  approval = 1.0;
1137  }
1138  return approval;
1139 }
1140 
1160 static uint64_t value_limit(uint64_t val, int quantity, const object *who, int isshop) {
1161  uint64_t newval, unit_price;
1162  mapstruct *map;
1163 
1164  unit_price = val/quantity;
1165  if (!isshop || !who) {
1166  if (unit_price > 10000)
1167  newval = 8000+isqrt(unit_price)*20;
1168  else
1169  newval = unit_price;
1170  } else {
1171  if (!who->map) {
1172  LOG(llevError, "value_limit: asked shop price for ob %s on NULL map\n", who->name);
1173  return val;
1174  }
1175  map = who->map;
1176  if (map->shopmin && unit_price < map->shopmin)
1177  return 0;
1178  else if (map->shopmax && unit_price > map->shopmax/2)
1179  newval = MIN((map->shopmax/2)+isqrt(unit_price-map->shopmax/2), map->shopmax);
1180  else if (unit_price > 10000)
1181  newval = 8000+isqrt(unit_price)*20;
1182  else
1183  newval = unit_price;
1184  }
1185  newval *= quantity;
1186  return newval;
1187 }
1188 
1194 int shop_describe(const object *op) {
1195  mapstruct *map = op->map;
1196  /*shopitems *items=map->shopitems;*/
1197  int pos = 0, i;
1198  double opinion = 0;
1199  char tmp[MAX_BUF] = "\0", *value;
1200 
1201  if (op->type != PLAYER)
1202  return 0;
1203 
1204  /*check if there is a shop specified for this map */
1205  if (map->shopitems
1206  || map->shopgreed
1207  || map->shoprace
1208  || map->shopmin
1209  || map->shopmax) {
1211  "From looking at the nearby shop you determine that it trades in:");
1212 
1213  if (map->shopitems) {
1214  for (i = 0; i < map->shopitems[0].index; i++) {
1215  if (map->shopitems[i].name && map->shopitems[i].strength > 10) {
1216  snprintf(tmp+pos, sizeof(tmp)-pos, "%s, ", map->shopitems[i].name_pl);
1217  pos += strlen(tmp+pos);
1218  }
1219  }
1220  }
1221  if (!pos)
1222  strcpy(tmp, "a little of everything.");
1223 
1224  /* format the string into a list */
1228 
1229  if (map->shopmax) {
1230  value = cost_str(map->shopmax);
1233  "It won't trade for items above %s.",
1234  value);
1235  free(value);
1236  }
1237 
1238  if (map->shopmin) {
1239  value = cost_str(map->shopmin);
1242  "It won't trade in items worth less than %s.",
1243  value);
1244  free(value);
1245  }
1246 
1247  if (map->shopgreed) {
1248  if (map->shopgreed > 2.0)
1251  "It tends to overcharge massively.");
1252  else if (map->shopgreed > 1.5)
1255  "It tends to overcharge substantially.");
1256  else if (map->shopgreed > 1.1)
1259  "It tends to overcharge slightly.");
1260  else if (map->shopgreed < 0.9)
1263  "It tends to undercharge.");
1264  }
1265  if (map->shoprace) {
1266  opinion = shop_approval(map, op);
1267  if (opinion > 0.8)
1270  "You think the shopkeeper likes you.");
1271  else if (opinion > 0.5)
1274  "The shopkeeper seems unconcerned by you.");
1275  else
1278  "The shopkeeper seems to have taken a dislike to you.");
1279  }
1281  "There is no shop nearby.");
1282 
1283  return 1;
1284 }
1285 
1289 static bool coords_in_shop(mapstruct *map, int x, int y) {
1290  FOR_MAP_PREPARE(map, x, y, floor)
1291  if (floor->type == SHOP_FLOOR) return true;
1292  FOR_MAP_FINISH();
1293  return false;
1294 }
1295 
1296 bool shop_contains(object *ob) {
1297  if (!ob->map) return 0;
1298  return coords_in_shop(ob->map, ob->x, ob->y);
1299 }
cost_approx_str
char * cost_approx_str(const object *tmp, object *who)
Definition: shop.cpp:369
shop_approval
double shop_approval(const mapstruct *map, const object *player)
Definition: shop.cpp:1131
PLAYER
@ PLAYER
Definition: object.h:110
global.h
sell_item
void sell_item(object *op, object *pl)
Definition: shop.cpp:966
settings
struct Settings settings
Definition: init.cpp:139
diamondslots.cointype
string cointype
Definition: diamondslots.py:18
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Definition: define.h:730
shop_cha_modifier
static float shop_cha_modifier(int charisma)
Definition: shop.cpp:173
Settings::max_level
int16_t max_level
Definition: global.h:302
unpaid_count::price
uint64_t price
Definition: shop.cpp:742
llevError
@ llevError
Definition: logger.h:11
find_skill_by_number
object * find_skill_by_number(object *who, int skillno)
Definition: main.cpp:375
WAND
@ WAND
Definition: object.h:223
unpaid_count::count
int count
Definition: shop.cpp:741
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:51
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
LARGEST_COIN_GIVEN
#define LARGEST_COIN_GIVEN
Definition: shop.cpp:59
diamondslots.x
x
Definition: diamondslots.py:15
MAX_SELL_EXTRA
#define MAX_SELL_EXTRA
Definition: shop.cpp:50
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
archininventory.arch
arch
DIALOGCHECK MINARGS 1 MAXARGS 1
Definition: archininventory.py:16
compute_price_variation_with_bargaining
static uint64_t compute_price_variation_with_bargaining(object *pl, uint64_t price, float max_variation)
Definition: shop.cpp:821
obj::value
int32_t value
Definition: object.h:358
unpaid_iter
static void unpaid_iter(object *item, void(*callback)(object *item, void *data), void *data)
Definition: shop.cpp:752
object_merge
object * object_merge(object *op, object *top)
Definition: object.cpp:2049
cost_str
char * cost_str(uint64_t cost)
Definition: shop.cpp:365
stringbuffer_append_printf
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Definition: stringbuffer.cpp:138
find_next_coin
static archetype * find_next_coin(uint64_t c, int *cointype)
Definition: shop.cpp:245
FALSE
#define FALSE
Definition: compat.h:14
add_value
static void add_value(object *coin_objs[], int64_t value)
Definition: shop.cpp:583
c
static event_registration c
Definition: citylife.cpp:425
disinfect.a
a
Definition: disinfect.py:13
SPECIALISATION_EFFECT
#define SPECIALISATION_EFFECT
Definition: shop.cpp:39
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.cpp:57
coords_in_shop
static bool coords_in_shop(mapstruct *map, int x, int y)
Definition: shop.cpp:1289
UPD_WEIGHT
#define UPD_WEIGHT
Definition: newclient.h:316
SHOP_FLOOR
@ SHOP_FLOOR
Definition: object.h:186
GEM
@ GEM
Definition: object.h:170
pl
Definition: player.h:105
price_approx
uint64_t price_approx(const object *tmp, object *who)
Definition: shop.cpp:133
insert_objects
static void insert_objects(object *pl, object *container, object *objects[], int objects_len)
Definition: shop.cpp:607
typedata::identifyskill
int identifyskill
Definition: define.h:93
guildjoin.ob
ob
Definition: guildjoin.py:42
mail_login.total
total
Definition: mail_login.py:30
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
MIN
#define MIN(x, y)
Definition: compat.h:21
object_copy
void object_copy(const object *src_ob, object *dest_ob)
Definition: object.cpp:1192
fix_object
void fix_object(object *op)
Definition: living.cpp:1125
shopitem::typenum
int typenum
Definition: map.h:300
Ice.tmp
int tmp
Definition: Ice.py:207
FLAG_BLESSED
#define FLAG_BLESSED
Definition: define.h:369
shop_pay_unpaid_callback
static void shop_pay_unpaid_callback(object *op, void *data)
Definition: shop.cpp:889
MSG_TYPE_SHOP_PAYMENT
#define MSG_TYPE_SHOP_PAYMENT
Definition: newclient.h:510
coins
static const char *const coins[]
Definition: shop.cpp:62
rndm
int rndm(int min, int max)
Definition: utils.cpp:162
SK_EXP_NONE
#define SK_EXP_NONE
Definition: skills.h:80
NEUTRAL_RATIO
#define NEUTRAL_RATIO
Definition: shop.cpp:45
object_get_value
const char * object_get_value(const object *op, const char *const key)
Definition: object.cpp:4339
MSG_TYPE_SHOP_MISC
#define MSG_TYPE_SHOP_MISC
Definition: newclient.h:513
FLAG_APPLIED
#define FLAG_APPLIED
Definition: define.h:235
events_execute_object_event
int events_execute_object_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
Definition: events.cpp:292
buf
StringBuffer * buf
Definition: readable.cpp:1611
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.cpp:2851
pay_for_item
int pay_for_item(object *op, object *pl, uint64_t reduction)
Definition: shop.cpp:501
obj::nrof
uint32_t nrof
Definition: object.h:340
NUM_COINS
#define NUM_COINS
Definition: shop.cpp:57
real_money_value
static StringBuffer * real_money_value(const object *coin, StringBuffer *buf)
Definition: shop.cpp:357
archt
Definition: object.h:472
obj
Definition: object.h:280
typedata
Definition: define.h:89
autojail.who
who
Definition: autojail.py:3
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.cpp:76
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Definition: object.cpp:1560
NROF
static uint32_t NROF(const object *const ob)
Definition: object.h:614
disinfect.map
map
Definition: disinfect.py:4
FLAG_WAS_WIZ
#define FLAG_WAS_WIZ
Definition: define.h:234
obj::name
sstring name
Definition: object.h:317
make_face_from_files.args
args
Definition: make_face_from_files.py:31
get_typedata
const typedata * get_typedata(int itemtype)
Definition: item.cpp:320
shop_price_sell
uint64_t shop_price_sell(const object *tmp, object *who)
Definition: shop.cpp:211
query_name
void query_name(const object *op, char *buf, size_t size)
Definition: item.cpp:585
EVENT_SELLING
#define EVENT_SELLING
Definition: events.h:30
shop_pay_unpaid
int shop_pay_unpaid(object *pl, object *op)
Definition: shop.cpp:947
query_money
uint64_t query_money(const object *op)
Definition: shop.cpp:430
shop_specialisation_ratio
static double shop_specialisation_ratio(const object *item, const mapstruct *map)
Definition: shop.cpp:1072
say.price
dictionary price
Definition: say.py:147
obj::name_pl
sstring name_pl
Definition: object.h:321
FOR_OB_AND_BELOW_FINISH
#define FOR_OB_AND_BELOW_FINISH()
Definition: define.h:754
unpaid_count
Definition: shop.cpp:739
CONTAINER
@ CONTAINER
Definition: object.h:234
done
int done
Definition: readable.cpp:1612
SCRIPT_FIX_ALL
#define SCRIPT_FIX_ALL
Definition: global.h:382
is_identified
int is_identified(const object *op)
Definition: item.cpp:1336
isqrt
int isqrt(int n)
Definition: utils.cpp:569
cost_string_from_value
char * cost_string_from_value(uint64_t cost, int largest_coin)
Definition: shop.cpp:277
Ice.b
b
Definition: Ice.py:48
FLAG_DAMNED
#define FLAG_DAMNED
Definition: define.h:317
MAX_BUY_REDUCTION
#define MAX_BUY_REDUCTION
Definition: shop.cpp:48
navar-midane_time.data
data
Definition: navar-midane_time.py:11
UPD_FLAGS
#define UPD_FLAGS
Definition: newclient.h:315
FOR_INV_FINISH
#define FOR_INV_FINISH()
Definition: define.h:677
change_exp
void change_exp(object *op, int64_t exp, const char *skill_name, int flag)
Definition: living.cpp:2166
disinfect.count
int count
Definition: disinfect.py:7
SK_BARGAINING
@ SK_BARGAINING
Definition: skills.h:28
add_with_overflow
uint64_t add_with_overflow(uint64_t a, uint64_t b)
Definition: shop.cpp:726
sproto.h
liv::food
int32_t food
Definition: living.h:48
commongive.quantity
quantity
Definition: commongive.py:7
stringbuffer_append_string
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Definition: stringbuffer.cpp:95
FOR_OB_AND_BELOW_PREPARE
#define FOR_OB_AND_BELOW_PREPARE(op_)
Definition: define.h:750
mapdef
Definition: map.h:317
MSG_TYPE_SHOP
#define MSG_TYPE_SHOP
Definition: newclient.h:403
MAX_BUF
#define MAX_BUF
Definition: define.h:35
shop_describe
int shop_describe(const object *op)
Definition: shop.cpp:1194
object_new
object * object_new(void)
Definition: object.cpp:1273
EVENT_BOUGHT
#define EVENT_BOUGHT
Definition: events.h:23
StringBuffer
Definition: stringbuffer.cpp:25
value_limit
static uint64_t value_limit(uint64_t val, int quantity, const object *who, int isshop)
Definition: shop.cpp:1160
count_coins
static void count_coins(object *item, uint32_t *coincount)
Definition: shop.cpp:795
FOR_MAP_PREPARE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Definition: define.h:723
shop_price_buy
uint64_t shop_price_buy(const object *tmp, object *who)
Definition: shop.cpp:190
obj::arch
struct archt * arch
Definition: object.h:420
obj::type
uint8_t type
Definition: object.h:346
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:262
obj::stats
living stats
Definition: object.h:376
archt::clone
object clone
Definition: object.h:476
MSG_TYPE_SHOP_SELL
#define MSG_TYPE_SHOP_SELL
Definition: newclient.h:512
shop_contains
bool shop_contains(object *ob)
Definition: shop.cpp:1296
obj::weight
int32_t weight
Definition: object.h:373
stringbuffer_delete
void stringbuffer_delete(StringBuffer *sb)
Definition: stringbuffer.cpp:71
remove_value
static int64_t remove_value(object *coin_objs[], int64_t remain)
Definition: shop.cpp:542
item
Definition: item.py:1
price_base
uint64_t price_base(const object *obj)
Definition: shop.cpp:75
give.op
op
Definition: give.py:33
autojail.value
value
Definition: autojail.py:6
find_archetype
archetype * find_archetype(const char *name)
Definition: assets.cpp:270
shop.h
esrv_update_item
void esrv_update_item(int flags, object *pl, object *op)
Definition: main.cpp:359
unpaid_count::pl
object * pl
Definition: shop.cpp:740
objects
object * objects
Definition: object.cpp:294
shopitem::index
int index
Definition: map.h:303
make_list_like
void make_list_like(char *input)
Definition: utils.cpp:378
diamondslots.y
y
Definition: diamondslots.py:16
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
shop_efficiency
float shop_efficiency(const object *player)
Definition: shop.cpp:184
MSG_TYPE_SHOP_LISTING
#define MSG_TYPE_SHOP_LISTING
Definition: newclient.h:508
shop_greed
static double shop_greed(const mapstruct *map)
Definition: shop.cpp:1123
typedata::identifyskill2
int identifyskill2
Definition: define.h:94
castle_read.key
key
Definition: castle_read.py:64
FMT64U
#define FMT64U
Definition: compat.h:17
UPD_NAME
#define UPD_NAME
Definition: newclient.h:318
count_unpaid_callback
static void count_unpaid_callback(object *item, void *data)
Definition: shop.cpp:763
Settings::real_wiz
uint8_t real_wiz
Definition: global.h:271
draw_ext_info
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Definition: main.cpp:308
object_remove
void object_remove(object *op)
Definition: object.cpp:1833
FLAG_PLAYER_SOLD
#define FLAG_PLAYER_SOLD
Definition: define.h:252
FLAG_UNPAID
#define FLAG_UNPAID
Definition: define.h:236
UINT32_MAX
#define UINT32_MAX
Definition: loader.c:83
object_set_value
int object_set_value(object *op, const char *key, const char *value, int add_key)
Definition: object.cpp:4492
diamondslots.cost
int cost
Definition: diamondslots.py:21
can_pay
int can_pay(object *pl)
Definition: shop.cpp:841
FLAG_CURSED
#define FLAG_CURSED
Definition: define.h:316
altar_valkyrie.pl
pl
Definition: altar_valkyrie.py:28
shopitem::strength
int8_t strength
Definition: map.h:301
obj::magic
int8_t magic
Definition: object.h:356
if
if(!(yy_init))
Definition: loader.c:2626
pay_for_amount
int pay_for_amount(uint64_t to_pay, object *pl)
Definition: shop.cpp:461
CUSTOM_NAME_FIELD
#define CUSTOM_NAME_FIELD
Definition: object.h:96
count_unpaid
static void count_unpaid(object *pl, object *item, int *unpaid_count, uint64_t *unpaid_price)
Definition: shop.cpp:781
shopitem
Definition: map.h:297
FOR_INV_PREPARE
#define FOR_INV_PREPARE(op_, it_)
Definition: define.h:670
obj::level
int16_t level
Definition: object.h:359
llevDebug
@ llevDebug
Definition: logger.h:13
MONEY
@ MONEY
Definition: object.h:140
pay_from_container
static uint64_t pay_from_container(object *pl, object *pouch, uint64_t to_pay)
Definition: shop.cpp:635
identify
object * identify(object *op)
Definition: item.cpp:1409