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);
94 if (!identified &&
obj->arch) {
95 val =
obj->arch->clone.value * number;
113 if (
obj->arch != NULL && identified) {
114 int diff =
obj->magic -
obj->arch->clone.magic;
115 val *= pow(1.15, diff);
120 val *=
obj->stats.food / 50.0;
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 %lu*adj(%.2f)/E(%.2f) = %.2f\n",
202 tmp->arch->name, val, adj, E, adj_val);
204 if (std::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 %lu*adj(%.2f)*s(%.2f)*E(%.2f) = %lu limited to %lu\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];
727 if (
a == UINT64_MAX) {
731 if (UINT64_MAX -
a <
b) {
785 *unpaid_price =
args.price;
802 if (!strcmp(
coins[i],
item->arch->name)) {
803 coincount[i] +=
item->nrof;
843 uint64_t unpaid_price = 0;
847 LOG(
llevError,
"can_pay(): called against something that isn't a player\n");
858 if (unpaid_price > player_wealth) {
860 int denominations = 0;
866 if (coincount[i] > 0 &&
coins[i]) {
867 if (denominations == 0)
868 snprintf(
buf+strlen(
buf),
sizeof(
buf)-strlen(
buf),
"but you only have");
873 snprintf(coinbuf,
sizeof(coinbuf),
" %u %s,", coincount[i],
arch->clone.name_pl);
874 snprintf(
buf+strlen(
buf),
sizeof(
buf)-strlen(
buf),
"%s", coinbuf);
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)
890 object *
pl = (
object *)
data;
902 "You lack %s to buy %s.",
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);
929 "You paid %s for %s.",
974 LOG(
llevDebug,
"Object other than player tried to sell something.\n");
987 "We're not interested in %s.",
995 if (extra_gain > 0) {
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);
1001 price += extra_gain;
1004 "You receive %s for %s.", value_str, obj_name);
1017 && strstr(pouch->race,
"gold")) {
1018 int w = at->
clone.
weight*(100-pouch->stats.Str)/100;
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;
1032 price -= (uint64_t)
tmp->nrof*(uint64_t)
tmp->value;
1042 price -= (uint64_t)
tmp->nrof*(uint64_t)
tmp->value;
1078 LOG(
llevError,
"shop_specialisation_ratio: passed a NULL item for map %s\n",
map->path);
1081 if (
item->type == (uint8_t)-1) {
1082 LOG(
llevError,
"shop_specialisation_ratio: passed an item with an invalid type\n");
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;
1095 if (likedness > 1.0) {
1096 LOG(
llevDebug,
"shop_specialisation ratio: item type %d on map %s is above 100%%\n",
item->type,
map->path);
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);
1103 ratio = ratio+(1.0-ratio)*likedness;
1124 float greed =
map->shopgreed;
1128 return tanh(-greed+2.0)/2 + 0.5;
1132 double approval = 1.0;
1133 if (
map->shoprace) {
1161 uint64_t newval, unit_price;
1165 if (!isshop || !
who) {
1166 if (unit_price > 10000)
1167 newval = 8000+
isqrt(unit_price)*20;
1169 newval = unit_price;
1172 LOG(
llevError,
"value_limit: asked shop price for ob %s on NULL map\n",
who->name);
1176 if (
map->shopmin && unit_price < map->shopmin)
1178 else if (
map->shopmax && unit_price >
map->shopmax/2)
1180 else if (unit_price > 10000)
1181 newval = 8000+
isqrt(unit_price)*20;
1183 newval = unit_price;
1211 "From looking at the nearby shop you determine that it trades in:");
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);
1222 strcpy(
tmp,
"a little of everything.");
1233 "It won't trade for items above %s.",
1242 "It won't trade in items worth less than %s.",
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.");
1265 if (
map->shoprace) {
1270 "You think the shopkeeper likes you.");
1271 else if (opinion > 0.5)
1274 "The shopkeeper seems unconcerned by you.");
1278 "The shopkeeper seems to have taken a dislike to you.");
1281 "There is no shop nearby.");
1297 if (!
ob->map)
return 0;
char * cost_approx_str(const object *tmp, object *who)
double shop_approval(const mapstruct *map, const object *player)
void sell_item(object *op, object *pl)
static float shop_cha_modifier(int charisma)
object * find_skill_by_number(object *who, int skillno)
void LOG(LogLevel logLevel, const char *format,...)
#define LARGEST_COIN_GIVEN
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
#define QUERY_FLAG(xyz, p)
arch
DIALOGCHECK MINARGS 1 MAXARGS 1
static uint64_t compute_price_variation_with_bargaining(object *pl, uint64_t price, float max_variation)
static void unpaid_iter(object *item, void(*callback)(object *item, void *data), void *data)
object * object_merge(object *op, object *top)
char * cost_str(uint64_t cost)
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
static archetype * find_next_coin(uint64_t c, int *cointype)
static void add_value(object *coin_objs[], int64_t value)
static event_registration c
#define SPECIALISATION_EFFECT
StringBuffer * stringbuffer_new(void)
static bool coords_in_shop(mapstruct *map, int x, int y)
uint64_t price_approx(const object *tmp, object *who)
static void insert_objects(object *pl, object *container, object *objects[], int objects_len)
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
void object_copy(const object *src_ob, object *dest_ob)
void fix_object(object *op)
static void shop_pay_unpaid_callback(object *op, void *data)
#define MSG_TYPE_SHOP_PAYMENT
static const char *const coins[]
const char * object_get_value(const object *op, const char *const key)
#define MSG_TYPE_SHOP_MISC
int events_execute_object_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
object * object_insert_in_ob(object *op, object *where)
int pay_for_item(object *op, object *pl, uint64_t reduction)
static StringBuffer * real_money_value(const object *coin, StringBuffer *buf)
char * stringbuffer_finish(StringBuffer *sb)
void object_free_drop_inventory(object *ob)
static uint32_t NROF(const object *const ob)
const typedata * get_typedata(int itemtype)
uint64_t shop_price_sell(const object *tmp, object *who)
void query_name(const object *op, char *buf, size_t size)
int shop_pay_unpaid(object *pl, object *op)
uint64_t query_money(const object *op)
static double shop_specialisation_ratio(const object *item, const mapstruct *map)
#define FOR_OB_AND_BELOW_FINISH()
int is_identified(const object *op)
char * cost_string_from_value(uint64_t cost, int largest_coin)
#define MAX_BUY_REDUCTION
void change_exp(object *op, int64_t exp, const char *skill_name, int flag)
uint64_t add_with_overflow(uint64_t a, uint64_t b)
void stringbuffer_append_string(StringBuffer *sb, const char *str)
#define FOR_OB_AND_BELOW_PREPARE(op_)
int shop_describe(const object *op)
object * object_new(void)
static uint64_t value_limit(uint64_t val, int quantity, const object *who, int isshop)
static void count_coins(object *item, uint32_t *coincount)
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
uint64_t shop_price_buy(const object *tmp, object *who)
#define MSG_TYPE_SHOP_SELL
bool shop_contains(object *ob)
void stringbuffer_delete(StringBuffer *sb)
static int64_t remove_value(object *coin_objs[], int64_t remain)
uint64_t price_base(const object *obj)
Magical Runes Runes are magical inscriptions on the dungeon floor
archetype * find_archetype(const char *name)
void esrv_update_item(int flags, object *pl, object *op)
#define CLEAR_FLAG(xyz, p)
float shop_efficiency(const object *player)
#define MSG_TYPE_SHOP_LISTING
static double shop_greed(const mapstruct *map)
static void count_unpaid_callback(object *item, void *data)
void object_remove(object *op)
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
int rndm(int min, int max)
int object_set_value(object *op, const char *key, const char *value, int add_key)
void make_list_like(char *input)
int pay_for_amount(uint64_t to_pay, object *pl)
#define CUSTOM_NAME_FIELD
static void count_unpaid(object *pl, object *item, int *unpaid_count, uint64_t *unpaid_price)
#define FOR_INV_PREPARE(op_, it_)
static uint64_t pay_from_container(object *pl, object *pouch, uint64_t to_pay)
object * identify(object *op)