Go to the documentation of this file.
39 #define SPECIALISATION_EFFECT 0.5
42 #define DISAPPROVAL_RATIO 0.2
45 #define NEUTRAL_RATIO 0.8
48 #define MAX_BUY_REDUCTION 0.1f
50 #define MAX_SELL_EXTRA 0.1f
59 #define LARGEST_COIN_GIVEN 2
62 static const char *const coins[] = {
79 uint64_t val = (uint64_t)
obj->
value * number;
84 float ratio = atof(
key);
113 if (
obj->
arch != NULL && identified) {
115 val *= pow(1.15, diff);
147 int lev_identify = 0;
161 LOG(
llevError,
"Query_cost: item %s hasn't got a valid type\n",
tmp->name);
163 val += val * (sin(
tmp->count) / sqrt(lev_identify * 3 + 1.0));
174 return tanh((charisma+15.0)/20);
199 const float adj_val = val * adj / E;
200 if (getenv(
"CF_DEBUG_SHOP")) {
201 LOG(
llevDebug,
"price_buy %s %u*adj(%.2f)/E(%.2f) = %u\n",
202 tmp->arch->name, val, adj, E, adj_val);
204 if (isfinite(adj_val)) {
221 const uint64_t adj_val = val * adj * spec * E;
227 if (getenv(
"CF_DEBUG_SHOP")) {
228 LOG(
llevDebug,
"price_sell %s %u*adj(%.2f)*s(%.2f)*E(%.2f) = %u limited to %u\n",
229 tmp->arch->name, val, adj, spec, E, adj_val, limval);
288 if (
cost == UINT64_MAX) {
316 if (next_coin == NULL)
434 LOG(
llevError,
"Query money called with non player/container\n");
442 && (
tmp->race == NULL || strstr(
tmp->race,
"gold"))) {
474 && (pouch->race == NULL || strstr(pouch->race,
"gold"))) {
479 LOG(
llevError,
"pay_for_amount: Cannot remove enough money -- %"FMT64U" remains\n", to_pay);
503 assert(to_pay >= reduction);
518 && (pouch->race == NULL || strstr(pouch->race,
"gold"))) {
523 LOG(
llevError,
"pay_for_item: Cannot remove enough money -- %"FMT64U" remains\n", to_pay);
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) {
555 num_coins = coin_objs[i]->
nrof;
557 remain -= (int64_t)num_coins*(int64_t)coin_objs[i]->
value;
558 coin_objs[i]->
nrof -= num_coins;
564 while (remain < 0 && count >= 0) {
591 coin_objs[i]->
nrof += nrof;
610 for (i = 0; i < objects_len; i++) {
639 object *other_money[16];
640 size_t other_money_len;
656 && (
tmp->value ==
tmp->arch->clone.value)) {
660 if (coin_objs[i] != NULL) {
663 coin_objs[i]->
nrof +=
tmp->nrof;
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);
677 other_money[other_money_len++] =
tmp;
686 if (coin_objs[i] == NULL) {
693 coin_objs[i]->
nrof = 0;
700 for (i = 0; i < other_money_len && remain > 0; i++) {
704 coin = other_money[i];
743 if (*unpaid_price != UINT64_MAX) {
744 if (UINT64_MAX - (*unpaid_price) <
price) {
746 *unpaid_price = UINT64_MAX;
748 *unpaid_price +=
price;
772 if (!strcmp(
coins[i],
item->arch->name)) {
773 coincount[i] +=
item->nrof;
793 if (skill && skill->
level > 0) {
812 int unpaid_count = 0, i;
813 uint64_t unpaid_price = 0;
817 LOG(
llevError,
"can_pay(): called against something that isn't a player\n");
828 if (unpaid_price > player_wealth) {
830 int denominations = 0;
833 snprintf(
buf,
sizeof(
buf),
"You have %d unpaid items that would cost you %s, ", unpaid_count,
value);
836 if (coincount[i] > 0 &&
coins[i]) {
837 if (denominations == 0)
838 snprintf(
buf+strlen(
buf),
sizeof(
buf)-strlen(
buf),
"but you only have");
843 snprintf(coinbuf,
sizeof(coinbuf),
" %u %s,", coincount[i],
arch->clone.name_pl);
844 snprintf(
buf+strlen(
buf),
sizeof(
buf)-strlen(
buf),
"%s", coinbuf);
848 if (denominations == 0)
849 snprintf(
buf+strlen(
buf),
sizeof(
buf)-strlen(
buf),
"but you don't have any money.");
850 else if (denominations > 1)
877 object *below =
op->below;
890 "You lack %s to buy %s.",
907 char *reduction_str =
cost_str(reduction);
910 "You paid %s for %s after bargaining a reduction of %s.",
911 value, name_op, reduction_str);
917 "You paid %s for %s.",
953 LOG(
llevDebug,
"Object other than player tried to sell something.\n");
967 "We're not interested in %s.",
975 if (extra_gain > 0) {
977 char *extra_str =
cost_str(extra_gain);
979 "You receive %s for %s, after bargaining for %s more than proposed.", value_str, obj_name, extra_str);
984 "You receive %s for %s.", value_str, obj_name);
997 && strstr(pouch->race,
"gold")) {
998 int w = at->
clone.
weight*(100-pouch->stats.Str)/100;
1004 && (!pouch->weight_limit || pouch->carrying+w <= pouch->weight_limit)) {
1005 if (pouch->weight_limit
1006 && (pouch->weight_limit-pouch->carrying)/w < n)
1007 n = (pouch->weight_limit-pouch->carrying)/w;
1012 price -= (uint64_t)
tmp->nrof*(uint64_t)
tmp->value;
1022 price -= (uint64_t)
tmp->nrof*(uint64_t)
tmp->value;
1058 LOG(
llevError,
"shop_specialisation_ratio: passed a NULL item for map %s\n",
map->path);
1061 if (
item->type == (uint8_t)-1) {
1062 LOG(
llevError,
"shop_specialisation_ratio: passed an item with an invalid type\n");
1070 if (
map->shopitems) {
1071 for (i = 0; i < items[0].
index; i++)
1072 if (items[i].typenum ==
item->type || (items[i].
typenum == -1 && likedness == 0.001))
1073 likedness = items[i].
strength/100.0;
1075 if (likedness > 1.0) {
1076 LOG(
llevDebug,
"shop_specialisation ratio: item type %d on map %s is above 100%%\n",
item->type,
map->path);
1079 if (likedness < -1.0) {
1080 LOG(
llevDebug,
"shop_specialisation ratio: item type %d on map %s is below -100%%\n",
item->type,
map->path);
1083 ratio = ratio+(1.0-ratio)*likedness;
1104 float greed =
map->shopgreed;
1108 return tanh(-greed+2.0)/2 + 0.5;
1112 double approval = 1.0;
1113 if (
map->shoprace) {
1141 uint64_t newval, unit_price;
1145 if (!isshop || !
who) {
1146 if (unit_price > 10000)
1147 newval = 8000+
isqrt(unit_price)*20;
1149 newval = unit_price;
1152 LOG(
llevError,
"value_limit: asked shop price for ob %s on NULL map\n",
who->name);
1156 if (
map->shopmin && unit_price < map->shopmin)
1158 else if (
map->shopmax && unit_price >
map->shopmax/2)
1160 else if (unit_price > 10000)
1161 newval = 8000+
isqrt(unit_price)*20;
1163 newval = unit_price;
1191 "From looking at the nearby shop you determine that it trades in:");
1193 if (
map->shopitems) {
1194 for (i = 0; i <
map->shopitems[0].index; i++) {
1195 if (
map->shopitems[i].name &&
map->shopitems[i].strength > 10) {
1196 snprintf(
tmp+pos,
sizeof(
tmp)-pos,
"%s, ",
map->shopitems[i].name_pl);
1197 pos += strlen(
tmp+pos);
1202 strcpy(
tmp,
"a little of everything.");
1213 "It won't trade for items above %s.",
1222 "It won't trade in items worth less than %s.",
1227 if (
map->shopgreed) {
1228 if (
map->shopgreed > 2.0)
1231 "It tends to overcharge massively.");
1232 else if (
map->shopgreed > 1.5)
1235 "It tends to overcharge substantially.");
1236 else if (
map->shopgreed > 1.1)
1239 "It tends to overcharge slightly.");
1240 else if (
map->shopgreed < 0.9)
1243 "It tends to undercharge.");
1245 if (
map->shoprace) {
1250 "You think the shopkeeper likes you.");
1251 else if (opinion > 0.5)
1254 "The shopkeeper seems unconcerned by you.");
1258 "The shopkeeper seems to have taken a dislike to you.");
1261 "There is no shop nearby.");
1277 if (!
ob->map)
return 0;
static uint64_t value_limit(uint64_t val, int quantity, const object *who, int isshop)
bool shop_contains(object *ob)
void object_remove(object *op)
StringBuffer * stringbuffer_new(void)
object * find_skill_by_number(object *who, int skillno)
#define QUERY_FLAG(xyz, p)
arch
DIALOGCHECK MINARGS 1 MAXARGS 1
#define SPECIALISATION_EFFECT
static double shop_greed(const mapstruct *map)
object * object_new(void)
static event_registration c
uint64_t price_approx(const object *tmp, object *who)
int shop_describe(const object *op)
static void add_value(object *coin_objs[], int64_t value)
static void count_unpaid(object *pl, object *item, int *unpaid_count, uint64_t *unpaid_price)
char * cost_approx_str(const object *tmp, object *who)
#define MSG_TYPE_SHOP_PAYMENT
int shop_pay_unpaid(object *pl, object *op)
void make_list_like(char *input)
#define MSG_TYPE_SHOP_MISC
int events_execute_object_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
uint64_t query_money(const object *op)
object * object_merge(object *op, object *top)
const char * object_get_value(const object *op, const char *const key)
object * identify(object *op)
static archetype * find_next_coin(uint64_t c, int *cointype)
static uint32_t NROF(const object *const ob)
void object_copy(const object *src_ob, object *dest_ob)
void query_name(const object *op, char *buf, size_t size)
static double shop_specialisation_ratio(const object *item, const mapstruct *map)
#define FOR_OB_AND_BELOW_FINISH()
void stringbuffer_append_string(StringBuffer *sb, const char *str)
static uint64_t compute_price_variation_with_bargaining(object *pl, uint64_t price, float max_variation)
uint64_t shop_price_sell(const object *tmp, object *who)
void fix_object(object *op)
char * stringbuffer_finish(StringBuffer *sb)
#define LARGEST_COIN_GIVEN
int rndm(int min, int max)
static void insert_objects(object *pl, object *container, object *objects[], int objects_len)
uint64_t price_base(const object *obj)
static uint64_t pay_from_container(object *pl, object *pouch, uint64_t to_pay)
#define FOR_OB_AND_BELOW_PREPARE(op_)
char * cost_string_from_value(uint64_t cost, int largest_coin)
uint64_t shop_price_buy(const object *tmp, object *who)
int pay_for_item(object *op, object *pl, uint64_t reduction)
#define FREE_AND_CLEAR_STR(xyz)
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
void sell_item(object *op, object *pl)
static float shop_cha_modifier(int charisma)
static StringBuffer * real_money_value(const object *coin, StringBuffer *buf)
#define MSG_TYPE_SHOP_SELL
void LOG(LogLevel logLevel, const char *format,...)
float shop_efficiency(const object *player)
archetype * find_archetype(const char *name)
void esrv_update_item(int flags, object *pl, object *op)
#define CLEAR_FLAG(xyz, p)
#define MSG_TYPE_SHOP_LISTING
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
void change_exp(object *op, int64_t exp, const char *skill_name, int flag)
object * object_insert_in_ob(object *op, object *where)
const typedata * get_typedata(int itemtype)
#define MAX_BUY_REDUCTION
double shop_approval(const mapstruct *map, const object *player)
static int64_t remove_value(object *coin_objs[], int64_t remain)
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
void object_free_drop_inventory(object *ob)
static bool coords_in_shop(mapstruct *map, int x, int y)
void stringbuffer_delete(StringBuffer *sb)
static const char *const coins[]
char * cost_str(uint64_t cost)
static void count_coins(object *item, uint32_t *coincount)
#define FOR_INV_PREPARE(op_, it_)
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
int pay_for_amount(uint64_t to_pay, object *pl)
int is_identified(const object *op)