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 <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 
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 (std::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) {
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) {
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 }
object::name_pl
sstring name_pl
Definition: object.h:323
cost_approx_str
char * cost_approx_str(const object *tmp, object *who)
Definition: shop.cpp:369
shopitems::strength
int8_t strength
Definition: map.h:298
shop_approval
double shop_approval(const mapstruct *map, const object *player)
Definition: shop.cpp:1131
PLAYER
@ PLAYER
Definition: object.h:112
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
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:225
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
player
Definition: player.h:105
altar_valkyrie.obj
obj
Definition: altar_valkyrie.py:33
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
n
based on the size of the this randomly makes land number of spaces randomly lower or higher The default is Note that this is run also based on the the altitude amount will likely be less So if you do something like l and n
Definition: land.6.txt:25
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
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:2046
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
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:305
SHOP_FLOOR
@ SHOP_FLOOR
Definition: object.h:188
GEM
@ GEM
Definition: object.h:172
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
shopitems::index
int index
Definition: map.h:300
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
Ice.tmp
int tmp
Definition: Ice.py:207
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
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:499
coins
static const char *const coins[]
Definition: shop.cpp:62
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:4337
MSG_TYPE_SHOP_MISC
#define MSG_TYPE_SHOP_MISC
Definition: newclient.h:502
FLAG_APPLIED
#define FLAG_APPLIED
Definition: define.h:235
object::level
int16_t level
Definition: object.h:361
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:1552
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.cpp:2848
pay_for_item
int pay_for_item(object *op, object *pl, uint64_t reduction)
Definition: shop.cpp:501
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
draw_ext_info
vs only yadda is in because all tags get reset on the next draw_ext_info In the second since it is all in one draw_ext_info
Definition: media-tags.txt:61
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:1555
NROF
static uint32_t NROF(const object *const ob)
Definition: object.h:616
disinfect.map
map
Definition: disinfect.py:4
FLAG_WAS_WIZ
#define FLAG_WAS_WIZ
Definition: define.h:234
make_face_from_files.args
args
Definition: make_face_from_files.py:37
get_typedata
const typedata * get_typedata(int itemtype)
Definition: item.cpp:327
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:592
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
archetype::clone
object clone
Definition: object.h:478
say.price
dictionary price
Definition: say.py:147
FOR_OB_AND_BELOW_FINISH
#define FOR_OB_AND_BELOW_FINISH()
Definition: define.h:754
isqrt
int isqrt(int n)
Definition: utils.cpp:559
unpaid_count
Definition: shop.cpp:739
CONTAINER
@ CONTAINER
Definition: object.h:236
done
int done
Definition: readable.cpp:1553
SCRIPT_FIX_ALL
#define SCRIPT_FIX_ALL
Definition: global.h:388
object::value
int32_t value
Definition: object.h:360
is_identified
int is_identified(const object *op)
Definition: item.cpp:1352
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
object::type
uint8_t type
Definition: object.h:348
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:304
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:2168
disinfect.count
int count
Definition: disinfect.py:7
SK_BARGAINING
@ SK_BARGAINING
Definition: skills.h:28
archetype
Definition: object.h:474
add_with_overflow
uint64_t add_with_overflow(uint64_t a, uint64_t b)
Definition: shop.cpp:726
sproto.h
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
MSG_TYPE_SHOP
#define MSG_TYPE_SHOP
Definition: newclient.h:392
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:1268
shopitems::typenum
int typenum
Definition: map.h:297
EVENT_BOUGHT
#define EVENT_BOUGHT
Definition: events.h:23
object::weight
int32_t weight
Definition: object.h:375
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
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:251
object::name
sstring name
Definition: object.h:319
Settings::max_level
int16_t max_level
Definition: global.h:302
MSG_TYPE_SHOP_SELL
#define MSG_TYPE_SHOP_SELL
Definition: newclient.h:501
shop_contains
bool shop_contains(object *ob)
Definition: shop.cpp:1296
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
mapstruct
Definition: map.h:314
floor
Magical Runes Runes are magical inscriptions on the dungeon floor
Definition: runes-guide.txt:3
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:266
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
shopitems
Definition: map.h:294
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:497
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:307
count_unpaid_callback
static void count_unpaid_callback(object *item, void *data)
Definition: shop.cpp:763
skill
skill
Definition: arch-handbook.txt:585
object_remove
void object_remove(object *op)
Definition: object.cpp:1828
a
Magical Runes Runes are magical inscriptions on the dungeon which cast a spell or detonate when something steps on them Flying objects don t detonate runes Beware ! Runes are invisible most of the time They are only visible occasionally ! There are several runes which are there are some special runes which may only be called with the invoke and people may apply it to read it Maybe useful for mazes ! This rune will not nor is it ordinarily invisible Partial Visibility of they ll be visible only part of the time They have a(your level/2) chance of being visible in any given round
FLAG_PLAYER_SOLD
#define FLAG_PLAYER_SOLD
Definition: define.h:252
FLAG_UNPAID
#define FLAG_UNPAID
Definition: define.h:236
object::nrof
uint32_t nrof
Definition: object.h:342
rndm
int rndm(int min, int max)
Definition: utils.cpp:162
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:4490
diamondslots.cost
int cost
Definition: diamondslots.py:21
make_list_like
void make_list_like(char *input)
Definition: utils.cpp:368
StringBuffer
Definition: stringbuffer.cpp:25
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
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:98
count_unpaid
static void count_unpaid(object *pl, object *item, int *unpaid_count, uint64_t *unpaid_price)
Definition: shop.cpp:781
FOR_INV_PREPARE
#define FOR_INV_PREPARE(op_, it_)
Definition: define.h:670
llevDebug
@ llevDebug
Definition: logger.h:13
MONEY
@ MONEY
Definition: object.h:142
Settings::real_wiz
uint8_t real_wiz
Definition: global.h:271
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:1425