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.7 by root, Sun Jun 25 22:19:42 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.7 2006/06/25 22:19:42 root 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
78 * 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
79 * thus remained 0. 79 * thus remained 0.
80 * 80 *
81 * Mark Wedel (mwedel@pyramid.com) 81 * Mark Wedel (mwedel@pyramid.com)
82 */ 82 */
83
84static uint64 approx_range;
85
83uint64 query_cost(const object *tmp, object *who, int flag) { 86uint64 query_cost(const object *tmp, object *who, int flag) {
84 uint64 val; 87 uint64 val;
85 int number; /* used to better calculate value */ 88 int number; /* used to better calculate value */
86 int no_bargain; 89 int no_bargain;
87 int identified; 90 int identified;
88 int not_cursed; 91 int not_cursed;
89 int approximate; 92 int approximate;
90 int shop; 93 int shop;
91 double diff; 94 double diff;
95
96 approx_range = 0;
92 97
93 no_bargain = flag & F_NO_BARGAIN; 98 no_bargain = flag & F_NO_BARGAIN;
94 identified = flag & F_IDENTIFIED; 99 identified = flag & F_IDENTIFIED;
95 not_cursed = flag & F_NOT_CURSED; 100 not_cursed = flag & F_NOT_CURSED;
96 approximate = flag & F_APPROX; 101 approximate = flag & F_APPROX;
120 LOG(llevError, "Asking for buy-value of unidentified object.\n"); 125 LOG(llevError, "Asking for buy-value of unidentified object.\n");
121 val = tmp->arch->clone.value * 50 * number; 126 val = tmp->arch->clone.value * 50 * number;
122 } 127 }
123 else { /* Trying to sell something, or get true value */ 128 else { /* Trying to sell something, or get true value */
124 if (tmp->type == POTION) 129 if (tmp->type == POTION)
125 val = number * 1000; /* Don't want to give anything away */ 130 val = number * 40; /* Don't want to give anything away */
126 else { 131 else {
127 /* 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
128 * unknown objects 133 * unknown objects
129 */ 134 */
130 if (QUERY_FLAG(tmp, FLAG_BEEN_APPLIED)) 135 if (QUERY_FLAG(tmp, FLAG_BEEN_APPLIED))
175 else /* if not identified, presume one charge */ 180 else /* if not identified, presume one charge */
176 val/=50; 181 val/=50;
177 } 182 }
178 183
179 /* Limit amount of money you can get for really great items. */ 184 /* Limit amount of money you can get for really great items. */
180 if (flag==F_TRUE || flag==F_SELL) 185 if (flag==F_SELL)
181 val=value_limit(val, number, who, shop); 186 val=value_limit(val, number, who, shop);
182 187
183 // use a nonlinear price adjustment. as my predecessor said, don't change 188 // use a nonlinear price adjustment. as my predecessor said, don't change
184 // the archetypes, its work required for balancing, and we don't care. 189 // the archetypes, its work required for balancing, and we don't care.
185 val = pow (val / 128., 1.4) * 128.; 190 //val = pow (val, 1.05);
186 191
187 /* This modification is for bargaining skill. 192 /* This modification is for bargaining skill.
188 * Now only players with max level in bargaining 193 * Now only players with max level in bargaining
189 * AND Cha = 30 will get optimal price. 194 * AND Cha = 30 will get optimal price.
190 * Thus charisma will never get useless. 195 * Thus charisma will never get useless.
219 224
220 /* ratio determines how much of the price modification 225 /* ratio determines how much of the price modification
221 * will come from the basic stat charisma 226 * will come from the basic stat charisma
222 * the rest will come from the level in bargaining skill 227 * the rest will come from the level in bargaining skill
223 */ 228 */
224 const double cha_ratio = 0.35; 229 const double cha_ratio = 0.40;
225 230
226 diff = no_bargain ? 1.0 : 1. - pow (lev_bargain / (double)settings.max_level, 0.25); 231 diff = no_bargain ? 1.0 : 1. - pow (lev_bargain / (double)settings.max_level, 0.25);
227 232
228 diff = (1. - cha_ratio) * diff 233 diff = (1. - cha_ratio) * diff
229 + cha_ratio * (cha_bonus[who->stats.Cha] - 1.) / (cha_bonus[who->stats.Cha] + 1.); 234 + cha_ratio * (cha_bonus[who->stats.Cha] - 1.) / (cha_bonus[who->stats.Cha] + 1.);
230 235
231 diff = .02 + (1. - .02) * diff; 236 diff = .02 + (.80 - .02) * diff;
232 237
233 if (flag == F_BUY) val = val * (1. + diff); 238 if (flag == F_BUY) val += val * diff;
234 else if (flag == F_SELL) val = val * (1. - diff); 239 else if (flag == F_SELL) val -= val * diff;
235 240
236 /* If we are approximating, then the value returned should be 241 // now find a price range. the less good we can judge, the larger the range is
237 * allowed to be wrong however merely using a random number each 242 // then the range is adjusted randomly around the correct value
238 * time will not be sufficiant, as then multiple examinations
239 * would give different answers, so we'll use the count
240 * instead. Using the count, generate a value between -1
241 * and 1, we then divide by the square root of the
242 * appropriate identification skills, so that higher level players
243 * get better estimates.
244 */
245
246 if (approximate) 243 if (approximate)
247 val += val * ((((int)(tmp->count & 1023) - 512) / 512.) / sqrt (lev_identify * 0.6 + 0.3)); 244 approx_range = val / sqrt (lev_identify * 3 + 1);
248 } 245 }
249 246
250 /* 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
251 * overflow of diff above. That shoudl only happen if 248 * overflow of diff above. That shoudl only happen if
252 * we are selling objects - in that case, the person just 249 * we are selling objects - in that case, the person just
322 * 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
323 * coins, there are certainly issues - the easiest fix at that 320 * coins, there are certainly issues - the easiest fix at that
324 * time is to add a higher denomination (mithril piece with 321 * time is to add a higher denomination (mithril piece with
325 * 10,000 silver or something) 322 * 10,000 silver or something)
326 */ 323 */
327static const char *cost_string_from_value(uint64 cost) 324static const char *cost_string_from_value(uint64 cost, int approx)
328{ 325{
329 static char buf[MAX_BUF]; 326 static char buf[MAX_BUF];
330 archetype *coin, *next_coin; 327 archetype *coin, *next_coin;
331 char *endbuf;
332 int num, cointype = 0; 328 int num, cointype = 0;
333 329
334 coin = find_next_coin(cost, &cointype); 330 coin = find_next_coin(cost, &cointype);
335 if (coin == NULL) 331 if (coin == NULL)
336 return "nothing"; 332 return "nothing";
344 strcpy(buf,"an unimaginable sum of money."); 340 strcpy(buf,"an unimaginable sum of money.");
345 return buf; 341 return buf;
346 } 342 }
347 343
348 cost -= (uint64)num * (uint64)coin->clone.value; 344 cost -= (uint64)num * (uint64)coin->clone.value;
349 if (num == 1) 345 sprintf(buf, "%d %s", num, num > 1 ? coin->clone.name_pl : coin->clone.name);
350 sprintf(buf, "1 %s", coin->clone.name);
351 else
352 sprintf(buf, "%d %s", num, coin->clone.name_pl);
353 346
354 next_coin = find_next_coin(cost, &cointype); 347 next_coin = find_next_coin(cost, &cointype);
355 if (next_coin == NULL) 348 if (next_coin == NULL || approx)
356 return buf; 349 return buf;
357
358 endbuf = buf + strlen(buf);
359 350
360 coin = next_coin; 351 coin = next_coin;
361 num = cost / coin->clone.value; 352 num = cost / coin->clone.value;
362 cost -= (uint64)num * (uint64)coin->clone.value; 353 cost -= (uint64)num * (uint64)coin->clone.value;
363 354
364 strcat(endbuf, " and "); endbuf += 5; 355 sprintf (buf + strlen (buf), " and %d %s", num, num > 1 ? coin->clone.name_pl : coin->clone.name);
365 if (num == 1)
366 sprintf(endbuf, "1 %s", coin->clone.name);
367 else
368 sprintf(endbuf, "%d %s", num, coin->clone.name_pl);
369 356
370 return buf; 357 return buf;
371} 358}
372 359
373const char *query_cost_string(const object *tmp,object *who,int flag) { 360const char *query_cost_string(const object *tmp,object *who,int flag) {
414 sprintf(buf, "a vast quantity of %s", coin->clone.name_pl); 401 sprintf(buf, "a vast quantity of %s", coin->clone.name_pl);
415 return buf; 402 return buf;
416 } 403 }
417 } 404 }
418 } 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 }
419 } 419 }
420
420 return cost_string_from_value(real_value); 421 return cost_string_from_value (real_value, 0);
421} 422}
422 423
423/* This function finds out how much money the player is carrying, 424/* This function finds out how much money the player is carrying,
424 * including what is in containers. 425 * including what is in containers.
425 */ 426 */
649 int denominations = 0; 650 int denominations = 0;
650 int has_coins = NUM_COINS; 651 int has_coins = NUM_COINS;
651 char cost[MAX_BUF]; 652 char cost[MAX_BUF];
652 char missing[MAX_BUF]; 653 char missing[MAX_BUF];
653 654
654 sprintf(cost, "%s", cost_string_from_value(unpaid_price)); 655 sprintf(cost, "%s", cost_string_from_value (unpaid_price, 0));
655 sprintf(missing, "%s", cost_string_from_value(unpaid_price - player_wealth)); 656 sprintf(missing, "%s", cost_string_from_value (unpaid_price - player_wealth, 0));
656 657
657 sprintf(buf, "You have %d unpaid items that would cost you %s. You need another %s to be able to afford that.", 658 sprintf(buf, "You have %d unpaid items that would cost you %s. You need another %s to be able to afford that.",
658 unpaid_count, cost, missing); 659 unpaid_count, cost, missing);
659 new_draw_info(NDI_UNIQUE, 0, pl, buf); 660 new_draw_info(NDI_UNIQUE, 0, pl, buf);
660 return 0; 661 return 0;
693 buf[MAX_BUF-1] = '\0'; 694 buf[MAX_BUF-1] = '\0';
694 if(!pay_for_item(op,pl)) { 695 if(!pay_for_item(op,pl)) {
695 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);
696 CLEAR_FLAG(op, FLAG_UNPAID); 697 CLEAR_FLAG(op, FLAG_UNPAID);
697 new_draw_info_format(NDI_UNIQUE, 0, pl, 698 new_draw_info_format(NDI_UNIQUE, 0, pl,
698 "You lack %s to buy %s.", cost_string_from_value(i), 699 "You lack %s to buy %s.", cost_string_from_value (i, 0),
699 query_name(op)); 700 query_name(op));
700 SET_FLAG(op, FLAG_UNPAID); 701 SET_FLAG(op, FLAG_UNPAID);
701 return 0; 702 return 0;
702 } else { 703 } else {
703 object *tmp; 704 object *tmp;
891static 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) {
892 uint64 newval, unit_price; 893 uint64 newval, unit_price;
893 mapstruct *map; 894 mapstruct *map;
894 unit_price=val/quantity; 895 unit_price=val/quantity;
895 if (!isshop || !who) { 896 if (!isshop || !who) {
896 if (unit_price > 10000) 897 if (unit_price > 250000)
897 newval=8000+isqrt(unit_price)*20; 898 newval = 250000. - pow (250000., .75) * 65. + pow (unit_price, .75) * 65.;
898 else 899 else
899 newval=unit_price; 900 newval=unit_price;
900 } else { 901 } else {
901 if (!who->map) { 902 if (!who->map) {
902 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);
904 } 905 }
905 map=who->map; 906 map=who->map;
906 if (map->shopmin && unit_price < map->shopmin) return 0; 907 if (map->shopmin && unit_price < map->shopmin) return 0;
907 else if (map->shopmax && unit_price > map->shopmax/2) 908 else if (map->shopmax && unit_price > map->shopmax/2)
908 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);
909 else if (unit_price>10000) 910 else if (unit_price > 250000)
910 newval=8000+isqrt(unit_price)*20; 911 newval = 250000. - pow (250000., .75) * 65. + pow (unit_price, .75) * 65.;
911 else 912 else
912 newval=unit_price; 913 newval=unit_price;
913 } 914 }
914 newval *= quantity; 915 newval *= quantity;
915 return newval; 916 return newval;
941 make_list_like(tmp); 942 make_list_like(tmp);
942 new_draw_info_format(NDI_UNIQUE, 0, op, "%s", tmp); 943 new_draw_info_format(NDI_UNIQUE, 0, op, "%s", tmp);
943 944
944 if (map->shopmax) 945 if (map->shopmax)
945 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.",
946 cost_string_from_value(map->shopmax)); 947 cost_string_from_value(map->shopmax, 0));
947 if (map->shopmin) 948 if (map->shopmin)
948 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.",
949 cost_string_from_value(map->shopmin)); 950 cost_string_from_value(map->shopmin, 0));
950 if (map->shopgreed) { 951 if (map->shopgreed) {
951 if (map->shopgreed >2.0) 952 if (map->shopgreed >2.0)
952 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.");
953 else if (map->shopgreed >1.5) 954 else if (map->shopgreed >1.5)
954 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