Crossfire Server, Trunk
|
#include "global.h"
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "shop.h"
#include "sproto.h"
Go to the source code of this file.
Macros | |
#define | DISAPPROVAL_RATIO 0.2 |
#define | LARGEST_COIN_GIVEN 2 |
#define | MAX_BUY_REDUCTION 0.1f |
#define | MAX_SELL_EXTRA 0.1f |
#define | NEUTRAL_RATIO 0.8 |
#define | NUM_COINS 5 |
#define | SPECIALISATION_EFFECT 0.5 |
Functions | |
static void | add_value (object *coin_objs[], int64_t value) |
int | can_pay (object *pl) |
static uint64_t | compute_price_variation_with_bargaining (object *pl, uint64_t price, float max_variation) |
static bool | coords_in_shop (mapstruct *map, int x, int y) |
char * | cost_approx_str (const object *tmp, object *who) |
char * | cost_str (uint64_t cost) |
char * | cost_string_from_value (uint64_t cost, int largest_coin) |
static void | count_coins (object *item, uint32_t *coincount) |
static void | count_unpaid (object *pl, object *item, int *unpaid_count, uint64_t *unpaid_price) |
static archetype * | find_next_coin (uint64_t c, int *cointype) |
static void | insert_objects (object *pl, object *container, object *objects[], int objects_len) |
int | pay_for_amount (uint64_t to_pay, object *pl) |
int | pay_for_item (object *op, object *pl, uint64_t reduction) |
static uint64_t | pay_from_container (object *pl, object *pouch, uint64_t to_pay) |
uint64_t | price_approx (const object *tmp, object *who) |
uint64_t | price_base (const object *obj) |
uint64_t | query_money (const object *op) |
static StringBuffer * | real_money_value (const object *coin, StringBuffer *buf) |
static int64_t | remove_value (object *coin_objs[], int64_t remain) |
void | sell_item (object *op, object *pl) |
double | shop_approval (const mapstruct *map, const object *player) |
static float | shop_cha_modifier (int charisma) |
bool | shop_contains (object *ob) |
int | shop_describe (const object *op) |
float | shop_efficiency (const object *player) |
static double | shop_greed (const mapstruct *map) |
int | shop_pay_unpaid (object *pl, object *op) |
uint64_t | shop_price_buy (const object *tmp, object *who) |
uint64_t | shop_price_sell (const object *tmp, object *who) |
static double | shop_specialisation_ratio (const object *item, const mapstruct *map) |
static uint64_t | value_limit (uint64_t val, int quantity, const object *who, int isshop) |
Variables | |
static const char *const | coins [] |
Those functions deal with shop handling, bargaining, things like that.
Definition in file shop.c.
#define DISAPPROVAL_RATIO 0.2 |
#define LARGEST_COIN_GIVEN 2 |
#define MAX_BUY_REDUCTION 0.1f |
#define MAX_SELL_EXTRA 0.1f |
#define NEUTRAL_RATIO 0.8 |
#define SPECIALISATION_EFFECT 0.5 |
This is a measure of how effective store specialisation is. A general store will offer this proportion of the 'maximum' price, a specialised store will offer a range of prices around it such that the maximum price is always one therefore making this number higher, makes specialisation less effective. setting this value above 1 or to a negative value would have interesting, (though not useful) effects.
|
static |
This function adds a given amount to a list of coins.
coin_objs | the list coins to add to; the list must be ordered from least to most valuable coin |
value | the value (in silver coins) to add |
Definition at line 583 of file shop.c.
References LARGEST_COIN_GIVEN, obj::nrof, NUM_COINS, autojail::value, and obj::value.
Referenced by pay_from_container().
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 actually afford what they want to buy. Prints appropriate messages to the player.
pl | player trying to bug. |
1 | player could buy the items. |
0 | some items can't be bought. |
Definition at line 811 of file shop.c.
References archininventory::arch, buf, coins, cost_str(), count_coins(), count_unpaid(), draw_ext_info(), find_archetype(), llevError, LOG(), make_list_like(), MAX_BUF, MSG_TYPE_SHOP, MSG_TYPE_SHOP_PAYMENT, NDI_UNIQUE, NUM_COINS, PLAYER, query_money(), and autojail::value.
Referenced by cfapi_player_can_pay(), and shop_mat_type_move_on().
|
static |
Compute a percent of the price which will be used as extra or reduction. This will be 0 if the player doesn't have the bargaining skill.
pl | player to compute for. |
price | base price. |
max_variation | maximum variation, 1 means 100%. |
Definition at line 791 of file shop.c.
References find_skill_by_number(), obj::level, Settings::max_level, say::price, rndm(), settings, and SK_BARGAINING.
Referenced by sell_item(), and shop_pay_unpaid().
|
static |
Check if the given map coordinates are in a shop.
Definition at line 1269 of file shop.c.
References FOR_MAP_FINISH, FOR_MAP_PREPARE, disinfect::map, SHOP_FLOOR, diamondslots::x, and diamondslots::y.
Referenced by shop_contains().
Return a textual cost approximation in a newly-allocated string.
obj | item to query the price of, must not be NULL. |
who | player asking for the price, must not be NULL. |
Definition at line 369 of file shop.c.
References buf, archt::clone, diamondslots::cointype, cost_str(), find_next_coin(), find_skill_by_number(), get_typedata(), typedata::identifyskill, typedata::identifyskill2, LARGEST_COIN_GIVEN, MONEY, obj::name, obj::name_pl, price_approx(), real_money_value(), SK_BARGAINING, stringbuffer_append_printf(), stringbuffer_append_string(), stringbuffer_delete(), stringbuffer_finish(), stringbuffer_new(), Ice::tmp, obj::value, and autojail::who.
Referenced by examine().
char* cost_str | ( | uint64_t | cost | ) |
Definition at line 365 of file shop.c.
References diamondslots::cost, cost_string_from_value(), and LARGEST_COIN_GIVEN.
Referenced by can_pay(), cost_approx_str(), examine(), pick_up_object(), sell_item(), shop_describe(), and shop_pay_unpaid().
char* cost_string_from_value | ( | uint64_t | cost, |
int | largest_coin | ||
) |
Converts a price to number of coins.
While cost is 64 bit, the number of any coin is still really limited to 32 bit (size of nrof field). If it turns out players have so much money that they have more than 2 billion platinum coins, there are certainly issues - the easiest fix at that time is to add a higher denomination (mithril piece with 10,000 silver or something)
cost | value to transform to currency. |
largest_coin | maximum coin to give the price into, should be between 0 and NUM_COINS - 1. |
Definition at line 277 of file shop.c.
References buf, archt::clone, diamondslots::cointype, diamondslots::cost, done, find_next_coin(), obj::name, NUM_COINS, stringbuffer_append_printf(), stringbuffer_append_string(), stringbuffer_finish(), stringbuffer_new(), UINT32_MAX, and obj::value.
Referenced by cfapi_cost_string_from_value(), and cost_str().
|
static |
Count the number of coins for each type, for all items below item and in inventory.
item | item to get the money from. |
coincount | array of NUM_COINS size, will contain how many coins of the type the player has. |
Definition at line 765 of file shop.c.
References coins, FOR_OB_AND_BELOW_FINISH, FOR_OB_AND_BELOW_PREPARE, and NUM_COINS.
Referenced by can_pay().
|
static |
Sum the amount to pay for all unpaid items and find available money.
pl | player we're checking for, used for buying price with bargaining. | |
item | item to check for. | |
[out] | unpaid_count | how many unpaid items are left. |
[out] | unpaid_price | total price unpaid. |
Definition at line 738 of file shop.c.
References FLAG_UNPAID, FOR_OB_AND_BELOW_FINISH, FOR_OB_AND_BELOW_PREPARE, say::price, QUERY_FLAG, and shop_price_buy().
Referenced by can_pay().
|
static |
Find the coin type that is worth more than 'c'. Starts at the cointype placement.
c | value we're searching. |
cointype | first coin type to search. |
Definition at line 245 of file shop.c.
References c, archt::clone, coins, diamondslots::cointype, find_archetype(), and obj::value.
Referenced by cost_approx_str(), and cost_string_from_value().
|
static |
Insert a list of objects into a player object.
pl | the player to add to |
container | the container (inside the player object) to add to |
objects | the list of objects to add; the objects will be either inserted into the player object or freed |
objects_len | the length of objects |
Definition at line 607 of file shop.c.
References esrv_update_item(), object_free_drop_inventory(), object_insert_in_ob(), objects, and UPD_WEIGHT.
Referenced by pay_from_container().
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_from_container() function.
to_pay | amount to pay. |
pl | player paying. |
Definition at line 461 of file shop.c.
References CONTAINER, fix_object(), FLAG_APPLIED, FMT64U, FOR_INV_FINISH, FOR_INV_PREPARE, llevError, LOG(), pay_from_container(), QUERY_FLAG, and query_money().
Referenced by cfapi_object_pay_amount().
Player attemps to buy an item, if she has enough money then remove coins as needed from active containers. Also handles bargaining experience.
op | object to buy. |
pl | player buying. |
reduction | positive or null price reduction, must be below the price of the item. |
Definition at line 501 of file shop.c.
References CONTAINER, FALSE, fix_object(), FLAG_APPLIED, FLAG_WAS_WIZ, FMT64U, FOR_INV_FINISH, FOR_INV_PREPARE, llevError, LOG(), give::op, pay_from_container(), QUERY_FLAG, query_money(), Settings::real_wiz, SET_FLAG, settings, and shop_price_buy().
Referenced by cfapi_object_pay_item(), and shop_pay_unpaid().
This pays for the item, and takes the proper amount of money off the specified container (pouch or player), without recursing opened containers.
pl | player paying. |
pouch | container (pouch or player) to remove the coins from. |
to_pay | required amount. |
Definition at line 635 of file shop.c.
References add_value(), archt::clone, coins, CONTAINER, find_archetype(), FOR_INV_FINISH, FOR_INV_PREPARE, if(), insert_objects(), llevError, LOG(), MONEY, obj::name, obj::nrof, NUM_COINS, object_copy(), object_free_drop_inventory(), object_new(), object_remove(), PLAYER, remove_value(), Ice::tmp, obj::type, and obj::value.
Referenced by pay_for_amount(), and pay_for_item().
Adjust the value of the given item based on the player's skills. This function should only be used when calculating "you reckon" prices.
obj | item in question. Must not be NULL. |
who | player trying to judge the value of the item. Must not be NULL. |
Definition at line 133 of file shop.c.
References find_skill_by_number(), get_typedata(), typedata::identifyskill, typedata::identifyskill2, obj::level, llevError, LOG(), price_base(), Ice::tmp, and autojail::who.
Referenced by cost_approx_str().
uint64_t price_base | ( | const object * | obj | ) |
Price an item based on its value or archetype value, type, identification/BUC status, and other heuristics.
Shopkeepers always know the BUC status of items. Adjust the base price of items based on their BUC status. Note that religious players can readily uncurse items, so don't make this too drastic.
Definition at line 75 of file shop.c.
References obj::arch, archt::clone, FLAG_BLESSED, FLAG_CURSED, FLAG_DAMNED, liv::food, GEM, is_identified(), castle_read::key, obj::magic, MONEY, NROF(), object_get_value(), QUERY_FLAG, obj::stats, obj::type, obj::value, and WAND.
Referenced by alchemy_object(), attempt_do_alchemy(), check_pick(), price_approx(), shop_price_buy(), and shop_price_sell().
uint64_t query_money | ( | const object * | op | ) |
Determine the amount of money the given object contains, including what is inside containers.
op | Player or container object |
Definition at line 430 of file shop.c.
References CONTAINER, FLAG_APPLIED, FOR_INV_FINISH, FOR_INV_PREPARE, llevError, LOG(), MONEY, give::op, PLAYER, QUERY_FLAG, Ice::tmp, and mail_login::total.
Referenced by can_pay(), cfapi_object_query_money(), pay_for_amount(), pay_for_item(), and shop_pay_unpaid().
|
static |
Returns a string representing the money's value, in plain coins.
coin | coin. Must be of type MONEY. |
buf | buffer to append to. Must not be NULL. |
Definition at line 357 of file shop.c.
References buf, MONEY, obj::name, obj::name_pl, obj::nrof, stringbuffer_append_printf(), and obj::type.
Referenced by cost_approx_str().
|
static |
This function removes a given amount from a list of coins.
coin_objs | the list coins to remove from; the list must be ordered from least to most valuable coin. |
remain | the value (in silver coins) to remove |
Definition at line 542 of file shop.c.
References disinfect::count, obj::nrof, NUM_COINS, autojail::value, and obj::value.
Referenced by pay_from_container().
Player is selling an item. Give money, print appropriate messages.
Will fill applied money containers before dumping remaining coins in character's inventory.
op | object to sell. |
pl | player. Shouldn't be NULL or non player. |
Definition at line 945 of file shop.c.
References change_exp(), archt::clone, coins, compute_price_variation_with_bargaining(), CONTAINER, cost_str(), disinfect::count, draw_ext_info_format(), esrv_update_item(), EVENT_SELLING, events_execute_object_event(), find_archetype(), FLAG_APPLIED, FLAG_UNPAID, FOR_INV_FINISH, FOR_INV_PREPARE, FREE_AND_CLEAR_STR, identify(), LARGEST_COIN_GIVEN, llevDebug, llevError, LOG(), MAX_BUF, MAX_SELL_EXTRA, MSG_TYPE_SHOP, MSG_TYPE_SHOP_SELL, NDI_UNIQUE, object_copy(), object_insert_in_ob(), object_new(), give::op, PLAYER, say::price, QUERY_FLAG, query_name(), SCRIPT_FIX_ALL, SET_FLAG, shop_price_sell(), SK_EXP_NONE, Ice::tmp, UPD_WEIGHT, obj::value, and obj::weight.
Referenced by drop_object().
Return the approval ratio for a shop for a given player. This is based on both the race of the shopkeeper and the player.
map | Map with a shop |
player | Player in question |
Definition at line 1111 of file shop.c.
References disinfect::map, and NEUTRAL_RATIO.
Referenced by shop_describe(), shop_efficiency(), and shop_mat_type_move_on().
|
static |
Calculate the buy price multiplier based on a player's charisma.
charisma | player's charisma. |
Definition at line 173 of file shop.c.
Referenced by shop_efficiency().
bool shop_contains | ( | object * | ob | ) |
Check if an object is in a shop.
Definition at line 1276 of file shop.c.
References coords_in_shop(), and guildjoin::ob.
Referenced by convert_item(), drop_object(), examine(), kill_player_not_permadeath(), shop_mat_type_move_on(), and transport_type_apply().
int shop_describe | ( | const object * | op | ) |
A player is examining a shop, so describe it.
op | who is examining the shop. |
Definition at line 1174 of file shop.c.
References cost_str(), draw_ext_info(), draw_ext_info_format(), make_list_like(), disinfect::map, MAX_BUF, MSG_TYPE_SHOP, MSG_TYPE_SHOP_LISTING, MSG_TYPE_SHOP_MISC, NDI_UNIQUE, give::op, PLAYER, shop_approval(), Ice::tmp, and autojail::value.
Referenced by do_skill().
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 than or equal to one. When E is one, there is no buy/sell spread and the shop makes no money. When E is low, transaction costs to the player are high. Shops should pay players price*E for items and sell it to players for price/E.
Definition at line 184 of file shop.c.
References shop_approval(), shop_cha_modifier(), and shop_greed().
Referenced by shop_price_buy(), and shop_price_sell().
|
static |
Gets a shop's greed. For historical reasons, this is a number between 0 and 2. Use this to compute a base efficiency for a shop: 0 ~= 1.0 (shop makes no profit) 1 ~= 0.9 (a reasonably efficient market) 2 ~= 0.5 (2x more expensive items, pays 0.5x for items)
Caveat: most shops have greed unset (0), so make that 1
map | map to get greed. |
Definition at line 1103 of file shop.c.
References disinfect::map.
Referenced by shop_efficiency().
Pay as many unpaid items as possible, recursing on op->inv and op->below.
pl | player who is buying items. |
op | first potentially unpaid item. |
Definition at line 865 of file shop.c.
References change_exp(), CLEAR_FLAG, compute_price_variation_with_bargaining(), cost_str(), draw_ext_info_format(), esrv_update_item(), EVENT_BOUGHT, events_execute_object_event(), FLAG_PLAYER_SOLD, FLAG_UNPAID, MAX_BUF, MAX_BUY_REDUCTION, MSG_TYPE_SHOP, MSG_TYPE_SHOP_PAYMENT, NDI_UNIQUE, object_merge(), give::op, pay_for_item(), PLAYER, say::price, QUERY_FLAG, query_money(), query_name(), SCRIPT_FIX_ALL, SET_FLAG, shop_price_buy(), SK_EXP_NONE, Ice::tmp, UPD_FLAGS, UPD_NAME, and autojail::value.
Referenced by shop_mat_type_move_on().
Adjust the value of an item to be bought based on the player's bargaining skill and charisma. This should only be used if the player is in a shop.
obj | item in question. Must not be NULL. |
who | player trying to judge the value of the item. Must not be NULL. |
Definition at line 190 of file shop.c.
References castle_read::key, llevDebug, LOG(), object_get_value(), PLAYER, price_base(), shop_efficiency(), Ice::tmp, and autojail::who.
Referenced by count_unpaid(), examine(), pay_for_item(), pick_up_object(), and shop_pay_unpaid().
Adjust the value of an item to be sold based on the player's bargaining skill and charisma. This should only be used if the player is in a shop.
obj | item in question. Must not be NULL. |
who | player trying to judge the value of the item. Must not be NULL. |
Definition at line 211 of file shop.c.
References castle_read::key, llevDebug, LOG(), NROF(), object_get_value(), PLAYER, price_base(), shop_efficiency(), shop_specialisation_ratio(), Ice::tmp, value_limit(), and autojail::who.
Referenced by examine(), sell_item(), and START_TEST().
Returns the ratio of the price that a shop will offer for an item based on the shop's specialisation. The ratio is between (2*SPECIALISATION_EFFECT-1) and 1 and in any event is never less than 0.1 (calling functions divide by it). This ratio should multiply only the sell price, because incorrectly coded shops that generate items outside of specialty shouldn't give away items for very low prices.
item | item to get ratio of. |
map | shop map. |
Definition at line 1052 of file shop.c.
References shopitem::index, llevDebug, llevError, LOG(), disinfect::map, SPECIALISATION_EFFECT, shopitem::strength, and shopitem::typenum.
Referenced by shop_price_sell().
|
static |
Limit the value of items based on the wealth of the shop. If the item is close to the maximum value a shop will offer, we start to reduce it, if the item is below the minimum value the shop is prepared to trade in, then we don't want it and offer nothing. If it isn't a shop, check whether we should do generic value reduction.
val | current price. |
quantity | number of items. |
who | player selling. |
isshop | 0 if not a shop, 1 if a shop. |
Definition at line 1140 of file shop.c.
References isqrt(), llevError, LOG(), disinfect::map, MIN, commongive::quantity, and autojail::who.
Referenced by shop_price_sell().
|
static |
Coins to use for shopping.
Definition at line 62 of file shop.c.
Referenced by can_pay(), count_coins(), find_next_coin(), pay_from_container(), and sell_item().