ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/shop.c
(Generate patch)

Comparing deliantra/server/server/shop.c (file contents):
Revision 1.3 by pippijn, Wed May 24 01:51:09 2006 UTC vs.
Revision 1.17 by root, Tue Jul 11 10:35:20 2006 UTC

1/* 1/*
2 * static char *rcsid_shop_c = 2 * static char *rcsid_shop_c =
3 * "$Id: shop.c,v 1.3 2006/05/24 01:51:09 pippijn Exp $"; 3 * "$Id: shop.c,v 1.17 2006/07/11 10:35:20 root 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
42 * therefore making this number higher, makes specialisation less effective. 42 * therefore making this number higher, makes specialisation less effective.
43 * setting this value above 1 or to a negative value would have interesting, 43 * setting this value above 1 or to a negative value would have interesting,
44 * (though not useful) effects. 44 * (though not useful) effects.
45 */ 45 */
46#define SPECIALISATION_EFFECT 0.5 46#define SPECIALISATION_EFFECT 0.5
47
48/* price a shopkeeper will give to someone they disapprove of.*/
49#define DISAPPROVAL_RATIO 0.2
50 47
51/* price a shopkeeper will give someone they neither like nor dislike */ 48/* price a shopkeeper will give someone they neither like nor dislike */
52#define NEUTRAL_RATIO 0.8 49#define NEUTRAL_RATIO 0.8
53 50
54static uint64 pay_from_container(object *pl, object *pouch, uint64 to_pay); 51static uint64 pay_from_container(object *pl, object *pouch, uint64 to_pay);
81 * divisions took place, the value got rounded to 0 (Being an int), and 78 * divisions took place, the value got rounded to 0 (Being an int), and
82 * thus remained 0. 79 * thus remained 0.
83 * 80 *
84 * Mark Wedel (mwedel@pyramid.com) 81 * Mark Wedel (mwedel@pyramid.com)
85 */ 82 */
83
84static uint64 approx_range;
85
86uint64 query_cost(const object *tmp, object *who, int flag) { 86uint64 query_cost(const object *tmp, object *who, int flag) {
87 uint64 val; 87 uint64 val;
88 int number; /* used to better calculate value */ 88 int number; /* used to better calculate value */
89 int no_bargain; 89 int no_bargain;
90 int identified; 90 int identified;
91 int not_cursed; 91 int not_cursed;
92 int approximate; 92 int approximate;
93 int shop; 93 int shop;
94 float diff; 94 double diff;
95 float ratio; 95
96 approx_range = 0;
96 97
97 no_bargain = flag & F_NO_BARGAIN; 98 no_bargain = flag & F_NO_BARGAIN;
98 identified = flag & F_IDENTIFIED; 99 identified = flag & F_IDENTIFIED;
99 not_cursed = flag & F_NOT_CURSED; 100 not_cursed = flag & F_NOT_CURSED;
100 approximate = flag & F_APPROX; 101 approximate = flag & F_APPROX;
124 LOG(llevError, "Asking for buy-value of unidentified object.\n"); 125 LOG(llevError, "Asking for buy-value of unidentified object.\n");
125 val = tmp->arch->clone.value * 50 * number; 126 val = tmp->arch->clone.value * 50 * number;
126 } 127 }
127 else { /* Trying to sell something, or get true value */ 128 else { /* Trying to sell something, or get true value */
128 if (tmp->type == POTION) 129 if (tmp->type == POTION)
129 val = number * 1000; /* Don't want to give anything away */ 130 val = number * 40; /* Don't want to give anything away */
130 else { 131 else {
131 /* Get 2/3'rd value for applied objects, 1/3'rd for totally 132 /* Get 2/3'rd value for applied objects, 1/3'rd for totally
132 * unknown objects 133 * unknown objects
133 */ 134 */
134 if (QUERY_FLAG(tmp, FLAG_BEEN_APPLIED)) 135 if (QUERY_FLAG(tmp, FLAG_BEEN_APPLIED))
179 else /* if not identified, presume one charge */ 180 else /* if not identified, presume one charge */
180 val/=50; 181 val/=50;
181 } 182 }
182 183
183 /* Limit amount of money you can get for really great items. */ 184 /* Limit amount of money you can get for really great items. */
184 if (flag==F_TRUE || flag==F_SELL) 185 if (flag==F_SELL)
185 val=value_limit(val, number, who, shop); 186 val=value_limit(val, number, who, shop);
186 187
187 /* we need to multiply these by 4.0 to keep buy costs roughly the same 188 // use a nonlinear price adjustment. as my predecessor said, don't change
188 * (otherwise, you could buy a potion of charisma for around 400 pp. 189 // the archetypes, its work required for balancing, and we don't care.
189 * Arguable, the costs in the archetypes should be updated to better 190 //val = pow (val, 1.05);
190 * reflect values (potion charisma list for 1250 gold)
191 */
192 val *= 4;
193 191
194 /* This modification is for bargaining skill. 192 /* This modification is for bargaining skill.
195 * Now only players with max level in bargaining 193 * Now only players with max level in bargaining
196 * AND Cha = 30 will get optimal price. 194 * AND Cha = 30 will get optimal price.
197 * Thus charisma will never get useless. 195 * Thus charisma will never get useless.
203 int lev_identify = 0; 201 int lev_identify = 0;
204 int idskill1=0; 202 int idskill1=0;
205 int idskill2=0; 203 int idskill2=0;
206 const typedata *tmptype; 204 const typedata *tmptype;
207 205
208 /* ratio determines how much of the price modification
209 * will come from the basic stat charisma
210 * the rest will come from the level in bargaining skill
211 */
212 ratio = 0.5;
213 tmptype=get_typedata(tmp->type); 206 tmptype=get_typedata(tmp->type);
214 207
215 if (find_skill_by_number(who,SK_BARGAINING)) { 208 if (find_skill_by_number(who,SK_BARGAINING)) {
216 lev_bargain = find_skill_by_number(who,SK_BARGAINING)->level; 209 lev_bargain = find_skill_by_number(who,SK_BARGAINING)->level;
217 } 210 }
226 lev_identify += find_skill_by_number(who,idskill2)->level; 219 lev_identify += find_skill_by_number(who,idskill2)->level;
227 } 220 }
228 } 221 }
229 } 222 }
230 else LOG(llevError, "Query_cost: item %s hasn't got a valid type\n", tmp->name); 223 else LOG(llevError, "Query_cost: item %s hasn't got a valid type\n", tmp->name);
231 if ( !no_bargain && (lev_bargain>0) ) 224
232 diff = (0.8 - 0.6*((lev_bargain+settings.max_level*0.05) 225 /* ratio determines how much of the price modification
233 /(settings.max_level*1.05))); 226 * will come from the basic stat charisma
234 else 227 * the rest will come from the level in bargaining skill
235 diff = 0.8; 228 */
229 const double cha_ratio = 0.40;
230
231 diff = no_bargain ? 1.0 : 1. - pow (lev_bargain / (double)settings.max_level, 0.25);
236 232
237 diff *= 1-ratio; 233 diff = (1. - cha_ratio) * diff
234 + cha_ratio * (cha_bonus[who->stats.Cha] - 1.) / (cha_bonus[who->stats.Cha] + 1.);
235
236 diff = .02 + (.80 - .02) * diff;
238 237
239 /* Diff is now a float between 0.2 and 0.8 */ 238 if (flag == F_BUY) val += val * diff;
240 diff+=(cha_bonus[who->stats.Cha]-1)/(1+cha_bonus[who->stats.Cha])*ratio; 239 else if (flag == F_SELL) val -= val * diff;
241 240
242 if(flag==F_BUY) 241 // now find a price range. the less good we can judge, the larger the range is
243 val=(val*(long)(1000*(1+diff)))/1000; 242 // then the range is adjusted randomly around the correct value
244 else if (flag==F_SELL)
245 val=(val*(long)(1000*(1-diff)))/1000;
246
247 /* If we are approximating, then the value returned should be allowed to be wrong
248 * however merely using a random number each time will not be sufficiant, as then
249 * multiple examinations would give different answers, so we'll use the count
250 * instead. By taking the sine of the count, a value between -1 and 1 is
251 * generated, we then divide by the square root of the bargaining skill and the
252 * appropriate identification skills, so that higher level players get better estimates.
253 * (we need a +1 there in case we would otherwise be dividing by zero.
254 */
255 if (approximate) 243 if (approximate)
256 val = (sint64)val + (sint64)((sint64)val*(sin(tmp->count)/sqrt(lev_bargain+lev_identify*2+1.0))); 244 approx_range = val / sqrt (lev_identify * 3 + 1);
257 } 245 }
258 246
259 /* I don't think this should really happen - if it does, it indicates and 247 /* I don't think this should really happen - if it does, it indicates and
260 * overflow of diff above. That shoudl only happen if 248 * overflow of diff above. That shoudl only happen if
261 * we are selling objects - in that case, the person just 249 * we are selling objects - in that case, the person just
331 * have so much money that they have more than 2 billion platinum 319 * have so much money that they have more than 2 billion platinum
332 * coins, there are certainly issues - the easiest fix at that 320 * coins, there are certainly issues - the easiest fix at that
333 * time is to add a higher denomination (mithril piece with 321 * time is to add a higher denomination (mithril piece with
334 * 10,000 silver or something) 322 * 10,000 silver or something)
335 */ 323 */
336static const char *cost_string_from_value(uint64 cost) 324static const char *cost_string_from_value(uint64 cost, int approx)
337{ 325{
338 static char buf[MAX_BUF]; 326 static char buf[MAX_BUF];
339 archetype *coin, *next_coin; 327 archetype *coin, *next_coin;
340 char *endbuf;
341 int num, cointype = 0; 328 int num, cointype = 0;
342 329
343 coin = find_next_coin(cost, &cointype); 330 coin = find_next_coin(cost, &cointype);
344 if (coin == NULL) 331 if (coin == NULL)
345 return "nothing"; 332 return "nothing";
353 strcpy(buf,"an unimaginable sum of money."); 340 strcpy(buf,"an unimaginable sum of money.");
354 return buf; 341 return buf;
355 } 342 }
356 343
357 cost -= (uint64)num * (uint64)coin->clone.value; 344 cost -= (uint64)num * (uint64)coin->clone.value;
358 if (num == 1) 345 sprintf(buf, "%d %s", num, num > 1 ? coin->clone.name_pl : coin->clone.name);
359 sprintf(buf, "1 %s", coin->clone.name);
360 else
361 sprintf(buf, "%d %s", num, coin->clone.name_pl);
362 346
363 next_coin = find_next_coin(cost, &cointype); 347 next_coin = find_next_coin(cost, &cointype);
364 if (next_coin == NULL) 348 if (next_coin == NULL || approx)
365 return buf; 349 return buf;
366 350
367 do {
368 endbuf = buf + strlen(buf);
369
370 coin = next_coin; 351 coin = next_coin;
371 num = cost / coin->clone.value; 352 num = cost / coin->clone.value;
372 cost -= (uint64)num * (uint64)coin->clone.value; 353 cost -= (uint64)num * (uint64)coin->clone.value;
373 354
374 if (cost == 0) 355 sprintf (buf + strlen (buf), " and %d %s", num, num > 1 ? coin->clone.name_pl : coin->clone.name);
375 next_coin = NULL; 356
376 else
377 next_coin = find_next_coin(cost, &cointype);
378
379 if (next_coin) {
380 /* There will be at least one more string to add to the list,
381 * use a comma.
382 */
383 strcat(endbuf, ", "); endbuf += 2;
384 } else {
385 strcat(endbuf, " and "); endbuf += 5;
386 }
387 if (num == 1)
388 sprintf(endbuf, "1 %s", coin->clone.name);
389 else
390 sprintf(endbuf, "%d %ss", num, coin->clone.name);
391 } while (next_coin);
392
393 return buf; 357 return buf;
394} 358}
395 359
396const char *query_cost_string(const object *tmp,object *who,int flag) { 360const char *query_cost_string(const object *tmp,object *who,int flag) {
397 uint64 real_value = query_cost(tmp,who,flag); 361 uint64 real_value = query_cost(tmp,who,flag);
437 sprintf(buf, "a vast quantity of %s", coin->clone.name_pl); 401 sprintf(buf, "a vast quantity of %s", coin->clone.name_pl);
438 return buf; 402 return buf;
439 } 403 }
440 } 404 }
441 } 405 }
406
407 int hash = ((unsigned int)tmp->count * 174364621) & 1023;
408
409 if (approx_range)
410 {
411 uint64 lo = (sint64)real_value - (approx_range * hash >> 10);
412 static char buf[MAX_BUF];
413
414 sprintf (buf, "between %s", cost_string_from_value (lo, 1));
415 sprintf (buf + strlen (buf), " and %s", cost_string_from_value (lo + approx_range, 1));
416
417 return buf;
418 }
442 } 419 }
420
443 return cost_string_from_value(real_value); 421 return cost_string_from_value (real_value, 0);
444} 422}
445 423
446/* This function finds out how much money the player is carrying, 424/* This function finds out how much money the player is carrying,
447 * including what is in containers. 425 * including what is in containers.
448 */ 426 */
669 } 647 }
670 if (unpaid_price > player_wealth) { 648 if (unpaid_price > player_wealth) {
671 char buf[MAX_BUF], coinbuf[MAX_BUF]; 649 char buf[MAX_BUF], coinbuf[MAX_BUF];
672 int denominations = 0; 650 int denominations = 0;
673 int has_coins = NUM_COINS; 651 int has_coins = NUM_COINS;
674 sprintf(buf, "You have %d unpaid items that would cost you %s, but you", 652 char cost[MAX_BUF];
653 char missing[MAX_BUF];
654
675 unpaid_count, cost_string_from_value(unpaid_price)); 655 sprintf(cost, "%s", cost_string_from_value (unpaid_price, 0));
676 for (i=0; i< NUM_COINS; i++) { 656 sprintf(missing, "%s", cost_string_from_value (unpaid_price - player_wealth, 0));
677 if (coincount[i] == 0) { 657
678 has_coins--; 658 sprintf(buf, "You have %d unpaid items that would cost you %s. You need another %s to be able to afford that.",
679 } 659 unpaid_count, cost, missing);
680 }
681 if (has_coins == 0) {
682 strcat (buf, " have nothing to spend.");
683 new_draw_info(NDI_UNIQUE, 0, pl, buf);
684 return 0;
685 }
686 for (i=0; i< NUM_COINS; i++) {
687 if (coincount[i] > 0 && coins[i]) {
688 denominations++;
689 sprintf(coinbuf, " %d %s,", coincount[i], find_archetype(coins[i])->clone.name_pl);
690 strcat (buf, coinbuf);
691 }
692 }
693 if (denominations > 1) make_list_like(buf);
694 new_draw_info(NDI_UNIQUE, 0, pl, buf); 660 new_draw_info(NDI_UNIQUE, 0, pl, buf);
695 return 0; 661 return 0;
696 } 662 }
697 else return 1; 663 else return 1;
698} 664}
728 buf[MAX_BUF-1] = '\0'; 694 buf[MAX_BUF-1] = '\0';
729 if(!pay_for_item(op,pl)) { 695 if(!pay_for_item(op,pl)) {
730 uint64 i=query_cost(op,pl,F_BUY | F_SHOP) - query_money(pl); 696 uint64 i=query_cost(op,pl,F_BUY | F_SHOP) - query_money(pl);
731 CLEAR_FLAG(op, FLAG_UNPAID); 697 CLEAR_FLAG(op, FLAG_UNPAID);
732 new_draw_info_format(NDI_UNIQUE, 0, pl, 698 new_draw_info_format(NDI_UNIQUE, 0, pl,
733 "You lack %s to buy %s.", cost_string_from_value(i), 699 "You lack %s to buy %s.", cost_string_from_value (i, 0),
734 query_name(op)); 700 query_name(op));
735 SET_FLAG(op, FLAG_UNPAID); 701 SET_FLAG(op, FLAG_UNPAID);
736 return 0; 702 return 0;
737 } else { 703 } else {
738 object *tmp; 704 object *tmp;
926static uint64 value_limit(uint64 val, int quantity, const object *who, int isshop) { 892static uint64 value_limit(uint64 val, int quantity, const object *who, int isshop) {
927 uint64 newval, unit_price; 893 uint64 newval, unit_price;
928 mapstruct *map; 894 mapstruct *map;
929 unit_price=val/quantity; 895 unit_price=val/quantity;
930 if (!isshop || !who) { 896 if (!isshop || !who) {
931 if (unit_price > 10000) 897 if (unit_price > 250000)
932 newval=8000+isqrt(unit_price)*20; 898 newval = 250000. - pow (250000., .75) * 65. + pow (unit_price, .75) * 65.;
933 else 899 else
934 newval=unit_price; 900 newval=unit_price;
935 } else { 901 } else {
936 if (!who->map) { 902 if (!who->map) {
937 LOG(llevError, "value_limit: asked shop price for ob %s on NULL map\n", who->name); 903 LOG(llevError, "value_limit: asked shop price for ob %s on NULL map\n", who->name);
939 } 905 }
940 map=who->map; 906 map=who->map;
941 if (map->shopmin && unit_price < map->shopmin) return 0; 907 if (map->shopmin && unit_price < map->shopmin) return 0;
942 else if (map->shopmax && unit_price > map->shopmax/2) 908 else if (map->shopmax && unit_price > map->shopmax/2)
943 newval=MIN((map->shopmax/2)+isqrt(unit_price-map->shopmax/2), map->shopmax); 909 newval=MIN((map->shopmax/2)+isqrt(unit_price-map->shopmax/2), map->shopmax);
944 else if (unit_price>10000) 910 else if (unit_price > 250000)
945 newval=8000+isqrt(unit_price)*20; 911 newval = 250000. - pow (250000., .75) * 65. + pow (unit_price, .75) * 65.;
946 else 912 else
947 newval=unit_price; 913 newval=unit_price;
948 } 914 }
949 newval *= quantity; 915 newval *= quantity;
950 return newval; 916 return newval;
976 make_list_like(tmp); 942 make_list_like(tmp);
977 new_draw_info_format(NDI_UNIQUE, 0, op, "%s", tmp); 943 new_draw_info_format(NDI_UNIQUE, 0, op, "%s", tmp);
978 944
979 if (map->shopmax) 945 if (map->shopmax)
980 new_draw_info_format(NDI_UNIQUE,0,op,"It won't trade for items above %s.", 946 new_draw_info_format(NDI_UNIQUE,0,op,"It won't trade for items above %s.",
981 cost_string_from_value(map->shopmax)); 947 cost_string_from_value(map->shopmax, 0));
982 if (map->shopmin) 948 if (map->shopmin)
983 new_draw_info_format(NDI_UNIQUE,0,op,"It won't trade in items worth less than %s.", 949 new_draw_info_format(NDI_UNIQUE,0,op,"It won't trade in items worth less than %s.",
984 cost_string_from_value(map->shopmin)); 950 cost_string_from_value(map->shopmin, 0));
985 if (map->shopgreed) { 951 if (map->shopgreed) {
986 if (map->shopgreed >2.0) 952 if (map->shopgreed >2.0)
987 new_draw_info(NDI_UNIQUE,0,op,"It tends to overcharge massively."); 953 new_draw_info(NDI_UNIQUE,0,op,"It tends to overcharge massively.");
988 else if (map->shopgreed >1.5) 954 else if (map->shopgreed >1.5)
989 new_draw_info(NDI_UNIQUE,0,op,"It tends to overcharge substantially."); 955 new_draw_info(NDI_UNIQUE,0,op,"It tends to overcharge substantially.");

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines