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 53 static uint64_t
value_limit(uint64_t val,
int quantity,
const object *who,
int isshop);
59 #define LARGEST_COIN_GIVEN 2 62 static const char *const coins[] = { 101 val += val * (sin(tmp->
count) / sqrt(lev_identify * 3 + 1.0));
112 return tanh((charisma+15.0)/20);
133 return NROF(tmp)*strtol(price, NULL, 10);
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);
147 if (std::isfinite(adj_val)) {
164 const uint64_t adj_val = val * adj * spec * E;
167 int number =
NROF(tmp);
168 uint64_t limval =
value_limit(adj_val, number, who, 1);
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);
192 if (
coins[*cointype] == NULL)
223 int cointype = largest_coin;
231 if (cost == UINT64_MAX) {
252 cost -= (uint64_t)num*(uint64_t)coin->
clone.
value;
259 if (next_coin == NULL)
265 cost -= (uint64_t)num*(uint64_t)coin->
clone.
value;
377 LOG(
llevError,
"Query money called with non player/container\n");
381 if (tmp->type ==
MONEY) {
382 total += (uint64_t)tmp->nrof*(uint64_t)tmp->value;
418 LOG(
llevError,
"pay_for_amount: Cannot remove enough money -- %" FMT64U " remains\n", to_pay);
442 assert(to_pay >= reduction);
460 LOG(
llevError,
"pay_for_item: Cannot remove enough money -- %" FMT64U " remains\n", to_pay);
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) {
492 num_coins = coin_objs[i]->
nrof;
494 remain -= (int64_t)num_coins*(int64_t)coin_objs[i]->
value;
495 coin_objs[i]->
nrof -= num_coins;
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;
520 static void add_value(
object *coin_objs[], int64_t value) {
526 nrof = (uint32_t)(value/coin_objs[i]->value);
527 value -= nrof*coin_objs[i]->
value;
528 coin_objs[i]->
nrof += nrof;
547 for (i = 0; i < objects_len; i++) {
548 if (objects[i]->nrof > 0) {
576 object *other_money[16];
577 size_t other_money_len;
590 if (tmp->type ==
MONEY) {
592 if (!strcmp(
coins[NUM_COINS-1-i], tmp->arch->name)
593 && (tmp->value == tmp->arch->clone.value)) {
597 if (coin_objs[i] != NULL) {
600 coin_objs[i]->
nrof += tmp->nrof;
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);
614 other_money[other_money_len++] = tmp;
623 if (coin_objs[i] == NULL) {
630 coin_objs[i]->
nrof = 0;
637 for (i = 0; i < other_money_len && remain > 0; i++) {
641 coin = other_money[i];
647 if (nrof > coin->
nrof) {
664 if (a == UINT64_MAX) {
668 if (UINT64_MAX - a < b) {
689 static void unpaid_iter(
object *item,
void (*callback)(
object *item,
void *data),
void *data) {
692 callback(item, data);
719 struct unpaid_count args = {
pl, 0, 0};
721 *unpaid_count = args.
count;
722 *unpaid_price = args.
price;
740 coincount[i] += item->
nrof;
760 if (skill && skill->
level > 0) {
780 uint64_t unpaid_price = 0;
784 LOG(
llevError,
"can_pay(): called against something that isn't a player\n");
795 if (unpaid_price > player_wealth) {
797 int denominations = 0;
798 char *value =
cost_str(unpaid_price);
800 snprintf(buf,
sizeof(buf),
"You have %d unpaid items that would cost you %s, ", unpaid_count, value);
803 if (coincount[i] > 0 &&
coins[i]) {
804 if (denominations == 0)
805 snprintf(buf+strlen(buf),
sizeof(buf)-strlen(buf),
"but you only have");
810 snprintf(coinbuf,
sizeof(coinbuf),
" %u %s,", coincount[i], arch->
clone.
name_pl);
811 snprintf(buf+strlen(buf),
sizeof(buf)-strlen(buf),
"%s", coinbuf);
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)
827 object *
pl = (
object *)data;
830 uint64_t reduction = 0;
843 "You lack %s to buy %s.",
854 char *value =
cost_str(price - reduction);
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);
872 "You paid %s for %s.",
917 LOG(
llevDebug,
"Object other than player tried to sell something.\n");
930 "We're not interested in %s.",
937 char *value_str =
cost_str(price + extra_gain);
939 if (extra_gain > 0) {
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);
948 "You receive %s for %s.", value_str, obj_name);
965 price -= (uint64_t)tmp->
nrof*(uint64_t)tmp->
value;
976 price -= (uint64_t)tmp->
nrof*(uint64_t)tmp->
value;
984 LOG(
llevError,
"Warning - payment not zero: %" PRIo64
"\n", price);
1012 LOG(
llevError,
"shop_specialisation_ratio: passed a NULL item for map %s\n", map->
path);
1015 if (item->
type == (uint8_t)-1) {
1016 LOG(
llevError,
"shop_specialisation_ratio: passed an item with an invalid type\n");
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;
1029 if (likedness > 1.0) {
1030 LOG(
llevDebug,
"shop_specialisation ratio: item type %d on map %s is above 100%%\n", item->
type, map->
path);
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);
1037 ratio = ratio+(1.0-ratio)*likedness;
1062 return tanh(-greed+2.0)/2 + 0.5;
1066 double approval = 1.0;
1094 static uint64_t
value_limit(uint64_t val,
int quantity,
const object *who,
int isshop) {
1095 uint64_t newval, unit_price;
1098 unit_price = val/quantity;
1099 if (!isshop || !who) {
1100 if (unit_price > 10000)
1101 newval = 8000+
isqrt(unit_price)*20;
1103 newval = unit_price;
1106 LOG(
llevError,
"value_limit: asked shop price for ob %s on NULL map\n", who->
name);
1110 if (map->
shopmin && unit_price < map->shopmin)
1112 else if (unit_price > map->
shopmax/2)
1114 else if (unit_price > 10000)
1115 newval = 8000+
isqrt(unit_price)*20;
1117 newval = unit_price;
1133 char tmp[
MAX_BUF] =
"\0", *value;
1145 "From looking at the nearby shop you determine that it trades in:");
1151 pos += strlen(tmp+pos);
1156 strcpy(tmp,
"a little of everything.");
1167 "It won't trade for items above %s.",
1176 "It won't trade in items worth less than %s.",
1185 "It tends to overcharge massively.");
1189 "It tends to overcharge substantially.");
1193 "It tends to overcharge slightly.");
1197 "It tends to undercharge.");
1204 "You think the shopkeeper likes you.");
1205 else if (opinion > 0.5)
1208 "The shopkeeper seems unconcerned by you.");
1212 "The shopkeeper seems to have taken a dislike to you.");
1215 "There is no shop nearby.");
static event_registration c
int pay_for_amount(uint64_t to_pay, object *pl)
Takes the amount of money from the the player inventory and from it's various pouches using the pay_f...
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.
#define LARGEST_COIN_GIVEN
Never give amber or jade, but accept them.
#define FLAG_PLAYER_SOLD
Object was sold to a shop by a player.
int index
Being the size of the shopitems array.
#define FLAG_UNPAID
Object hasn't been paid for yet.
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.
static archetype * find_next_coin(uint64_t c, int *cointype)
Find the coin type that is worth more than 'c'.
char * cost_str(uint64_t cost)
#define MSG_TYPE_SHOP_LISTING
Shop listings - inventory, what it deals in.
struct archetype * arch
Pointer to archetype.
uint64_t shopmax
MMaximum price a shop will offer.
#define MSG_TYPE_SHOP_SELL
Messages about selling items.
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
uint64_t price_approx(const object *tmp, object *who)
Adjust the value of the given item based on the player's skills.
int rndm(int min, int max)
Returns a number between min and max.
int identifyskill
Skill used to identify this object class.
const typedata * get_typedata(int itemtype)
static float shop_cha_modifier(int charisma)
Calculate the buy price multiplier based on a player's charisma.
#define NEUTRAL_RATIO
Price a shopkeeper will give someone they neither like nor dislike.
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)
void fix_object(object *op)
Updates all abilities given by applied objects in the inventory of the given object.
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to...
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...
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...
int16_t max_level
This is read out of exp_table.
int8_t strength
The degree of specialisation the shop has in this item, as a percentage from -100 to 100...
#define MSG_TYPE_SHOP_PAYMENT
Messages about payment, lack of funds.
void esrv_update_item(int flags, object *pl, object *op)
Updates object *op for player *pl.
static void unpaid_iter(object *item, void(*callback)(object *item, void *data), void *data)
Search for unpaid items in 'item' and call 'callback' on each item.
static uint32_t NROF(const object *const ob)
Returns ob->nrof, unless it is 0, in which case return 1.
int32_t value
How much money it is worth (or contains)
void sell_item(object *op, object *pl)
Player is selling an item.
#define EVENT_SELLING
Object is being sold by another one.
void change_exp(object *op, int64_t exp, const char *skill_name, int flag)
Changes experience to a player/monster.
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.
#define NUM_COINS
Number of coin types.
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...
#define MAX_SELL_EXTRA
Maximum price increase when selling an item with bargaining skill.
Global type definitions and header inclusions.
Link an object type with skill needed to identify, and general name.
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).
#define SPECIALISATION_EFFECT
This is a measure of how effective store specialisation is.
#define FOR_OB_AND_BELOW_FINISH()
Finishes FOR_OB_AND_BELOW_PREPARE().
void events_execute_global_event(int eventcode,...)
Execute a global event.
static const char *const coins[]
Coins to use for shopping.
#define MAX_BUY_REDUCTION
Maximum price reduction when buying an item with bargaining skill.
static void insert_objects(object *pl, object *container, object *objects[], int objects_len)
Insert a list of objects into a player object.
int shop_pay_unpaid(object *pl, object *op)
Pay as many unpaid items as possible, recursing on op->inv and op->below.
int16_t level
Level of creature or object.
uint64_t add_with_overflow(uint64_t a, uint64_t b)
static StringBuffer * real_money_value(const object *coin, StringBuffer *buf)
Returns a string representing the money's value, in plain coins.
static void shop_pay_unpaid_callback(object *op, void *data)
object * identify(object *op)
Identifies an item.
The archetype structure is a set of rules on how to generate and manipulate objects which point to ar...
sstring name
More definite name, like "generate_kobold".
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.
char path[HUGE_BUF]
Filename of the map.
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Append a string to a string buffer instance.
#define QUERY_FLAG(xyz, p)
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.
double shopgreed
How much our shopkeeper overcharges.
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.
uint64_t shop_price_buy(const object *tmp, object *who)
Adjust the value of an item to be bought based on the player's bargaining skill and charisma...
void query_name(const object *op, char *buf, size_t size)
Describes an item.
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.
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
#define MSG_TYPE_SHOP_MISC
Random messages.
sstring race
Human, goblin, dragon, etc.
sstring object_get_value(const object *op, const char *const key)
Get an extra value by key.
int typenum
Itemtype number we need to match, -1 if it is the default price.
uint64_t shopmin
Minimum price a shop will trade for.
uint8_t real_wiz
Use mud-like wizards.
uint64_t shop_price_sell(const object *tmp, object *who)
Adjust the value of an item to be sold based on the player's bargaining skill and charisma...
struct Settings settings
Global settings.
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's specialisation...
object * object_new(void)
Grabs an object from the list of unused objects, makes sure it is initialised, and returns it...
static double shop_greed(const mapstruct *map)
Gets a shop's greed.
static int64_t remove_value(object *coin_objs[], int64_t remain)
This function removes a given amount from a list of coins.
int isqrt(int n)
Compute the square root.
living stats
Str, Con, Dex, etc.
#define MAX_BUF
Used for all kinds of things.
char * cost_string_from_value(uint64_t cost, int largest_coin)
Converts a price to number of coins.
char * shoprace
The preffered race of the local shopkeeper.
uint64_t price_base(const object *obj)
Price an item based on its value or archetype value, type, identification/BUC status, and other heuristics.
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...
struct mapstruct * map
Pointer to the map in which this object is present.
#define EVENT_BOUGHT
Object is being bought by player.
#define EVENT_GSOLD
Player sold object in shop, but global.
int identifyskill2
Second skill used to identify this object class.
const char * name_pl
Plural name.
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...
sstring name_pl
The plural name of the object.
static void count_unpaid_callback(object *item, void *data)
sstring name
The name of the object, obviously...
const char * name
Name of the item in question, null if it is the default item.
Only for debugging purposes.
uint32_t nrof
Number of objects.
#define SK_EXP_NONE
Player gets nothing.
#define CLEAR_FLAG(xyz, p)
uint8_t type
PLAYER, BULLET, etc.
#define FLAG_APPLIED
Object is ready for use by living.
void stringbuffer_delete(StringBuffer *sb)
Totally delete a string buffer.
Shop-related information for a map.
int object_set_value(object *op, const char *key, const char *value, int add_key)
Updates the key in op to value.
object * inv
Pointer to the first object in the inventory.
#define FOR_OB_AND_BELOW_PREPARE(op_)
Constructs a loop iterating over an object and all objects below it in the same pile.
object * objects
Pointer to the list of used objects.
char * cost_approx_str(const object *tmp, object *who)
Return a textual cost approximation in a newly-allocated string.
float shop_efficiency(const object *player)
Return the shop's efficiency (E) for a player, a number greater than (but not equal to) zero and less...
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.
#define NDI_UNIQUE
Print immediately, don't buffer.
double shop_approval(const mapstruct *map, const object *player)
Return the approval ratio for a shop for a given player.
#define FLAG_WAS_WIZ
Player was once a wiz.
void make_list_like(char *input)
Taking a string as an argument, mutate it into a string that looks like a list.
A buffer that will be expanded as content is added to it.
struct shopitems * shopitems
List of item-types the map's shop will trade in.
object * find_skill_by_number(object *who, int skillno)
This returns the first skill pointer of the given subtype (the one that accumulates exp...
object * object_insert_in_ob(object *op, object *where)
This function inserts the object op in the linked list inside the object environment.
tag_t count
Unique object number for this object.
static void add_value(object *coin_objs[], int64_t value)
This function adds a given amount to a list of coins.
object clone
An object from which to do object_copy()
bool object_value_set(const object *op, const char *const key)
Determine if an extra value is set.
#define CUSTOM_NAME_FIELD
Key in an object for the player-assigned custom name.
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
#define EVENT_GBOUGHT
Player bought object in shop, but global.
int can_pay(object *pl)
Checks all unpaid items in op's inventory, adds up all the money they have, and checks that they can ...