39 #define SPECIALISATION_EFFECT 0.5 42 #define DISAPPROVAL_RATIO 0.2 45 #define NEUTRAL_RATIO 0.8 54 #define LARGEST_COIN_GIVEN 2 57 static const char *const coins[] = { 72 const int number =
NROF(obj);
79 float ratio = atof(key);
89 if (!identified && obj->
arch) {
108 if (obj->
arch != NULL && identified) {
110 val *= pow(1.15, diff);
142 int lev_identify = 0;
158 val += val * (sin(tmp->
count) / sqrt(lev_identify * 3 + 1.0));
170 float multiplier = 1 / (0.38 * pow(1.06, charisma));
172 if (multiplier > 2) {
174 }
else if (multiplier < 0.5) {
198 float ratio = atof(key);
211 int bargain_level = 0;
220 val *= multiplier > 0.5 ? multiplier : 0.5;
256 float ratio = atof(key);
266 if (tmp->
arch != NULL) {
283 int number =
NROF(tmp);
306 if (
coins[*cointype] == NULL)
337 int cointype = largest_coin;
368 if (next_coin == NULL)
486 LOG(
llevError,
"Query money called with non player/container\n");
490 if (tmp->type ==
MONEY) {
494 && (tmp->race == NULL || strstr(tmp->race,
"gold"))) {
526 && (pouch->race == NULL || strstr(pouch->race,
"gold"))) {
531 LOG(
llevError,
"pay_for_amount: Cannot remove enough money -- %"FMT64U" remains\n", to_pay);
574 && (pouch->race == NULL || strstr(pouch->race,
"gold"))) {
579 LOG(
llevError,
"pay_for_item: Cannot remove enough money -- %"FMT64U" remains\n", to_pay);
605 if ((
int64_t)coin_objs[i]->nrof * coin_objs[i]->value > remain) {
606 num_coins = remain/coin_objs[i]->
value;
611 num_coins = coin_objs[i]->
nrof;
614 coin_objs[i]->
nrof -= num_coins;
620 while (remain < 0 && count >= 0) {
621 num_coins = -remain/coin_objs[count]->
value;
622 coin_objs[count]->
nrof += num_coins;
623 remain += num_coins*coin_objs[count]->
value;
645 nrof = (
uint32_t)(value/coin_objs[i]->value);
646 value -= nrof*coin_objs[i]->
value;
647 coin_objs[i]->
nrof += nrof;
666 for (i = 0; i < objects_len; i++) {
667 if (objects[i]->nrof > 0) {
695 object *other_money[16];
696 size_t other_money_len;
709 if (tmp->type ==
MONEY) {
711 if (!strcmp(
coins[NUM_COINS-1-i], tmp->arch->name)
712 && (tmp->value == tmp->arch->clone.value)) {
716 if (coin_objs[i] != NULL) {
719 coin_objs[i]->
nrof += tmp->nrof;
728 if (i == NUM_COINS) {
729 if (other_money_len >=
sizeof(other_money)/
sizeof(*other_money)) {
730 LOG(
llevError,
"pay_for_item: Cannot store non-standard money object %s\n", tmp->arch->name);
733 other_money[other_money_len++] = tmp;
742 if (coin_objs[i] == NULL) {
749 coin_objs[i]->
nrof = 0;
756 for (i = 0; i < other_money_len && remain > 0; i++) {
760 coin = other_money[i];
766 if (nrof > coin->
nrof) {
810 coincount[i] += item->
nrof;
831 int unpaid_count = 0, i;
837 LOG(
llevError,
"can_pay(): called against something that isn't a player\n");
846 if (unpaid_price > player_wealth) {
848 int denominations = 0;
849 char *value =
cost_str(unpaid_price);
851 snprintf(buf,
sizeof(buf),
"You have %d unpaid items that would cost you %s, ", unpaid_count, value);
854 if (coincount[i] > 0 &&
coins[i]) {
855 if (denominations == 0)
856 snprintf(buf+strlen(buf),
sizeof(buf)-strlen(buf),
"but you only have");
862 snprintf(buf+strlen(buf),
sizeof(buf)-strlen(buf),
"%s", coinbuf);
866 if (denominations == 0)
867 snprintf(buf+strlen(buf),
sizeof(buf)-strlen(buf),
"but you don't have any money.");
868 else if (denominations > 1)
887 if (op != NULL && op->
inv)
893 if (op != NULL && op->
below)
909 "You lack %s to buy %s.",
927 "You paid %s for %s.",
959 LOG(
llevDebug,
"Object other than player tried to sell something.\n");
973 "We're not interested in %s.",
984 if (extra_gain > 0) {
990 "You receive %s for %s.", value_str, obj_name);
1002 && strstr(pouch->race,
"gold")) {
1003 int w = at->
clone.
weight*(100-pouch->stats.Str)/100;
1009 && (!pouch->weight_limit || pouch->carrying+w <= pouch->weight_limit)) {
1010 if (pouch->weight_limit
1011 && (pouch->weight_limit-pouch->carrying)/w < n)
1012 n = (pouch->weight_limit-pouch->carrying)/w;
1035 LOG(
llevError,
"Warning - payment not zero: %" PRIo64
"\n", price);
1061 LOG(
llevError,
"shop_specialisation_ratio: passed a NULL item for map %s\n", map->
path);
1065 LOG(
llevError,
"shop_specialisation_ratio: passed an item with an invalid type\n");
1074 for (i = 0; i < items[0].
index; i++)
1075 if (items[i].typenum == item->
type || (items[i].
typenum == -1 && likedness == 0.001))
1076 likedness = items[i].
strength/100.0;
1078 if (likedness > 1.0) {
1079 LOG(
llevDebug,
"shop_specialisation ratio: item type %d on map %s is above 100%%\n", item->
type, map->
path);
1082 if (likedness < -1.0) {
1083 LOG(
llevDebug,
"shop_specialisation ratio: item type %d on map %s is below -100%%\n", item->
type, map->
path);
1086 ratio = ratio+(1.0-ratio)*likedness;
1109 double approval = 1.0;
1142 unit_price = val/quantity;
1143 if (!isshop || !who) {
1144 if (unit_price > 10000)
1145 newval = 8000+
isqrt(unit_price)*20;
1147 newval = unit_price;
1150 LOG(
llevError,
"value_limit: asked shop price for ob %s on NULL map\n", who->
name);
1154 if (map->
shopmin && unit_price < map->shopmin)
1158 else if (unit_price > 10000)
1159 newval = 8000+
isqrt(unit_price)*20;
1161 newval = unit_price;
1177 char tmp[
MAX_BUF] =
"\0", *value;
1189 "From looking at the nearby shop you determine that it trades in:");
1195 pos += strlen(tmp+pos);
1200 strcpy(tmp,
"a little of everything.");
1211 "It won't trade for items above %s.",
1220 "It won't trade in items worth less than %s.",
1229 "It tends to overcharge massively.");
1233 "It tends to overcharge substantially.");
1237 "It tends to overcharge slightly.");
1241 "It tends to undercharge.");
1248 "You think the shopkeeper likes you.");
1249 else if (opinion > 0.5)
1252 "The shopkeeper seems unconcerned by you.");
1256 "The shopkeeper seems to have taken a dislike to you.");
1259 "There is no shop nearby.");
1275 if (!ob->
map)
return 0;
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
archetype * find_archetype(const char *name)
#define MSG_TYPE_SHOP_LISTING
static archetype * find_next_coin(uint64_t c, int *cointype)
static const char *const coins[]
uint64_t query_money(const object *op)
static StringBuffer * real_money_value(const object *coin, StringBuffer *buf)
uint64_t shop_price_sell(const object *tmp, object *who)
#define MSG_TYPE_SHOP_SELL
static bool coords_in_shop(mapstruct *map, int x, int y)
StringBuffer * stringbuffer_new(void)
static double shop_specialisation_ratio(const object *item, const mapstruct *map)
#define MSG_TYPE_SHOP_PAYMENT
void esrv_update_item(int flags, object *pl, object *op)
const char * object_get_value(const object *op, const char *const key)
static uint64_t value_limit(uint64_t val, int quantity, const object *who, int isshop)
static uint32_t NROF(const object *const ob)
double shop_approval(const mapstruct *map, const object *player)
uint64_t shop_price_buy(const object *tmp, object *who)
bool shop_contains(object *ob)
static void count_unpaid(object *pl, object *item, int *unpaid_count, uint64_t *unpaid_price, uint32_t *coincount)
static void insert_objects(object *pl, object *container, object *objects[], int objects_len)
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
#define FOR_OB_AND_BELOW_FINISH()
uint64_t price_approx(const object *tmp, object *who)
const typedata * get_typedata(int itemtype)
static void add_value(object *coin_objs[], int64_t value)
void make_list_like(char *input)
void object_free_drop_inventory(object *ob)
int pay_for_item(object *op, object *pl)
int is_identified(const object *op)
static int64_t remove_value(object *coin_objs[], int64_t remain)
object * object_new(void)
void stringbuffer_append_string(StringBuffer *sb, const char *str)
object * object_insert_in_ob(object *op, object *where)
char * cost_string_from_value(uint64_t cost, int largest_coin)
#define MSG_TYPE_SHOP_MISC
char * cost_approx_str(const object *tmp, object *who)
static double shop_greed(const mapstruct *map)
int pay_for_amount(uint64_t to_pay, object *pl)
#define FREE_AND_CLEAR_STR(xyz)
unsigned __int64 uint64_t
#define QUERY_FLAG(xyz, p)
#define CLEAR_FLAG(xyz, p)
void change_exp(object *op, int64_t exp, const char *skill_name, int flag)
#define FLAG_BEEN_APPLIED
int shop_pay_unpaid(object *pl, object *op)
static uint64_t pay_from_container(object *pl, object *pouch, uint64_t to_pay)
static float shop_buy_multiplier(int charisma)
#define LARGEST_COIN_GIVEN
void stringbuffer_delete(StringBuffer *sb)
char * cost_str(uint64_t cost)
void sell_item(object *op, object *pl)
object * object_merge(object *op, object *top)
int execute_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
#define FOR_OB_AND_BELOW_PREPARE(op_)
#define SPECIALISATION_EFFECT
object * identify(object *op)
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
static float shop_bargain_multiplier(int lev_bargain)
void object_copy(const object *src_ob, object *dest_ob)
void LOG(LogLevel logLevel, const char *format,...)
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
struct shopitem * shopitems
void query_name(const object *op, char *buf, size_t size)
object * find_skill_by_number(object *who, int skillno)
int shop_describe(const object *op)
uint64_t price_base(const object *obj)
void fix_object(object *op)
char * stringbuffer_finish(StringBuffer *sb)
#define FOR_INV_PREPARE(op_, it_)
void object_remove(object *op)