1 | /* |
1 | /* |
2 | * static char *rcsid_shop_c = |
2 | * static char *rcsid_shop_c = |
3 | * "$Id: shop.c,v 1.1.1.1 2006/02/03 07:14:37 root Exp $"; |
3 | * "$Id: shop.c,v 1.1.1.2 2006/02/22 18:03:24 elmex Exp $"; |
4 | */ |
4 | */ |
5 | |
5 | |
6 | /* |
6 | /* |
7 | CrossFire, A Multiplayer game for X-windows |
7 | CrossFire, A Multiplayer game for X-windows |
8 | |
8 | |
… | |
… | |
50 | |
50 | |
51 | /* price a shopkeeper will give someone they neither like nor dislike */ |
51 | /* price a shopkeeper will give someone they neither like nor dislike */ |
52 | #define NEUTRAL_RATIO 0.8 |
52 | #define NEUTRAL_RATIO 0.8 |
53 | |
53 | |
54 | static uint64 pay_from_container(object *pl, object *pouch, uint64 to_pay); |
54 | static uint64 pay_from_container(object *pl, object *pouch, uint64 to_pay); |
55 | static uint64 value_limit(uint64 val, int quantity, object *who, int isshop); |
55 | static uint64 value_limit(uint64 val, int quantity, const object *who, int isshop); |
|
|
56 | static double shop_specialisation_ratio(const object *item, const mapstruct *map); |
|
|
57 | static double shop_greed(const mapstruct *map); |
56 | |
58 | |
57 | #define NUM_COINS 3 /* number of coin types */ |
59 | #define NUM_COINS 3 /* number of coin types */ |
58 | static char *coins[] = {"platinacoin", "goldcoin", "silvercoin", NULL}; |
60 | static const char* const coins[] = {"platinacoin", "goldcoin", "silvercoin", NULL}; |
59 | |
61 | |
60 | /* Added F_TRUE flag to define.h to mean that the price should not |
62 | /* Added F_TRUE flag to define.h to mean that the price should not |
61 | * be adjusted by players charisma. With F_TRUE, it returns the amount |
63 | * be adjusted by players charisma. With F_TRUE, it returns the amount |
62 | * that the item is worth, if it was sold, but unadjusted by charisma. |
64 | * that the item is worth, if it was sold, but unadjusted by charisma. |
63 | * This is needed for alchemy, to to determine what value of gold nuggets |
65 | * This is needed for alchemy, to to determine what value of gold nuggets |
… | |
… | |
79 | * divisions took place, the value got rounded to 0 (Being an int), and |
81 | * divisions took place, the value got rounded to 0 (Being an int), and |
80 | * thus remained 0. |
82 | * thus remained 0. |
81 | * |
83 | * |
82 | * Mark Wedel (mwedel@pyramid.com) |
84 | * Mark Wedel (mwedel@pyramid.com) |
83 | */ |
85 | */ |
84 | uint64 query_cost(object *tmp, object *who, int flag) { |
86 | uint64 query_cost(const object *tmp, object *who, int flag) { |
85 | uint64 val; |
87 | uint64 val; |
86 | int number; /* used to better calculate value */ |
88 | int number; /* used to better calculate value */ |
87 | int no_bargain; |
89 | int no_bargain; |
88 | int identified; |
90 | int identified; |
89 | int not_cursed; |
91 | int not_cursed; |
… | |
… | |
328 | * have so much money that they have more than 2 billion platinum |
330 | * have so much money that they have more than 2 billion platinum |
329 | * coins, there are certainly issues - the easiest fix at that |
331 | * coins, there are certainly issues - the easiest fix at that |
330 | * time is to add a higher denomination (mithril piece with |
332 | * time is to add a higher denomination (mithril piece with |
331 | * 10,000 silver or something) |
333 | * 10,000 silver or something) |
332 | */ |
334 | */ |
333 | const char *cost_string_from_value(uint64 cost) |
335 | static const char *cost_string_from_value(uint64 cost) |
334 | { |
336 | { |
335 | static char buf[MAX_BUF]; |
337 | static char buf[MAX_BUF]; |
336 | archetype *coin, *next_coin; |
338 | archetype *coin, *next_coin; |
337 | char *endbuf; |
339 | char *endbuf; |
338 | int num, cointype = 0; |
340 | int num, cointype = 0; |
… | |
… | |
388 | } while (next_coin); |
390 | } while (next_coin); |
389 | |
391 | |
390 | return buf; |
392 | return buf; |
391 | } |
393 | } |
392 | |
394 | |
393 | const char *query_cost_string(object *tmp,object *who,int flag) { |
395 | const char *query_cost_string(const object *tmp,object *who,int flag) { |
394 | uint64 real_value = query_cost(tmp,who,flag); |
396 | uint64 real_value = query_cost(tmp,who,flag); |
395 | int idskill1=0; |
397 | int idskill1=0; |
396 | int idskill2=0; |
398 | int idskill2=0; |
397 | const typedata *tmptype; |
399 | const typedata *tmptype; |
398 | |
400 | |
… | |
… | |
441 | } |
443 | } |
442 | |
444 | |
443 | /* This function finds out how much money the player is carrying, |
445 | /* This function finds out how much money the player is carrying, |
444 | * including what is in containers. |
446 | * including what is in containers. |
445 | */ |
447 | */ |
446 | uint64 query_money(object *op) { |
448 | uint64 query_money(const object *op) { |
447 | object *tmp; |
449 | object *tmp; |
448 | uint64 total=0; |
450 | uint64 total=0; |
449 | |
451 | |
450 | if (op->type!=PLAYER && op->type!=CONTAINER) { |
452 | if (op->type!=PLAYER && op->type!=CONTAINER) { |
451 | LOG(llevError, "Query money called with non player/container\n"); |
453 | LOG(llevError, "Query money called with non player/container\n"); |
… | |
… | |
642 | uint64 unpaid_price = 0; |
644 | uint64 unpaid_price = 0; |
643 | uint64 player_wealth = query_money(pl); |
645 | uint64 player_wealth = query_money(pl); |
644 | object *item; |
646 | object *item; |
645 | uint32 coincount[NUM_COINS]; |
647 | uint32 coincount[NUM_COINS]; |
646 | if (!pl || pl->type != PLAYER) { |
648 | if (!pl || pl->type != PLAYER) { |
647 | LOG(llevError, "can_pay(): called against something that isn't a player"); |
649 | LOG(llevError, "can_pay(): called against something that isn't a player\n"); |
648 | return 0; |
650 | return 0; |
649 | } |
651 | } |
650 | for (i=0; i< NUM_COINS; i++) coincount[i] = 0; |
652 | for (i=0; i< NUM_COINS; i++) coincount[i] = 0; |
651 | for (item = pl->inv;item;) { |
653 | for (item = pl->inv;item;) { |
652 | if QUERY_FLAG(item, FLAG_UNPAID) { |
654 | if QUERY_FLAG(item, FLAG_UNPAID) { |
… | |
… | |
842 | /* returns a double that is the ratio of the price that a shop will offer for |
844 | /* returns a double that is the ratio of the price that a shop will offer for |
843 | * item based on the shops specialisation. Does not take account of greed, |
845 | * item based on the shops specialisation. Does not take account of greed, |
844 | * returned value is between (2*SPECIALISATION_EFFECT-1) and 1 and in any |
846 | * returned value is between (2*SPECIALISATION_EFFECT-1) and 1 and in any |
845 | * event is never less than 0.1 (calling functions divide by it) |
847 | * event is never less than 0.1 (calling functions divide by it) |
846 | */ |
848 | */ |
847 | double shop_specialisation_ratio(object *item, mapstruct *map) { |
849 | static double shop_specialisation_ratio(const object *item, const mapstruct *map) { |
848 | shopitems *items=map->shopitems; |
850 | shopitems *items=map->shopitems; |
849 | double ratio = SPECIALISATION_EFFECT, likedness=0.001; |
851 | double ratio = SPECIALISATION_EFFECT, likedness=0.001; |
850 | int i; |
852 | int i; |
851 | |
853 | |
852 | if (item==NULL) { |
854 | if (item==NULL) { |
853 | LOG(llevError, "shop_specialisation_ratio: passed a NULL item for map %s", map->path); |
855 | LOG(llevError, "shop_specialisation_ratio: passed a NULL item for map %s\n", map->path); |
854 | return 0; |
856 | return 0; |
855 | } |
857 | } |
856 | if (!item->type) { |
858 | if (!item->type) { |
857 | LOG(llevError, "shop_specialisation_ratio: passed an item with an invalid type"); |
859 | LOG(llevError, "shop_specialisation_ratio: passed an item with an invalid type\n"); |
858 | /* |
860 | /* |
859 | * I'm not really sure what the /right/ thing to do here is, these types of |
861 | * I'm not really sure what the /right/ thing to do here is, these types of |
860 | * item shouldn't exist anyway, but returning the ratio is probably the best bet.." |
862 | * item shouldn't exist anyway, but returning the ratio is probably the best bet.." |
861 | */ |
863 | */ |
862 | return ratio; |
864 | return ratio; |
… | |
… | |
880 | if (ratio <= 0.1) ratio=0.1; /* if the ratio were much lower than this, we would get silly prices */ |
882 | if (ratio <= 0.1) ratio=0.1; /* if the ratio were much lower than this, we would get silly prices */ |
881 | return ratio; |
883 | return ratio; |
882 | } |
884 | } |
883 | |
885 | |
884 | /*returns the greed of the shop on map, or 1 if it isn't specified. */ |
886 | /*returns the greed of the shop on map, or 1 if it isn't specified. */ |
885 | double shop_greed(mapstruct *map) { |
887 | static double shop_greed(const mapstruct *map) { |
886 | double greed=1.0; |
888 | double greed=1.0; |
887 | if (map->shopgreed) |
889 | if (map->shopgreed) |
888 | return map->shopgreed; |
890 | return map->shopgreed; |
889 | return greed; |
891 | return greed; |
890 | } |
892 | } |
891 | |
893 | |
892 | /* Returns a double based on how much the shopkeeper approves of the player. |
894 | /* Returns a double based on how much the shopkeeper approves of the player. |
893 | * this is based on the race of the shopkeeper and that of the player. |
895 | * this is based on the race of the shopkeeper and that of the player. |
894 | */ |
896 | */ |
895 | double shopkeeper_approval(mapstruct *map, object *player) { |
897 | double shopkeeper_approval(const mapstruct *map, const object *player) { |
896 | double approval=1.0; |
898 | double approval=1.0; |
897 | |
899 | |
898 | if (map->shoprace) { |
900 | if (map->shoprace) { |
899 | approval=NEUTRAL_RATIO; |
901 | approval=NEUTRAL_RATIO; |
900 | if (player->race && !strcmp(player->race, map->shoprace)) approval = 1.0; |
902 | if (player->race && !strcmp(player->race, map->shoprace)) approval = 1.0; |
… | |
… | |
907 | * below the minimum value the shop is prepared to trade in, then we don't |
909 | * below the minimum value the shop is prepared to trade in, then we don't |
908 | * want it and offer nothing. If it isn't a shop, check whether we should do generic |
910 | * want it and offer nothing. If it isn't a shop, check whether we should do generic |
909 | * value reduction. |
911 | * value reduction. |
910 | * |
912 | * |
911 | */ |
913 | */ |
912 | static uint64 value_limit(uint64 val, int quantity, object *who, int isshop) { |
914 | static uint64 value_limit(uint64 val, int quantity, const object *who, int isshop) { |
913 | uint64 newval, unit_price; |
915 | uint64 newval, unit_price; |
914 | mapstruct *map; |
916 | mapstruct *map; |
915 | unit_price=val/quantity; |
917 | unit_price=val/quantity; |
916 | if (!isshop || !who) { |
918 | if (!isshop || !who) { |
917 | if (unit_price > 10000) |
919 | if (unit_price > 10000) |
918 | newval=8000+isqrt(unit_price)*20; |
920 | newval=8000+isqrt(unit_price)*20; |
919 | else |
921 | else |
920 | newval=unit_price; |
922 | newval=unit_price; |
921 | } else { |
923 | } else { |
922 | if (!who->map) { |
924 | if (!who->map) { |
923 | LOG(llevError, "value_limit: asked shop price for ob %s on NULL map", who->name); |
925 | LOG(llevError, "value_limit: asked shop price for ob %s on NULL map\n", who->name); |
924 | return val; |
926 | return val; |
925 | } |
927 | } |
926 | map=who->map; |
928 | map=who->map; |
927 | if (map->shopmin && unit_price < map->shopmin) return 0; |
929 | if (map->shopmin && unit_price < map->shopmin) return 0; |
928 | else if (map->shopmax && unit_price > map->shopmax/2) |
930 | else if (map->shopmax && unit_price > map->shopmax/2) |
… | |
… | |
935 | newval *= quantity; |
937 | newval *= quantity; |
936 | return newval; |
938 | return newval; |
937 | } |
939 | } |
938 | |
940 | |
939 | /* gives a desciption of the shop on their current map to the player op. */ |
941 | /* gives a desciption of the shop on their current map to the player op. */ |
940 | int describe_shop(object *op) { |
942 | int describe_shop(const object *op) { |
941 | mapstruct *map = op->map; |
943 | mapstruct *map = op->map; |
942 | /*shopitems *items=map->shopitems;*/ |
944 | /*shopitems *items=map->shopitems;*/ |
943 | int pos=0, i; |
945 | int pos=0, i; |
944 | double opinion=0; |
946 | double opinion=0; |
945 | char tmp[MAX_BUF]="\0"; |
947 | char tmp[MAX_BUF]="\0"; |