Crossfire Server  1.75.0
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 <cmath>
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 
71 uint64_t price_approx(const object *tmp, object *who) {
72  uint64_t val = price_base(tmp);
73 
74  /* If we are approximating, then the value returned should
75  * be allowed to be wrong however merely using a random number
76  * each time will not be sufficient, as then multiple examinations
77  * would give different answers, so we'll use the count instead.
78  * By taking the sine of the count, a value between -1 and 1 is
79  * generated, we then divide by the square root of the bargaining
80  * skill and the appropriate identification skills, so that higher
81  * level players get better estimates. (We need a +1 there to
82  * prevent dividing by zero.)
83  */
84  const typedata *tmptype = get_typedata(tmp->type);
85  int lev_identify = 0;
86 
87  if (tmptype) {
88  int idskill1 = tmptype->identifyskill;
89  if (idskill1) {
90  int idskill2 = tmptype->identifyskill2;
91  if (find_skill_by_number(who, idskill1)) {
92  lev_identify = find_skill_by_number(who, idskill1)->level;
93  }
94  if (idskill2 && find_skill_by_number(who, idskill2)) {
95  lev_identify += find_skill_by_number(who, idskill2)->level;
96  }
97  }
98  } else {
99  LOG(llevError, "Query_cost: item %s hasn't got a valid type\n", tmp->name);
100  }
101  val += val * (sin(tmp->count) / sqrt(lev_identify * 3 + 1.0));
102 
103  return val;
104 }
105 
111 static float shop_cha_modifier(int charisma) {
112  return tanh((charisma+15.0)/20);
113 }
114 
122 float shop_efficiency(const object *player) {
123  return shop_greed(player->map)
124  * shop_approval(player->map, player)
125  * shop_cha_modifier(player->stats.Cha);
126 }
127 
128 uint64_t shop_price_buy(const object *tmp, object *who) {
129  assert(who != NULL && who->type == PLAYER);
130  // price tags override any buy price
131  if (object_value_set(tmp, "price")) {
132  const char *price = object_get_value(tmp, "price");
133  return NROF(tmp)*strtol(price, NULL, 10);
134  }
135  const uint64_t val = price_base(tmp);
136  const char *key = object_get_value(tmp, "price_adjustment_buy");
137  float adj = 1;
138  if (key != NULL) {
139  adj = atof(key);
140  }
141  float E = shop_efficiency(who);
142  const float adj_val = val * adj / E;
143  if (getenv("CF_DEBUG_SHOP")) {
144  LOG(llevDebug, "price_buy %s %lu*adj(%.2f)/E(%.2f) = %.2f\n",
145  tmp->arch->name, val, adj, E, adj_val);
146  }
147  if (std::isfinite(adj_val)) {
148  return adj_val;
149  } else {
150  return UINT64_MAX;
151  }
152 }
153 
154 uint64_t shop_price_sell(const object *tmp, object *who) {
155  assert(who != NULL && who->type == PLAYER);
156  const uint64_t val = price_base(tmp);
157  const char *key = object_get_value(tmp, "price_adjustment_sell");
158  float adj = 1;
159  if (key != NULL) {
160  adj = atof(key);
161  }
162  float spec = shop_specialisation_ratio(tmp, who->map);
163  float E = shop_efficiency(who);
164  const uint64_t adj_val = val * adj * spec * E;
165 
166  /* Limit amount of money you can get for really great items. */
167  int number = NROF(tmp);
168  uint64_t limval = value_limit(adj_val, number, who, 1);
169 
170  if (getenv("CF_DEBUG_SHOP")) {
171  LOG(llevDebug, "price_sell %s %lu*adj(%.2f)*s(%.2f)*E(%.2f) = %lu limited to %lu\n",
172  tmp->arch->name, val, adj, spec, E, adj_val, limval);
173  }
174  return limval;
175 }
176 
188 static archetype *find_next_coin(uint64_t c, int *cointype) {
189  archetype *coin;
190 
191  do {
192  if (coins[*cointype] == NULL)
193  return NULL;
194  coin = find_archetype(coins[*cointype]);
195  if (coin == NULL)
196  return NULL;
197  *cointype += 1;
198  } while (coin->clone.value > (int64_t) c);
199 
200  return coin;
201 }
202 
220 char* cost_string_from_value(uint64_t cost, int largest_coin) {
221  archetype *coin, *next_coin;
222  uint32_t num;
223  int cointype = largest_coin;
224 
225  if (cointype < 0)
226  cointype = 0;
227  else if (cointype >= NUM_COINS)
228  cointype = NUM_COINS - 1;
229 
231  if (cost == UINT64_MAX) {
232  stringbuffer_append_string(buf, "an unimaginable sum of money");
233  goto done;
234  }
235 
236  coin = find_next_coin(cost, &cointype);
237  if (coin == NULL) {
238  stringbuffer_append_string(buf, "nothing");
239  goto done;
240  }
241 
242  num = cost/coin->clone.value;
243  /* so long as nrof is 32 bit, this is true.
244  * If it takes more coins than a person can possibly carry, this
245  * is basically true.
246  */
247  if ((cost/coin->clone.value) > UINT32_MAX) {
248  stringbuffer_append_string(buf, "an unimaginable sum of money");
249  goto done;
250  }
251 
252  cost -= (uint64_t)num*(uint64_t)coin->clone.value;
253  if (num == 1)
254  stringbuffer_append_printf(buf, "1 %s", coin->clone.name);
255  else
256  stringbuffer_append_printf(buf, "%u %ss", num, coin->clone.name);
257 
258  next_coin = find_next_coin(cost, &cointype);
259  if (next_coin == NULL)
260  goto done;
261 
262  do {
263  coin = next_coin;
264  num = cost/coin->clone.value;
265  cost -= (uint64_t)num*(uint64_t)coin->clone.value;
266 
267  if (cost == 0)
268  next_coin = NULL;
269  else
270  next_coin = find_next_coin(cost, &cointype);
271 
272  if (next_coin) {
273  /* There will be at least one more string to add to the list,
274  * use a comma.
275  */
276  stringbuffer_append_string(buf, ", ");
277  } else {
278  stringbuffer_append_string(buf, " and ");
279  }
280  if (num == 1)
281  stringbuffer_append_printf(buf, "1 %s", coin->clone.name);
282  else
283  stringbuffer_append_printf(buf, "%u %ss", num, coin->clone.name);
284  } while (next_coin);
285 
286 done:
287  return stringbuffer_finish(buf);
288 }
289 
300 static StringBuffer *real_money_value(const object *coin, StringBuffer *buf) {
301  assert(coin->type == MONEY);
302  assert(buf);
303 
304  stringbuffer_append_printf(buf, "%ld %s", (long)coin->nrof, coin->nrof == 1 ? coin->name : coin->name_pl);
305  return buf;
306 }
307 
308 char *cost_str(uint64_t cost) {
310 }
311 
312 char *cost_approx_str(const object *tmp, object *who) {
313  uint64_t approx_val = price_approx(tmp, who);
314  int idskill1 = 0;
315  int idskill2 = 0;
316  const typedata *tmptype;
317 
319 
320  /* money it's pretty hard to not give the exact price, so skip all logic and just return the real value. */
321  if (tmp->type == MONEY) {
322  return stringbuffer_finish(real_money_value(tmp, buf));
323  }
324 
325  tmptype = get_typedata(tmp->type);
326  if (tmptype) {
327  idskill1 = tmptype->identifyskill;
328  idskill2 = tmptype->identifyskill2;
329  }
330 
331  /* we show an approximate price if
332  * 1) we are approximating
333  * 2) there either is no id skill(s) for the item, or we don't have them
334  * 3) we don't have bargaining skill either
335  */
336  if (!idskill1 || !find_skill_by_number(who, idskill1)) {
337  if (!idskill2 || !find_skill_by_number(who, idskill2)) {
338  if (!find_skill_by_number(who, SK_BARGAINING)) {
339  int num;
340  int cointype = LARGEST_COIN_GIVEN;
341  archetype *coin = find_next_coin(approx_val, &cointype);
342 
343  if (coin == NULL) {
344  stringbuffer_append_string(buf, "nothing");
345  return stringbuffer_finish(buf);
346  }
347 
348  num = approx_val/coin->clone.value;
349  if (num == 1)
350  stringbuffer_append_printf(buf, "about one %s", coin->clone.name);
351  else if (num < 5)
352  stringbuffer_append_printf(buf, "a few %s", coin->clone.name_pl);
353  else if (num < 10)
354  stringbuffer_append_printf(buf, "several %s", coin->clone.name_pl);
355  else if (num < 25)
356  stringbuffer_append_printf(buf, "a moderate amount of %s", coin->clone.name_pl);
357  else if (num < 100)
358  stringbuffer_append_printf(buf, "lots of %s", coin->clone.name_pl);
359  else if (num < 1000)
360  stringbuffer_append_printf(buf, "a great many %s", coin->clone.name_pl);
361  else
362  stringbuffer_append_printf(buf, "a vast quantity of %s", coin->clone.name_pl);
363  return stringbuffer_finish(buf);
364  }
365  }
366  }
367 
368  // If we get here, return the price we guessed.
369  stringbuffer_delete(buf);
370  return cost_str(approx_val);
371 }
372 
373 uint64_t query_money(const object *op) {
374  uint64_t total = 0;
375 
376  if (op->type != PLAYER && op->type != CONTAINER) {
377  LOG(llevError, "Query money called with non player/container\n");
378  return 0;
379  }
380  FOR_INV_PREPARE(op, tmp) {
381  if (tmp->type == MONEY) {
382  total += (uint64_t)tmp->nrof*(uint64_t)tmp->value;
383  } else if (tmp->type == CONTAINER && QUERY_FLAG(tmp, FLAG_APPLIED)) {
384  total += query_money(tmp);
385  }
386  } FOR_INV_FINISH();
387  return total;
388 }
389 
402 int pay_for_amount(uint64_t to_pay, object *pl) {
403  if (to_pay == 0)
404  return 1;
405  if (to_pay > query_money(pl))
406  return 0;
407 
408  to_pay = pay_from_container(pl, pl, to_pay);
409 
410  FOR_INV_PREPARE(pl, pouch) {
411  if (to_pay <= 0)
412  break;
413  if (pouch->type == CONTAINER && QUERY_FLAG(pouch, FLAG_APPLIED)) {
414  to_pay = pay_from_container(pl, pouch, to_pay);
415  }
416  } FOR_INV_FINISH();
417  if (to_pay > 0) {
418  LOG(llevError, "pay_for_amount: Cannot remove enough money -- %" FMT64U " remains\n", to_pay);
419  }
420 
421  fix_object(pl);
422  return 1;
423 }
424 
440 int pay_for_item(object *op, object *pl, uint64_t reduction) {
441  uint64_t to_pay = shop_price_buy(op, pl);
442  assert(to_pay >= reduction);
443  to_pay -= reduction;
444 
445  if (to_pay == 0)
446  return 1;
447  if (to_pay > query_money(pl))
448  return 0;
449 
450  to_pay = pay_from_container(pl, pl, to_pay);
451 
452  FOR_INV_PREPARE(pl, pouch) {
453  if (to_pay <= 0)
454  break;
455  if (pouch->type == CONTAINER && QUERY_FLAG(pouch, FLAG_APPLIED)) {
456  to_pay = pay_from_container(pl, pouch, to_pay);
457  }
458  } FOR_INV_FINISH();
459  if (to_pay > 0) {
460  LOG(llevError, "pay_for_item: Cannot remove enough money -- %" FMT64U " remains\n", to_pay);
461  }
463  SET_FLAG(op, FLAG_WAS_WIZ);
464  fix_object(pl);
465  return 1;
466 }
467 
479 static int64_t remove_value(object *coin_objs[], int64_t remain) {
480  int i;
481 
482  for (i = 0; i < NUM_COINS; i++) {
483  int count;
484  int64_t num_coins;
485 
486  if ((int64_t)coin_objs[i]->nrof * coin_objs[i]->value > remain) {
487  num_coins = remain/coin_objs[i]->value;
488  if ((uint64_t)num_coins*(uint64_t)coin_objs[i]->value < (uint64_t) remain) {
489  num_coins++;
490  }
491  } else {
492  num_coins = coin_objs[i]->nrof;
493  }
494  remain -= (int64_t)num_coins*(int64_t)coin_objs[i]->value;
495  coin_objs[i]->nrof -= num_coins;
496  /* Now start making change. Start at the coin value
497  * below the one we just did, and work down to
498  * the lowest value.
499  */
500  count = i-1;
501  while (remain < 0 && count >= 0) {
502  num_coins = -remain/coin_objs[count]->value;
503  coin_objs[count]->nrof += num_coins;
504  remain += num_coins*coin_objs[count]->value;
505  count--;
506  }
507  }
508 
509  return remain;
510 }
511 
520 static void add_value(object *coin_objs[], int64_t value) {
521  int i;
522 
523  for (i = NUM_COINS-LARGEST_COIN_GIVEN-1; i >= 0; i--) {
524  uint32_t nrof;
525 
526  nrof = (uint32_t)(value/coin_objs[i]->value);
527  value -= nrof*coin_objs[i]->value;
528  coin_objs[i]->nrof += nrof;
529  }
530 }
531 
544 static void insert_objects(object *pl, object *container, object *objects[], int objects_len) {
545  int i, one = 0;
546 
547  for (i = 0; i < objects_len; i++) {
548  if (objects[i]->nrof > 0) {
549  object_insert_in_ob(objects[i], container);
550  one = 1;
551  } else {
552  object_free_drop_inventory(objects[i]);
553  }
554  }
555  if (one)
556  esrv_update_item(UPD_WEIGHT, pl, container);
557 }
558 
572 static uint64_t pay_from_container(object *pl, object *pouch, uint64_t to_pay) {
573  size_t i;
574  int64_t remain;
575  object *coin_objs[NUM_COINS];
576  object *other_money[16]; /* collects MONEY objects not matching coins[] */
577  size_t other_money_len; /* number of allocated entries in other_money[] */
578  archetype *at;
579 
580  if (pouch->type != PLAYER && pouch->type != CONTAINER)
581  return to_pay;
582 
583  remain = to_pay;
584  for (i = 0; i < NUM_COINS; i++)
585  coin_objs[i] = NULL;
586 
587  /* This hunk should remove all the money objects from the player/container */
588  other_money_len = 0;
589  FOR_INV_PREPARE(pouch, tmp) {
590  if (tmp->type == MONEY) {
591  for (i = 0; i < NUM_COINS; i++) {
592  if (!strcmp(coins[NUM_COINS-1-i], tmp->arch->name)
593  && (tmp->value == tmp->arch->clone.value)) {
594  /* This should not happen, but if it does, just
595  * merge the two.
596  */
597  if (coin_objs[i] != NULL) {
598  LOG(llevError, "%s has two money entries of (%s)\n", pouch->name, coins[NUM_COINS-1-i]);
599  object_remove(tmp);
600  coin_objs[i]->nrof += tmp->nrof;
602  } else {
603  object_remove(tmp);
604  coin_objs[i] = tmp;
605  }
606  break;
607  }
608  }
609  if (i == NUM_COINS) {
610  if (other_money_len >= sizeof(other_money)/sizeof(*other_money)) {
611  LOG(llevError, "pay_for_item: Cannot store non-standard money object %s\n", tmp->arch->name);
612  } else {
613  object_remove(tmp);
614  other_money[other_money_len++] = tmp;
615  }
616  }
617  }
618  } FOR_INV_FINISH();
619 
620  /* Fill in any gaps in the coin_objs array - needed to make change. */
621  /* Note that the coin_objs array goes from least value to greatest value */
622  for (i = 0; i < NUM_COINS; i++)
623  if (coin_objs[i] == NULL) {
624  at = find_archetype(coins[NUM_COINS-1-i]);
625  if (at == NULL) {
626  continue;
627  }
628  coin_objs[i] = object_new();
629  object_copy(&at->clone, coin_objs[i]);
630  coin_objs[i]->nrof = 0;
631  }
632 
633  /* Try to pay from standard coins first. */
634  remain = remove_value(coin_objs, remain);
635 
636  /* Now pay from non-standard coins until all is paid. */
637  for (i = 0; i < other_money_len && remain > 0; i++) {
638  uint32_t nrof;
639  object *coin;
640 
641  coin = other_money[i];
642 
643  /* Find the minimal number of coins to use. This prevents converting
644  * excess non-standard coins to standard money.
645  */
646  nrof = (remain+coin->value-1)/coin->value;
647  if (nrof > coin->nrof) {
648  nrof = coin->nrof;
649  }
650  coin->nrof -= nrof;
651  add_value(coin_objs, nrof*coin->value);
652 
653  remain = remove_value(coin_objs, remain);
654  }
655 
656  /* re-insert remaining coins into player */
657  insert_objects(pl, pouch, coin_objs, NUM_COINS);
658  insert_objects(pl, pouch, other_money, other_money_len);
659 
660  return(remain);
661 }
662 
663 uint64_t add_with_overflow(uint64_t a, uint64_t b) {
664  if (a == UINT64_MAX) {
665  return a;
666  }
667 
668  if (UINT64_MAX - a < b) {
669  // Overflow
670  return UINT64_MAX;
671  } else {
672  return a + b;
673  }
674 }
675 
676 struct unpaid_count {
677  object *pl;
678  int count;
679  uint64_t price;
680 };
681 
689 static void unpaid_iter(object *item, void (*callback)(object *item, void *data), void *data) {
691  if (QUERY_FLAG(item, FLAG_UNPAID)) {
692  callback(item, data);
693  }
694  if (item->inv) {
695  unpaid_iter(item->inv, callback, data);
696  }
698 }
699 
700 static void count_unpaid_callback(object *item, void *data) {
701  struct unpaid_count *args = (struct unpaid_count *)data;
702  args->count++;
703  args->price = add_with_overflow(args->price, shop_price_buy(item, args->pl));
704 }
705 
718 static void count_unpaid(object *pl, object *item, int *unpaid_count, uint64_t *unpaid_price) {
719  struct unpaid_count args = {pl, 0, 0};
720  unpaid_iter(item, count_unpaid_callback, &args);
721  *unpaid_count = args.count;
722  *unpaid_price = args.price;
723 }
724 
732 static void count_coins(object *item, uint32_t *coincount) {
734  /* Merely converting the player's monetary wealth won't do.
735  * If we did that, we could print the wrong numbers for the
736  * coins, so we count the money instead.
737  */
738  for (int i = 0; i < NUM_COINS; i++) {
739  if (!strcmp(coins[i], item->arch->name)) {
740  coincount[i] += item->nrof;
741  break;
742  }
743  }
744  if (item->inv) {
745  count_coins(item->inv, coincount);
746  }
748 }
749 
758 static uint64_t compute_price_variation_with_bargaining(object *pl, uint64_t price, float max_variation) {
759  object *skill = find_skill_by_number(pl, SK_BARGAINING);
760  if (skill && skill->level > 0) {
761  return rndm(0, price * (max_variation * skill->level / settings.max_level));
762  }
763  return 0;
764 }
765 
778 int can_pay(object *pl) {
779  int unpaid_count = 0, i;
780  uint64_t unpaid_price = 0;
781  uint32_t coincount[NUM_COINS];
782 
783  if (!pl || pl->type != PLAYER) {
784  LOG(llevError, "can_pay(): called against something that isn't a player\n");
785  return 0;
786  }
787  uint64_t player_wealth = query_money(pl);
788 
789  for (i = 0; i < NUM_COINS; i++)
790  coincount[i] = 0;
791 
792  count_unpaid(pl, pl->inv, &unpaid_count, &unpaid_price);
793  count_coins(pl->inv, coincount);
794 
795  if (unpaid_price > player_wealth) {
796  char buf[MAX_BUF], coinbuf[MAX_BUF];
797  int denominations = 0;
798  char *value = cost_str(unpaid_price);
799 
800  snprintf(buf, sizeof(buf), "You have %d unpaid items that would cost you %s, ", unpaid_count, value);
801  free(value);
802  for (i = 0; i < NUM_COINS; i++) {
803  if (coincount[i] > 0 && coins[i]) {
804  if (denominations == 0)
805  snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "but you only have");
806  denominations++;
807  archetype *arch = find_archetype(coins[i]);
808  if (arch != NULL)
809  {
810  snprintf(coinbuf, sizeof(coinbuf), " %u %s,", coincount[i], arch->clone.name_pl);
811  snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%s", coinbuf);
812  }
813  }
814  }
815  if (denominations == 0)
816  snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "but you don't have any money.");
817  else if (denominations > 1)
818  make_list_like(buf);
820  MSG_TYPE_SHOP_PAYMENT, buf);
821  return 0;
822  } else
823  return 1;
824 }
825 
826 static void shop_pay_unpaid_callback(object *op, void *data) {
827  object *pl = (object *)data;
828  char name_op[MAX_BUF];
829  uint64_t price = shop_price_buy(op, pl);
830  uint64_t reduction = 0;
831  if (!object_value_set(op, "price")) {
832  // only items without a player-set price can be bargained for
834  }
835  if (!pay_for_item(op, pl, reduction)) {
836  uint64_t i = price - query_money(pl);
837  char *missing = cost_str(i);
838 
839  CLEAR_FLAG(op, FLAG_UNPAID);
840  query_name(op, name_op, MAX_BUF);
843  "You lack %s to buy %s.",
844  missing, name_op);
845  free(missing);
846  SET_FLAG(op, FLAG_UNPAID);
847  return;
848  } else {
849  // TODO: Figure out how to pass in the shop owner for player shops.
850  if (events_execute_object_event(op, EVENT_BOUGHT, pl, NULL, NULL, SCRIPT_FIX_ALL) != 0)
851  return;
852 
853  object *tmp;
854  char *value = cost_str(price - reduction);
855 
856  CLEAR_FLAG(op, FLAG_UNPAID);
859  query_name(op, name_op, MAX_BUF);
860 
861  if (reduction > 0) {
862  char *reduction_str = cost_str(reduction);
865  "You paid %s for %s after bargaining a reduction of %s.",
866  value, name_op, reduction_str);
867  change_exp(pl, reduction, "bargaining", SK_EXP_NONE);
868  free(reduction_str);
869  } else {
872  "You paid %s for %s.",
873  value, name_op);
874  }
875  free(value);
876  tmp = object_merge(op, NULL);
877  if (pl->type == PLAYER && !tmp) {
878  /* If item wasn't merged we update it. If merged, object_merge() handled everything for us. */
880  }
881  }
882 }
883 
890 int shop_pay_unpaid(object *pl, object *op) {
891  if (!op) {
892  return 1;
893  }
895  return 1;
896 }
897 
909 void sell_item(object *op, object *pl) {
910  object *tmp;
911  archetype *at;
912  char obj_name[MAX_BUF];
913 
914  query_name(op, obj_name, MAX_BUF);
915 
916  if (pl == NULL || pl->type != PLAYER) {
917  LOG(llevDebug, "Object other than player tried to sell something.\n");
918  return;
919  }
920 
921  if (events_execute_object_event(op, EVENT_SELLING, pl, NULL, NULL, SCRIPT_FIX_ALL) != 0)
922  return;
923 
924  object_set_value(op, CUSTOM_NAME_FIELD, NULL, 0);
925 
926  uint64_t price = shop_price_sell(op, pl);
927  if (price == 0) {
930  "We're not interested in %s.",
931  obj_name);
932  return;
933  }
935 
936  int64_t extra_gain = compute_price_variation_with_bargaining(pl, price, MAX_SELL_EXTRA);
937  char *value_str = cost_str(price + extra_gain);
938 
939  if (extra_gain > 0) {
940  change_exp(pl, extra_gain, "bargaining", SK_EXP_NONE);
941  char *extra_str = cost_str(extra_gain);
943  "You receive %s for %s, after bargaining for %s more than proposed.", value_str, obj_name, extra_str);
944  free(extra_str);
945  price += extra_gain;
946  } else {
948  "You receive %s for %s.", value_str, obj_name);
949  }
950  free(value_str);
951 
952  for (int count = LARGEST_COIN_GIVEN; coins[count] != NULL; count++) {
953  at = find_archetype(coins[count]);
954  if (at == NULL)
955  LOG(llevError, "Could not find %s archetype\n", coins[count]);
956  else if ((price/at->clone.value) > 0) {
957  FOR_INV_PREPARE(pl, pouch) {
958  // Try to put money in player's active container
959  int n = price/at->clone.value;
960  // pass NULL as PL to avoid sending player messages about things that don't fit
961  if (pouch->type == CONTAINER && sack_can_hold(NULL, pouch, &at->clone, n)) {
962  tmp = object_new();
963  object_copy(&at->clone, tmp);
964  tmp->nrof = n;
965  price -= (uint64_t)tmp->nrof*(uint64_t)tmp->value;
966  tmp = object_insert_in_ob(tmp, pouch);
967  esrv_update_item(UPD_WEIGHT, pl, pl);
968  }
969  } FOR_INV_FINISH();
970  // Any left over get put into player's inventory
971  // TODO: This doesn't check the player's weight limit
972  if (price/at->clone.value > 0) {
973  tmp = object_new();
974  object_copy(&at->clone, tmp);
975  tmp->nrof = price/tmp->value;
976  price -= (uint64_t)tmp->nrof*(uint64_t)tmp->value;
977  tmp = object_insert_in_ob(tmp, pl);
978  esrv_update_item(UPD_WEIGHT, pl, pl);
979  }
980  }
981  }
982 
983  if (price != 0) {
984  LOG(llevError, "Warning - payment not zero: %" PRIo64 "\n", price);
985  }
986 
987  SET_FLAG(op, FLAG_UNPAID);
988  identify(op);
989 }
990 
1006 static double shop_specialisation_ratio(const object *item, const mapstruct *map) {
1007  shopitems *items = map->shopitems;
1008  double ratio = SPECIALISATION_EFFECT, likedness = 0.001;
1009  int i;
1010 
1011  if (item == NULL) {
1012  LOG(llevError, "shop_specialisation_ratio: passed a NULL item for map %s\n", map->path);
1013  return 0;
1014  }
1015  if (item->type == (uint8_t)-1) {
1016  LOG(llevError, "shop_specialisation_ratio: passed an item with an invalid type\n");
1017  /*
1018  * I'm not really sure what the /right/ thing to do here is,
1019  * these types of item shouldn't exist anyway, but returning
1020  * the ratio is probably the best bet.."
1021  */
1022  return ratio;
1023  }
1024  if (map->shopitems) {
1025  for (i = 0; i < items[0].index; i++)
1026  if (items[i].typenum == item->type || (items[i].typenum == -1 && likedness == 0.001))
1027  likedness = items[i].strength/100.0;
1028  }
1029  if (likedness > 1.0) { /* someone has been rather silly with the map headers. */
1030  LOG(llevDebug, "shop_specialisation ratio: item type %d on map %s is above 100%%\n", item->type, map->path);
1031  likedness = 1.0;
1032  }
1033  if (likedness < -1.0) {
1034  LOG(llevDebug, "shop_specialisation ratio: item type %d on map %s is below -100%%\n", item->type, map->path);
1035  likedness = -1.0;
1036  }
1037  ratio = ratio+(1.0-ratio)*likedness;
1038  if (ratio <= 0.1)
1039  ratio = 0.1; /* if the ratio were much lower than this, we would get silly prices */
1040  return ratio;
1041 }
1042 
1057 static double shop_greed(const mapstruct *map) {
1058  float greed = map->shopgreed;
1059  if (greed == 0) {
1060  greed = 1;
1061  }
1062  return tanh(-greed+2.0)/2 + 0.5;
1063 }
1064 
1065 double shop_approval(const mapstruct *map, const object *player) {
1066  double approval = 1.0;
1067  if (map->shoprace) {
1068  approval = NEUTRAL_RATIO;
1069  if (player->race && !strcmp(player->race, map->shoprace))
1070  approval = 1.0;
1071  }
1072  return approval;
1073 }
1074 
1094 static uint64_t value_limit(uint64_t val, int quantity, const object *who, int isshop) {
1095  uint64_t newval, unit_price;
1096  mapstruct *map;
1097 
1098  unit_price = val/quantity;
1099  if (!isshop || !who) {
1100  if (unit_price > 10000)
1101  newval = 8000+isqrt(unit_price)*20;
1102  else
1103  newval = unit_price;
1104  } else {
1105  if (!who->map) {
1106  LOG(llevError, "value_limit: asked shop price for ob %s on NULL map\n", who->name);
1107  return val;
1108  }
1109  map = who->map;
1110  if (map->shopmin && unit_price < map->shopmin)
1111  return 0;
1112  else if (unit_price > map->shopmax/2)
1113  newval = MIN((map->shopmax/2)+isqrt(unit_price-map->shopmax/2), map->shopmax);
1114  else if (unit_price > 10000)
1115  newval = 8000+isqrt(unit_price)*20;
1116  else
1117  newval = unit_price;
1118  }
1119  newval *= quantity;
1120  return newval;
1121 }
1122 
1128 int shop_describe(const object *op) {
1129  mapstruct *map = op->map;
1130  /*shopitems *items=map->shopitems;*/
1131  int pos = 0, i;
1132  double opinion = 0;
1133  char tmp[MAX_BUF] = "\0", *value;
1134 
1135  if (op->type != PLAYER)
1136  return 0;
1137 
1138  /*check if there is a shop specified for this map */
1139  if (map->shopitems
1140  || map->shopgreed
1141  || map->shoprace
1142  || map->shopmin
1143  || map->shopmax) {
1145  "From looking at the nearby shop you determine that it trades in:");
1146 
1147  if (map->shopitems) {
1148  for (i = 0; i < map->shopitems[0].index; i++) {
1149  if (map->shopitems[i].name && map->shopitems[i].strength > 10) {
1150  snprintf(tmp+pos, sizeof(tmp)-pos, "%s, ", map->shopitems[i].name_pl);
1151  pos += strlen(tmp+pos);
1152  }
1153  }
1154  }
1155  if (!pos)
1156  strcpy(tmp, "a little of everything.");
1157 
1158  /* format the string into a list */
1159  make_list_like(tmp);
1160  draw_ext_info(NDI_UNIQUE, 0, op,
1162 
1163  if (map->shopmax) {
1164  value = cost_str(map->shopmax);
1167  "It won't trade for items above %s.",
1168  value);
1169  free(value);
1170  }
1171 
1172  if (map->shopmin) {
1173  value = cost_str(map->shopmin);
1176  "It won't trade in items worth less than %s.",
1177  value);
1178  free(value);
1179  }
1180 
1181  if (map->shopgreed) {
1182  if (map->shopgreed > 2.0)
1183  draw_ext_info(NDI_UNIQUE, 0, op,
1185  "It tends to overcharge massively.");
1186  else if (map->shopgreed > 1.5)
1187  draw_ext_info(NDI_UNIQUE, 0, op,
1189  "It tends to overcharge substantially.");
1190  else if (map->shopgreed > 1.1)
1191  draw_ext_info(NDI_UNIQUE, 0, op,
1193  "It tends to overcharge slightly.");
1194  else if (map->shopgreed < 0.9)
1195  draw_ext_info(NDI_UNIQUE, 0, op,
1197  "It tends to undercharge.");
1198  }
1199  if (map->shoprace) {
1200  opinion = shop_approval(map, op);
1201  if (opinion > 0.8)
1202  draw_ext_info(NDI_UNIQUE, 0, op,
1204  "You think the shopkeeper likes you.");
1205  else if (opinion > 0.5)
1206  draw_ext_info(NDI_UNIQUE, 0, op,
1208  "The shopkeeper seems unconcerned by you.");
1209  else
1210  draw_ext_info(NDI_UNIQUE, 0, op,
1212  "The shopkeeper seems to have taken a dislike to you.");
1213  }
1215  "There is no shop nearby.");
1216 
1217  return 1;
1218 }
Error, serious thing.
Definition: logger.h:11
static event_registration c
Definition: citylife.cpp:424
int pay_for_amount(uint64_t to_pay, object *pl)
Takes the amount of money from the the player inventory and from it&#39;s various pouches using the pay_f...
Definition: shop.cpp:402
static void count_unpaid(object *pl, object *item, int *unpaid_count, uint64_t *unpaid_price)
Sum the amount to pay for all unpaid items and find available money.
Definition: shop.cpp:718
#define LARGEST_COIN_GIVEN
Never give amber or jade, but accept them.
Definition: shop.cpp:59
#define FLAG_PLAYER_SOLD
Object was sold to a shop by a player.
Definition: define.h:239
int index
Being the size of the shopitems array.
Definition: map.h:306
#define FLAG_UNPAID
Object hasn&#39;t been paid for yet.
Definition: define.h:223
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
static uint64_t compute_price_variation_with_bargaining(object *pl, uint64_t price, float max_variation)
Compute a percent of the price which will be used as extra or reduction.
Definition: shop.cpp:758
static archetype * find_next_coin(uint64_t c, int *cointype)
Find the coin type that is worth more than &#39;c&#39;.
Definition: shop.cpp:188
char * cost_str(uint64_t cost)
Definition: shop.cpp:308
#define MSG_TYPE_SHOP_LISTING
Shop listings - inventory, what it deals in.
Definition: newclient.h:527
struct archetype * arch
Pointer to archetype.
Definition: object.h:424
uint64_t shopmax
MMaximum price a shop will offer.
Definition: map.h:355
#define MSG_TYPE_SHOP_SELL
Messages about selling items.
Definition: newclient.h:533
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.cpp:58
uint64_t price_approx(const object *tmp, object *who)
Adjust the value of the given item based on the player&#39;s skills.
Definition: shop.cpp:71
int rndm(int min, int max)
Returns a number between min and max.
Definition: utils.cpp:162
int identifyskill
Skill used to identify this object class.
Definition: define.h:93
const typedata * get_typedata(int itemtype)
Definition: item.cpp:328
static float shop_cha_modifier(int charisma)
Calculate the buy price multiplier based on a player&#39;s charisma.
Definition: shop.cpp:111
#define NEUTRAL_RATIO
Price a shopkeeper will give someone they neither like nor dislike.
Definition: shop.cpp:45
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
archetype * find_archetype(const char *name)
Definition: assets.cpp:270
void fix_object(object *op)
Updates all abilities given by applied objects in the inventory of the given object.
Definition: living.cpp:1132
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to...
Definition: object.cpp:1818
static uint64_t pay_from_container(object *pl, object *pouch, uint64_t to_pay)
This pays for the item, and takes the proper amount of money off the specified container (pouch or pl...
Definition: shop.cpp:572
int pay_for_item(object *op, object *pl, uint64_t reduction)
Player attemps to buy an item, if she has enough money then remove coins as needed from active contai...
Definition: shop.cpp:440
int16_t max_level
This is read out of exp_table.
Definition: global.h:303
int8_t strength
The degree of specialisation the shop has in this item, as a percentage from -100 to 100...
Definition: map.h:304
#define FMT64U
Definition: compat.h:17
#define MSG_TYPE_SHOP_PAYMENT
Messages about payment, lack of funds.
Definition: newclient.h:530
void esrv_update_item(int flags, object *pl, object *op)
Updates object *op for player *pl.
Definition: main.cpp:359
See Money.
Definition: object.h:142
static void unpaid_iter(object *item, void(*callback)(object *item, void *data), void *data)
Search for unpaid items in &#39;item&#39; and call &#39;callback&#39; on each item.
Definition: shop.cpp:689
static uint32_t NROF(const object *const ob)
Returns ob->nrof, unless it is 0, in which case return 1.
Definition: object.h:627
int32_t value
How much money it is worth (or contains)
Definition: object.h:360
void sell_item(object *op, object *pl)
Player is selling an item.
Definition: shop.cpp:909
#define EVENT_SELLING
Object is being sold by another one.
Definition: events.h:38
void change_exp(object *op, int64_t exp, const char *skill_name, int flag)
Changes experience to a player/monster.
Definition: living.cpp:2179
int sack_can_hold(const object *pl, const object *sack, const object *op, uint32_t nrof)
Check if an item op can be put into a sack.
Definition: container.cpp:66
#define NUM_COINS
Number of coin types.
Definition: shop.cpp:57
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
uint64_t query_money(const object *op)
Determine the amount of money the given object contains, including what is inside containers...
Definition: shop.cpp:373
#define MAX_SELL_EXTRA
Maximum price increase when selling an item with bargaining skill.
Definition: shop.cpp:50
#define FALSE
Definition: compat.h:14
Global type definitions and header inclusions.
Link an object type with skill needed to identify, and general name.
Definition: define.h:89
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Sends message to player(s).
Definition: main.cpp:308
#define SPECIALISATION_EFFECT
This is a measure of how effective store specialisation is.
Definition: shop.cpp:39
Bargaining.
Definition: skills.h:28
#define FOR_OB_AND_BELOW_FINISH()
Finishes FOR_OB_AND_BELOW_PREPARE().
Definition: define.h:777
#define MIN(x, y)
Definition: compat.h:21
void events_execute_global_event(int eventcode,...)
Execute a global event.
Definition: events.cpp:30
static const char *const coins[]
Coins to use for shopping.
Definition: shop.cpp:62
#define MAX_BUY_REDUCTION
Maximum price reduction when buying an item with bargaining skill.
Definition: shop.cpp:48
static void insert_objects(object *pl, object *container, object *objects[], int objects_len)
Insert a list of objects into a player object.
Definition: shop.cpp:544
int shop_pay_unpaid(object *pl, object *op)
Pay as many unpaid items as possible, recursing on op->inv and op->below.
Definition: shop.cpp:890
int16_t level
Level of creature or object.
Definition: object.h:361
uint64_t add_with_overflow(uint64_t a, uint64_t b)
Definition: shop.cpp:663
static StringBuffer * real_money_value(const object *coin, StringBuffer *buf)
Returns a string representing the money&#39;s value, in plain coins.
Definition: shop.cpp:300
static void shop_pay_unpaid_callback(object *op, void *data)
Definition: shop.cpp:826
object * identify(object *op)
Identifies an item.
Definition: item.cpp:1446
The archetype structure is a set of rules on how to generate and manipulate objects which point to ar...
Definition: object.h:483
sstring name
More definite name, like "generate_kobold".
Definition: object.h:484
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Append a formatted string to a string buffer instance.
int shop_describe(const object *op)
A player is examining a shop, so describe it.
Definition: shop.cpp:1128
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:360
#define SET_FLAG(xyz, p)
Definition: define.h:384
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Append a string to a string buffer instance.
#define QUERY_FLAG(xyz, p)
Definition: define.h:386
static void count_coins(object *item, uint32_t *coincount)
Count the number of coins for each type, for all items below item and in inventory.
Definition: shop.cpp:732
double shopgreed
How much our shopkeeper overcharges.
Definition: map.h:353
static uint64_t value_limit(uint64_t val, int quantity, const object *who, int isshop)
Limit the value of items based on the wealth of the shop.
Definition: shop.cpp:1094
uint64_t shop_price_buy(const object *tmp, object *who)
Adjust the value of an item to be bought based on the player&#39;s bargaining skill and charisma...
Definition: shop.cpp:128
void query_name(const object *op, char *buf, size_t size)
Describes an item.
Definition: item.cpp:594
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.cpp:1545
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
Definition: define.h:700
#define MSG_TYPE_SHOP_MISC
Random messages.
Definition: newclient.h:534
sstring race
Human, goblin, dragon, etc.
Definition: object.h:326
This is a game-map.
Definition: map.h:320
int count
Definition: shop.cpp:678
sstring object_get_value(const object *op, const char *const key)
Get an extra value by key.
Definition: object.cpp:4331
int typenum
Itemtype number we need to match, -1 if it is the default price.
Definition: map.h:303
uint64_t shopmin
Minimum price a shop will trade for.
Definition: map.h:354
#define UPD_FLAGS
Definition: newclient.h:331
uint8_t real_wiz
Use mud-like wizards.
Definition: global.h:272
uint64_t shop_price_sell(const object *tmp, object *who)
Adjust the value of an item to be sold based on the player&#39;s bargaining skill and charisma...
Definition: shop.cpp:154
struct Settings settings
Global settings.
Definition: init.cpp:139
static double shop_specialisation_ratio(const object *item, const mapstruct *map)
Returns the ratio of the price that a shop will offer for an item based on the shop&#39;s specialisation...
Definition: shop.cpp:1006
object * object_new(void)
Grabs an object from the list of unused objects, makes sure it is initialised, and returns it...
Definition: object.cpp:1258
#define MSG_TYPE_SHOP
Definition: newclient.h:419
#define UPD_WEIGHT
Definition: newclient.h:332
object * pl
Definition: shop.cpp:677
static double shop_greed(const mapstruct *map)
Gets a shop&#39;s greed.
Definition: shop.cpp:1057
static int64_t remove_value(object *coin_objs[], int64_t remain)
This function removes a given amount from a list of coins.
Definition: shop.cpp:479
int isqrt(int n)
Compute the square root.
Definition: utils.cpp:562
living stats
Str, Con, Dex, etc.
Definition: object.h:378
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
char * cost_string_from_value(uint64_t cost, int largest_coin)
Converts a price to number of coins.
Definition: shop.cpp:220
char * shoprace
The preffered race of the local shopkeeper.
Definition: map.h:352
uint64_t price_base(const object *obj)
Price an item based on its value or archetype value, type, identification/BUC status, and other heuristics.
Definition: item.cpp:1507
void object_copy(const object *src_ob, object *dest_ob)
Copy object first frees everything allocated by the second object, and then copies the contents of th...
Definition: object.cpp:1177
struct mapstruct * map
Pointer to the map in which this object is present.
Definition: object.h:305
#define EVENT_BOUGHT
Object is being bought by player.
Definition: events.h:31
See Container.
Definition: object.h:236
#define EVENT_GSOLD
Player sold object in shop, but global.
Definition: events.h:71
int identifyskill2
Second skill used to identify this object class.
Definition: define.h:94
const char * name_pl
Plural name.
Definition: map.h:302
object * object_merge(object *op, object *top)
This function goes through all objects below and including top, and merges op to the first matching o...
Definition: object.cpp:2036
See Player.
Definition: object.h:112
sstring name_pl
The plural name of the object.
Definition: object.h:323
static void count_unpaid_callback(object *item, void *data)
Definition: shop.cpp:700
int done
Definition: readable.cpp:1564
sstring name
The name of the object, obviously...
Definition: object.h:319
#define SCRIPT_FIX_ALL
Definition: global.h:380
const char * name
Name of the item in question, null if it is the default item.
Definition: map.h:301
Only for debugging purposes.
Definition: logger.h:13
uint32_t nrof
Number of objects.
Definition: object.h:342
int8_t Cha
Use
Definition: living.h:36
#define SK_EXP_NONE
Player gets nothing.
Definition: skills.h:80
#define CLEAR_FLAG(xyz, p)
Definition: define.h:385
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:348
#define FLAG_APPLIED
Object is ready for use by living.
Definition: define.h:222
void stringbuffer_delete(StringBuffer *sb)
Totally delete a string buffer.
#define UPD_NAME
Definition: newclient.h:334
Shop-related information for a map.
Definition: map.h:300
int object_set_value(object *op, const char *key, const char *value, int add_key)
Updates the key in op to value.
Definition: object.cpp:4484
object * inv
Pointer to the first object in the inventory.
Definition: object.h:298
#define FOR_OB_AND_BELOW_PREPARE(op_)
Constructs a loop iterating over an object and all objects below it in the same pile.
Definition: define.h:773
object * objects
Pointer to the list of used objects.
Definition: object.cpp:294
char * cost_approx_str(const object *tmp, object *who)
Return a textual cost approximation in a newly-allocated string.
Definition: shop.cpp:312
float shop_efficiency(const object *player)
Return the shop&#39;s efficiency (E) for a player, a number greater than (but not equal to) zero and less...
Definition: shop.cpp:122
int events_execute_object_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
Execute an event on the specified object.
Definition: events.cpp:309
#define NDI_UNIQUE
Print immediately, don&#39;t buffer.
Definition: newclient.h:270
double shop_approval(const mapstruct *map, const object *player)
Return the approval ratio for a shop for a given player.
Definition: shop.cpp:1065
One player.
Definition: player.h:107
#define FLAG_WAS_WIZ
Player was once a wiz.
Definition: define.h:221
StringBuffer * buf
Definition: readable.cpp:1563
void make_list_like(char *input)
Taking a string as an argument, mutate it into a string that looks like a list.
Definition: utils.cpp:368
A buffer that will be expanded as content is added to it.
struct shopitems * shopitems
List of item-types the map&#39;s shop will trade in.
Definition: map.h:351
object * find_skill_by_number(object *who, int skillno)
This returns the first skill pointer of the given subtype (the one that accumulates exp...
Definition: main.cpp:375
object * object_insert_in_ob(object *op, object *where)
This function inserts the object op in the linked list inside the object environment.
Definition: object.cpp:2842
uint64_t price
Definition: shop.cpp:679
tag_t count
Unique object number for this object.
Definition: object.h:307
static void add_value(object *coin_objs[], int64_t value)
This function adds a given amount to a list of coins.
Definition: shop.cpp:520
object clone
An object from which to do object_copy()
Definition: object.h:487
bool object_value_set(const object *op, const char *const key)
Determine if an extra value is set.
Definition: object.cpp:4361
#define CUSTOM_NAME_FIELD
Key in an object for the player-assigned custom name.
Definition: object.h:98
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
Definition: define.h:693
#define EVENT_GBOUGHT
Player bought object in shop, but global.
Definition: events.h:70
int can_pay(object *pl)
Checks all unpaid items in op&#39;s inventory, adds up all the money they have, and checks that they can ...
Definition: shop.cpp:778