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.10 by root, Sun Sep 10 15:59:57 2006 UTC vs.
Revision 1.14 by root, Tue Sep 12 19:20:08 2006 UTC

1 1
2/* 2/*
3 * static char *rcsid_shop_c = 3 * static char *rcsid_shop_c =
4 * "$Id: shop.C,v 1.10 2006/09/10 15:59:57 root Exp $"; 4 * "$Id: shop.C,v 1.14 2006/09/12 19:20:08 root Exp $";
5 */ 5 */
6 6
7/* 7/*
8 CrossFire, A Multiplayer game for X-windows 8 CrossFire, A Multiplayer game for X-windows
9 9
47#define SPECIALISATION_EFFECT 0.5 47#define SPECIALISATION_EFFECT 0.5
48 48
49/* price a shopkeeper will give someone they neither like nor dislike */ 49/* price a shopkeeper will give someone they neither like nor dislike */
50#define NEUTRAL_RATIO 0.8 50#define NEUTRAL_RATIO 0.8
51 51
52static uint64 pay_from_container (object *pl, object *pouch, uint64 to_pay); 52static void pay_from_container (object *pl, object *pouch, sint64 &to_pay);
53static uint64 value_limit (uint64 val, int quantity, const object *who, int isshop); 53static sint64 value_limit (sint64 val, int quantity, const object *who, int isshop);
54static double shop_specialisation_ratio (const object *item, const mapstruct *map); 54static double shop_specialisation_ratio (const object *item, const mapstruct *map);
55static double shop_greed (const mapstruct *map); 55static double shop_greed (const mapstruct *map);
56 56
57#define NUM_COINS 4 /* number of coin types */ 57#define NUM_COINS 4 /* number of coin types */
58static const char *const coins[] = { "royalty", "platinacoin", "goldcoin", "silvercoin", NULL }; 58static const char *const coins[] = { "royalty", "platinacoin", "goldcoin", "silvercoin", NULL };
80 * thus remained 0. 80 * thus remained 0.
81 * 81 *
82 * Mark Wedel (mwedel@pyramid.com) 82 * Mark Wedel (mwedel@pyramid.com)
83 */ 83 */
84 84
85static uint64 approx_range; 85static sint64 approx_range;
86 86
87uint64 87sint64
88query_cost (const object *tmp, object *who, int flag) 88query_cost (const object *tmp, object *who, int flag)
89{ 89{
90 double val; 90 double val;
91 int number; /* used to better calculate value */ 91 int number; /* used to better calculate value */
92 int no_bargain; 92 int no_bargain;
104 approximate = flag & F_APPROX; 104 approximate = flag & F_APPROX;
105 shop = flag & F_SHOP; 105 shop = flag & F_SHOP;
106 flag &= ~(F_NO_BARGAIN | F_IDENTIFIED | F_NOT_CURSED | F_APPROX | F_SHOP); 106 flag &= ~(F_NO_BARGAIN | F_IDENTIFIED | F_NOT_CURSED | F_APPROX | F_SHOP);
107 107
108 if (tmp->type == MONEY) 108 if (tmp->type == MONEY)
109 return (tmp->nrof * tmp->value); 109 return tmp->nrof * tmp->value;
110
110 if (tmp->type == GEM) 111 if (tmp->type == GEM)
111 { 112 {
112 if (flag == F_TRUE) 113 if (flag == F_TRUE)
113 return (tmp->nrof * tmp->value); 114 return (tmp->nrof * tmp->value);
115
114 if (flag == F_BUY) 116 if (flag == F_BUY)
115 return (uint64) (1.03 * tmp->nrof * tmp->value); 117 return (sint64) (1.03 * tmp->nrof * tmp->value);
118
116 if (flag == F_SELL) 119 if (flag == F_SELL)
117 return (uint64) (0.97 * tmp->nrof * tmp->value); 120 return (sint64) (0.97 * tmp->nrof * tmp->value);
121
118 LOG (llevError, "Query_cost: Gem type with unknown flag : %d\n", flag); 122 LOG (llevError, "Query_cost: Gem type with unknown flag %d: %s\n", flag, tmp->debug_desc ());
119 return 0; 123 return 0;
120 } 124 }
125
121 number = tmp->nrof; 126 number = tmp->nrof;
122 if (number == 0) 127 if (number == 0)
123 number = 1; 128 number = 1;
124 if (QUERY_FLAG (tmp, FLAG_IDENTIFIED) || !need_identify (tmp) || identified) 129 if (QUERY_FLAG (tmp, FLAG_IDENTIFIED) || !need_identify (tmp) || identified)
125 { 130 {
200 val /= 50; 205 val /= 50;
201 } 206 }
202 207
203 /* Limit amount of money you can get for really great items. */ 208 /* Limit amount of money you can get for really great items. */
204 if (flag == F_SELL) 209 if (flag == F_SELL)
205 val = value_limit ((uint64) val, number, who, shop); 210 val = value_limit ((sint64) val, number, who, shop);
206 211
207 // use a nonlinear price adjustment. as my predecessor said, don't change 212 // use a nonlinear price adjustment. as my predecessor said, don't change
208 // the archetypes, its work required for balancing, and we don't care. 213 // the archetypes, its work required for balancing, and we don't care.
209 //val = pow (val, 1.05); 214 //val = pow (val, 1.05);
210 215
224 const typedata *tmptype; 229 const typedata *tmptype;
225 230
226 tmptype = get_typedata (tmp->type); 231 tmptype = get_typedata (tmp->type);
227 232
228 if (find_skill_by_number (who, SK_BARGAINING)) 233 if (find_skill_by_number (who, SK_BARGAINING))
229 {
230 lev_bargain = find_skill_by_number (who, SK_BARGAINING)->level; 234 lev_bargain = find_skill_by_number (who, SK_BARGAINING)->level;
231 } 235
232 if (tmptype) 236 if (tmptype)
233 { 237 {
234 idskill1 = tmptype->identifyskill; 238 idskill1 = tmptype->identifyskill;
239
235 if (idskill1) 240 if (idskill1)
236 { 241 {
237 idskill2 = tmptype->identifyskill2; 242 idskill2 = tmptype->identifyskill2;
243
238 if (find_skill_by_number (who, idskill1)) 244 if (find_skill_by_number (who, idskill1))
239 {
240 lev_identify = find_skill_by_number (who, idskill1)->level; 245 lev_identify = find_skill_by_number (who, idskill1)->level;
241 } 246
242 if (idskill2 && find_skill_by_number (who, idskill2)) 247 if (idskill2 && find_skill_by_number (who, idskill2))
243 {
244 lev_identify += find_skill_by_number (who, idskill2)->level; 248 lev_identify += find_skill_by_number (who, idskill2)->level;
245 }
246 } 249 }
247 } 250 }
248 else 251 else
249 LOG (llevError, "Query_cost: item %s hasn't got a valid type\n", &tmp->name); 252 LOG (llevError, "Query_cost: item %s hasn't got a valid type\n", tmp->debug_desc ());
250 253
251 /* ratio determines how much of the price modification 254 /* ratio determines how much of the price modification
252 * will come from the basic stat charisma 255 * will come from the basic stat charisma
253 * the rest will come from the level in bargaining skill 256 * the rest will come from the level in bargaining skill
254 */ 257 */
266 val -= (val * diff); 269 val -= (val * diff);
267 270
268 // now find a price range. the less good we can judge, the larger the range is 271 // now find a price range. the less good we can judge, the larger the range is
269 // then the range is adjusted randomly around the correct value 272 // then the range is adjusted randomly around the correct value
270 if (approximate) 273 if (approximate)
271 approx_range = uint64 (val / sqrt (lev_identify * 3 + 1)); 274 approx_range = sint64 (val / sqrt (lev_identify * 3 + 1));
272 } 275 }
273 276
274 /* I don't think this should really happen - if it does, it indicates and 277 /* I don't think this should really happen - if it does, it indicates and
275 * overflow of diff above. That shoudl only happen if 278 * overflow of diff above. That shoudl only happen if
276 * we are selling objects - in that case, the person just 279 * we are selling objects - in that case, the person just
315 * pointful, and could give fun with rounding. 318 * pointful, and could give fun with rounding.
316 */ 319 */
317 if (who->map->path != NULL && val > 50) 320 if (who->map->path != NULL && val > 50)
318 val = (val + 0.05 * (sint64) val * cos (tmp->count + strlen (who->map->path))); 321 val = (val + 0.05 * (sint64) val * cos (tmp->count + strlen (who->map->path)));
319 } 322 }
320 return (uint64) val; 323 return (sint64) val;
321} 324}
322 325
323/* Find the coin type that is worth more the 'c'. Starts at the 326/* Find the coin type that is worth more the 'c'. Starts at the
324 * cointype placement. 327 * cointype placement.
325 */ 328 */
326 329
327static archetype * 330static archetype *
328find_next_coin (uint64 c, int *cointype) 331find_next_coin (sint64 c, int *cointype)
329{ 332{
330 archetype *coin; 333 archetype *coin;
331 334
332 do 335 do
333 { 336 {
336 coin = find_archetype (coins[*cointype]); 339 coin = find_archetype (coins[*cointype]);
337 if (coin == NULL) 340 if (coin == NULL)
338 return NULL; 341 return NULL;
339 *cointype += 1; 342 *cointype += 1;
340 } 343 }
341 while ((uint64) coin->clone.value > c); 344 while (coin->clone.value > c);
342 345
343 return coin; 346 return coin;
344} 347}
345 348
346/* This returns a string of how much something is worth based on 349/* This returns a string of how much something is worth based on
352 * coins, there are certainly issues - the easiest fix at that 355 * coins, there are certainly issues - the easiest fix at that
353 * time is to add a higher denomination (mithril piece with 356 * time is to add a higher denomination (mithril piece with
354 * 10,000 silver or something) 357 * 10,000 silver or something)
355 */ 358 */
356const char * 359const char *
357cost_string_from_value (uint64 cost, int approx) 360cost_string_from_value (sint64 cost, int approx)
358{ 361{
359 static char buf[MAX_BUF]; 362 static char buf[MAX_BUF];
360 archetype *coin, *next_coin; 363 archetype *coin, *next_coin;
361 int num, cointype = 0; 364 int num, cointype = 0;
362 365
373 { 376 {
374 strcpy (buf, "an unimaginable sum of money"); 377 strcpy (buf, "an unimaginable sum of money");
375 return buf; 378 return buf;
376 } 379 }
377 380
378 cost -= (uint64) num *(uint64) coin->clone.value; 381 cost -= num * (sint64)coin->clone.value;
379 382
380 sprintf (buf, "%d %s", num, num > 1 ? &coin->clone.name_pl : &coin->clone.name); 383 sprintf (buf, "%d %s", num, num > 1 ? &coin->clone.name_pl : &coin->clone.name);
381 384
382 next_coin = find_next_coin (cost, &cointype); 385 next_coin = find_next_coin (cost, &cointype);
383 if (next_coin == NULL || approx) 386 if (next_coin == NULL || approx)
384 return buf; 387 return buf;
385 388
386 coin = next_coin; 389 coin = next_coin;
387 num = cost / coin->clone.value; 390 num = cost / coin->clone.value;
388 cost -= (uint64) num *(uint64) coin->clone.value; 391 cost -= num * (sint64)coin->clone.value;
389 392
390 sprintf (buf + strlen (buf), " and %d %s", num, num > 1 ? &coin->clone.name_pl : &coin->clone.name); 393 sprintf (buf + strlen (buf), " and %d %s", num, num > 1 ? &coin->clone.name_pl : &coin->clone.name);
391 394
392 return buf; 395 return buf;
393} 396}
394 397
395const char * 398const char *
396query_cost_string (const object *tmp, object *who, int flag) 399query_cost_string (const object *tmp, object *who, int flag)
397{ 400{
398 uint64 real_value = query_cost (tmp, who, flag); 401 sint64 real_value = query_cost (tmp, who, flag);
399 int idskill1 = 0; 402 int idskill1 = 0;
400 int idskill2 = 0; 403 int idskill2 = 0;
401 const typedata *tmptype; 404 const typedata *tmptype;
402 405
403 tmptype = get_typedata (tmp->type); 406 tmptype = get_typedata (tmp->type);
449 452
450 int hash = ((unsigned int) tmp->count * 174364621) & 1023; 453 int hash = ((unsigned int) tmp->count * 174364621) & 1023;
451 454
452 if (approx_range) 455 if (approx_range)
453 { 456 {
454 uint64 lo = (sint64) real_value - (approx_range * hash >> 10); 457 sint64 lo = (sint64) real_value - (approx_range * hash >> 10);
455 static char buf[MAX_BUF]; 458 static char buf[MAX_BUF];
456 459
457 sprintf (buf, "between %s", cost_string_from_value (lo, 1)); 460 sprintf (buf, "between %s", cost_string_from_value (lo, 1));
458 sprintf (buf + strlen (buf), " and %s", cost_string_from_value (lo + approx_range, 1)); 461 sprintf (buf + strlen (buf), " and %s", cost_string_from_value (lo + approx_range, 1));
459 462
465} 468}
466 469
467/* This function finds out how much money the player is carrying, 470/* This function finds out how much money the player is carrying,
468 * including what is in containers. 471 * including what is in containers.
469 */ 472 */
470uint64 473sint64
471query_money (const object *op) 474query_money (const object *op)
472{ 475{
473 object *tmp; 476 object *tmp;
474 uint64 total = 0; 477 sint64 total = 0;
475 478
476 if (op->type != PLAYER && op->type != CONTAINER) 479 if (op->type != PLAYER && op->type != CONTAINER)
477 { 480 {
478 LOG (llevError, "Query money called with non player/container\n"); 481 LOG (llevError, "Query money called with non player/container\n");
479 return 0; 482 return 0;
480 } 483 }
484
481 for (tmp = op->inv; tmp; tmp = tmp->below) 485 for (tmp = op->inv; tmp; tmp = tmp->below)
482 {
483 if (tmp->type == MONEY) 486 if (tmp->type == MONEY)
484 {
485 total += (uint64) tmp->nrof * (uint64) tmp->value; 487 total += tmp->nrof * (sint64)tmp->value;
486 }
487 else if (tmp->type == CONTAINER && QUERY_FLAG (tmp, FLAG_APPLIED) && (tmp->race == NULL || strstr (tmp->race, "gold"))) 488 else if (tmp->type == CONTAINER && QUERY_FLAG (tmp, FLAG_APPLIED) && (tmp->race == NULL || strstr (tmp->race, "gold")))
488 {
489 total += query_money (tmp); 489 total += query_money (tmp);
490 } 490
491 }
492 return total; 491 return total;
493} 492}
494 493
495/* TCHIZE: This function takes the amount of money from the 494/* TCHIZE: This function takes the amount of money from the
496 * the player inventory and from it's various pouches using the 495 * the player inventory and from it's various pouches using the
497 * pay_from_container function. 496 * pay_from_container function.
498 * returns 0 if not possible. 1 if success 497 * returns 0 if not possible. 1 if success
499 */ 498 */
500int 499int
501pay_for_amount (uint64 to_pay, object *pl) 500pay_for_amount (sint64 to_pay, object *pl)
502{ 501{
503 object *pouch; 502 object *pouch;
504 503
505 if (to_pay == 0) 504 if (to_pay == 0)
506 return 1; 505 return 1;
506
507 if (to_pay > query_money (pl)) 507 if (to_pay > query_money (pl))
508 return 0; 508 return 0;
509 509
510 to_pay = pay_from_container (pl, pl, to_pay); 510 pay_from_container (pl, pl, to_pay);
511 511
512 for (pouch = pl->inv; (pouch != NULL) && (to_pay > 0); pouch = pouch->below) 512 for (pouch = pl->inv; pouch && to_pay; pouch = pouch->below)
513 {
514 if (pouch->type == CONTAINER && QUERY_FLAG (pouch, FLAG_APPLIED) && (pouch->race == NULL || strstr (pouch->race, "gold"))) 513 if (pouch->type == CONTAINER && QUERY_FLAG (pouch, FLAG_APPLIED) && (pouch->race == NULL || strstr (pouch->race, "gold")))
515 {
516 to_pay = pay_from_container (pl, pouch, to_pay); 514 pay_from_container (pl, pouch, to_pay);
517 } 515
518 }
519 fix_player (pl); 516 fix_player (pl);
520 return 1; 517 return 1;
521} 518}
522 519
523/* DAMN: This is now a wrapper for pay_from_container, which is 520/* DAMN: This is now a wrapper for pay_from_container, which is
526 * of the price was paid from. 523 * of the price was paid from.
527 */ 524 */
528int 525int
529pay_for_item (object *op, object *pl) 526pay_for_item (object *op, object *pl)
530{ 527{
531 uint64 to_pay = query_cost (op, pl, F_BUY | F_SHOP); 528 sint64 to_pay = query_cost (op, pl, F_BUY | F_SHOP);
532 object *pouch; 529 object *pouch;
533 uint64 saved_money; 530 sint64 saved_money;
534 531
535 if (to_pay == 0) 532 if (to_pay == 0)
536 return 1; 533 return 1;
534
537 if (to_pay > query_money (pl)) 535 if (to_pay > query_money (pl))
538 return 0; 536 return 0;
539 537
540 /* We compare the paid price with the one for a player 538 /* We compare the paid price with the one for a player
541 * without bargaining skill. 539 * without bargaining skill.
544 saved_money = query_cost (op, pl, F_BUY | F_NO_BARGAIN | F_SHOP) - to_pay; 542 saved_money = query_cost (op, pl, F_BUY | F_NO_BARGAIN | F_SHOP) - to_pay;
545 543
546 if (saved_money > 0) 544 if (saved_money > 0)
547 change_exp (pl, saved_money, "bargaining", SK_EXP_NONE); 545 change_exp (pl, saved_money, "bargaining", SK_EXP_NONE);
548 546
549 to_pay = pay_from_container (pl, pl, to_pay); 547 pay_from_container (pl, pl, to_pay);
550 548
551 for (pouch = pl->inv; (pouch != NULL) && (to_pay > 0); pouch = pouch->below) 549 for (pouch = pl->inv; pouch && to_pay; pouch = pouch->below)
552 {
553 if (pouch->type == CONTAINER && QUERY_FLAG (pouch, FLAG_APPLIED) && (pouch->race == NULL || strstr (pouch->race, "gold"))) 550 if (pouch->type == CONTAINER && QUERY_FLAG (pouch, FLAG_APPLIED) && (pouch->race == NULL || strstr (pouch->race, "gold")))
554 {
555 to_pay = pay_from_container (pl, pouch, to_pay); 551 pay_from_container (pl, pouch, to_pay);
556 } 552
557 }
558 if (settings.real_wiz == FALSE && QUERY_FLAG (pl, FLAG_WAS_WIZ)) 553 if (settings.real_wiz == FALSE && QUERY_FLAG (pl, FLAG_WAS_WIZ))
559 SET_FLAG (op, FLAG_WAS_WIZ); 554 SET_FLAG (op, FLAG_WAS_WIZ);
555
560 fix_player (pl); 556 fix_player (pl);
561 return 1; 557 return 1;
562} 558}
563 559
564/* This pays for the item, and takes the proper amount of money off 560/* This pays for the item, and takes the proper amount of money off
573 * 569 *
574 * pouch is the container (pouch or player) to remove the coins from. 570 * pouch is the container (pouch or player) to remove the coins from.
575 * to_pay is the required amount. 571 * to_pay is the required amount.
576 * returns the amount still missing after using "pouch". 572 * returns the amount still missing after using "pouch".
577 */ 573 */
578static uint64 574static void
579pay_from_container (object *pl, object *pouch, uint64 to_pay) 575pay_from_container (object *pl, object *pouch, sint64 &to_pay)
580{ 576{
581 int count, i; 577 int count, i;
582 uint64 remain; 578 object *tmp, *next;
583 object *tmp, *coin_objs[NUM_COINS], *next;
584 archetype *at; 579 archetype *at;
585 580
586 if (pouch->type != PLAYER && pouch->type != CONTAINER) 581 if (pouch->type != PLAYER && pouch->type != CONTAINER)
587 return to_pay; 582 return;
588 583
589 remain = to_pay; 584 object *coin_objs[NUM_COINS] = { 0 };
590 for (i = 0; i < NUM_COINS; i++)
591 coin_objs[i] = NULL;
592 585
593 /* This hunk should remove all the money objects from the player/container */ 586 /* This hunk should remove all the money objects from the player/container */
594 for (tmp = pouch->inv; tmp; tmp = next) 587 for (tmp = pouch->inv; tmp; tmp = next)
595 { 588 {
596 next = tmp->below; 589 next = tmp->below;
597 590
598 if (tmp->type == MONEY) 591 if (tmp->type == MONEY)
599 { 592 {
600 for (i = 0; i < NUM_COINS; i++) 593 for (i = 0; i < NUM_COINS; i++)
601 { 594 {
602 if (!strcmp (coins[NUM_COINS - 1 - i], tmp->arch->name) && (tmp->value == tmp->arch->clone.value)) 595 if (tmp->value == tmp->arch->clone.value && !strcmp (coins[NUM_COINS - 1 - i], tmp->arch->name))
603 { 596 {
604
605 /* This should not happen, but if it does, just * 597 // This should not happen, but if it does, just merge the two.
606 * merge the two. */
607 if (coin_objs[i] != NULL) 598 if (coin_objs [i])
608 { 599 {
609 LOG (llevError, "%s has two money entries of (%s)\n", &pouch->name, coins[NUM_COINS - 1 - i]); 600 LOG (llevError, "%s has two money entries of (%s)\n", &pouch->name, coins[NUM_COINS - 1 - i]);
610 remove_ob (tmp); 601 remove_ob (tmp);
611 coin_objs[i]->nrof += tmp->nrof; 602 coin_objs[i]->nrof += tmp->nrof;
612 esrv_del_item (pl->contr, tmp->count); 603 esrv_del_item (pl->contr, tmp->count);
613 free_object (tmp); 604 free_object (tmp);
614 } 605 }
615 else 606 else
616 { 607 {
617 remove_ob (tmp); 608 remove_ob (tmp);
609
618 if (pouch->type == PLAYER) 610 if (pouch->type == PLAYER)
619 esrv_del_item (pl->contr, tmp->count); 611 esrv_del_item (pl->contr, tmp->count);
612
620 coin_objs[i] = tmp; 613 coin_objs[i] = tmp;
621 } 614 }
615
622 break; 616 break;
623 } 617 }
624 } 618 }
619
625 if (i == NUM_COINS) 620 if (i == NUM_COINS)
626 LOG (llevError, "in pay_for_item: Did not find string match for %s\n", &tmp->arch->name); 621 LOG (llevError, "in pay_for_item: Did not find string match for %s\n", &tmp->arch->name);
627 } 622 }
628 } 623 }
629 624
630 /* Fill in any gaps in the coin_objs array - needed to make change. */ 625 /* Fill in any gaps in the coin_objs array - needed to make change. */
631 /* Note that the coin_objs array goes from least value to greatest value */ 626 /* Note that the coin_objs array goes from least value to greatest value */
632 for (i = 0; i < NUM_COINS; i++) 627 for (i = 0; i < NUM_COINS; i++)
633 if (coin_objs[i] == NULL) 628 if (!coin_objs[i])
634 { 629 {
635 at = find_archetype (coins[NUM_COINS - 1 - i]); 630 at = find_archetype (coins[NUM_COINS - 1 - i]);
631
636 if (at == NULL) 632 if (at == NULL)
637 LOG (llevError, "Could not find %s archetype\n", coins[NUM_COINS - 1 - i]); 633 LOG (llevError, "Could not find %s archetype\n", coins[NUM_COINS - 1 - i]);
634
638 coin_objs[i] = arch_to_object (at); 635 coin_objs[i] = arch_to_object (at);
639 coin_objs[i]->nrof = 0; 636 coin_objs[i]->nrof = 0;
640 } 637 }
641 638
642 for (i = 0; i < NUM_COINS; i++) 639 for (i = 0; i < NUM_COINS; i++)
643 { 640 {
644 int num_coins; 641 object &coin = *coin_objs[i];
642 sint64 num_coins = min ((to_pay + coin.value - 1) / coin.value, coin.nrof);
643 to_pay -= num_coins * coin.value;
645 644
646 if (coin_objs[i]->nrof * coin_objs[i]->value > remain)
647 {
648 num_coins = remain / coin_objs[i]->value;
649 if ((uint64) num_coins * (uint64) coin_objs[i]->value < remain)
650 num_coins++;
651 }
652 else
653 {
654 num_coins = coin_objs[i]->nrof;
655 }
656 remain -= (sint64) num_coins *(sint64) coin_objs[i]->value;
657
658 coin_objs[i]->nrof -= num_coins; 645 coin.nrof -= num_coins;
659 /* Now start making change. Start at the coin value 646 /* Now start making change. Start at the coin value
660 * below the one we just did, and work down to 647 * below the one we just did, and work down to
661 * the lowest value. 648 * the lowest value.
662 */ 649 */
663 count = i - 1; 650 count = i - 1;
651
664 while (remain < 0 && count >= 0) 652 while (to_pay < 0 && count >= 0)
665 { 653 {
666 num_coins = -remain / coin_objs[count]->value; 654 num_coins = (-to_pay) / coin_objs[count]->value;
667 coin_objs[count]->nrof += num_coins; 655 coin_objs[count]->nrof += num_coins;
668 remain += num_coins * coin_objs[count]->value; 656 to_pay += num_coins * coin_objs[count]->value;
669 count--; 657 count--;
670 } 658 }
671 } 659 }
660
672 for (i = 0; i < NUM_COINS; i++) 661 for (i = 0; i < NUM_COINS; i++)
673 { 662 {
674 if (coin_objs[i]->nrof) 663 if (coin_objs[i]->nrof)
675 { 664 {
676 object *tmp = insert_ob_in_ob (coin_objs[i], pouch); 665 object *tmp = insert_ob_in_ob (coin_objs[i], pouch);
677 666
678 esrv_send_item (pl, tmp); 667 esrv_send_item (pl, tmp);
679 esrv_send_item (pl, pouch); 668 esrv_send_item (pl, pouch);
669
680 if (pl != pouch) 670 if (pl != pouch)
681 esrv_update_item (UPD_WEIGHT, pl, pouch); 671 esrv_update_item (UPD_WEIGHT, pl, pouch);
672
682 if (pl->type != PLAYER) 673 if (pl->type != PLAYER)
683 {
684 esrv_send_item (pl, pl); 674 esrv_send_item (pl, pl);
685 }
686 } 675 }
687 else 676 else
688 {
689 free_object (coin_objs[i]); 677 free_object (coin_objs[i]);
690 }
691 } 678 }
692 return (remain);
693} 679}
694 680
695/* Checks all unpaid items in op's inventory, adds up all the money they 681/* Checks all unpaid items in op's inventory, adds up all the money they
696 * have, and checks that they can actually afford what they want to buy. 682 * have, and checks that they can actually afford what they want to buy.
697 * Returns 1 if they can, and 0 if they can't. also prints an appropriate message 683 * Returns 1 if they can, and 0 if they can't. also prints an appropriate message
698 * to the player 684 * to the player
699 */ 685 */
700
701int 686int
702can_pay (object *pl) 687can_pay (object *pl)
703{ 688{
704 int unpaid_count = 0, i; 689 int unpaid_count = 0;
705 uint64 unpaid_price = 0; 690 sint64 unpaid_price = 0;
706 uint64 player_wealth = query_money (pl); 691 sint64 player_wealth = query_money (pl);
707 object *item; 692 object *item;
708 uint32 coincount[NUM_COINS];
709 693
710 if (!pl || pl->type != PLAYER) 694 if (!pl || pl->type != PLAYER)
711 { 695 {
712 LOG (llevError, "can_pay(): called against something that isn't a player\n"); 696 LOG (llevError, "can_pay(): called against something that isn't a player\n");
713 return 0; 697 return 0;
714 } 698 }
715 for (i = 0; i < NUM_COINS; i++) 699
716 coincount[i] = 0; 700 for (object::depth_iterator item = pl->begin (); item != pl->end (); ++item)
717 for (item = pl->inv; item;) 701 if (QUERY_FLAG (item, FLAG_UNPAID))
718 {
719 if QUERY_FLAG
720 (item, FLAG_UNPAID)
721 { 702 {
722 unpaid_count++; 703 unpaid_count++;
723 unpaid_price += query_cost (item, pl, F_BUY | F_SHOP); 704 unpaid_price += query_cost (item, pl, F_BUY | F_SHOP);
724 } 705 }
725 /* merely converting the player's monetary wealth won't do, if we did that, 706
726 * we could print the wrong numbers for the coins, so we count the money instead
727 */
728 for (i = 0; i < NUM_COINS; i++)
729 if (!strcmp (coins[i], item->arch->name))
730 coincount[i] += item->nrof;
731 if (item->inv)
732 item = item->inv;
733 else if (item->below)
734 item = item->below;
735 else if (item->env && item->env != pl && item->env->below)
736 item = item->env->below;
737 else
738 item = NULL;
739 }
740 if (unpaid_price > player_wealth) 707 if (unpaid_price > player_wealth)
741 { 708 {
742 char buf[MAX_BUF]; 709 char buf[MAX_BUF];
743 char cost[MAX_BUF]; 710 char cost[MAX_BUF];
744 char missing[MAX_BUF]; 711 char missing[MAX_BUF];
745 712
746 sprintf (cost, "%s", cost_string_from_value (unpaid_price, 0)); 713 snprintf (cost, MAX_BUF, "%s", cost_string_from_value (unpaid_price, 0));
747 sprintf (missing, "%s", cost_string_from_value (unpaid_price - player_wealth, 0)); 714 snprintf (missing, MAX_BUF, "%s", cost_string_from_value (unpaid_price - player_wealth, 0));
748 715
749 sprintf (buf, "You have %d unpaid items that would cost you %s. You need another %s to be able to afford that.", 716 snprintf (buf, MAX_BUF, "You have %d unpaid items that would cost you %s. You need another %s to be able to afford that.",
750 unpaid_count, cost, missing); 717 unpaid_count, cost, missing);
751 new_draw_info (NDI_UNIQUE, 0, pl, buf); 718 new_draw_info (NDI_UNIQUE, 0, pl, buf);
719
752 return 0; 720 return 0;
753 } 721 }
754 else 722 else
755 return 1; 723 return 1;
756} 724}
757
758 725
759/* Better get_payment, descends containers looking for 726/* Better get_payment, descends containers looking for
760 * unpaid items, and pays for them. 727 * unpaid items, and pays for them.
761 * returns 0 if the player still has unpaid items. 728 * returns 0 if the player still has unpaid items.
762 * returns 1 if the player has paid for everything. 729 * returns 1 if the player has paid for everything.
763 * pl is the player buying the stuff. 730 * pl is the player buying the stuff.
764 * op is the object we are examining. If op has
765 * and inventory, we examine that. IF there are objects
766 * below op, we descend down.
767 */ 731 */
768int 732int
769get_payment (object *pl, object *op) 733get_payment (object *pl)
770{ 734{
771 char buf[MAX_BUF]; 735 for (;;)
772 int ret = 1;
773
774 if (op != NULL && op->inv)
775 ret = get_payment (pl, op->inv);
776
777 if (!ret)
778 return 0;
779
780 if (op != NULL && op->below)
781 ret = get_payment (pl, op->below);
782
783 if (!ret)
784 return 0;
785
786 if (op != NULL && QUERY_FLAG (op, FLAG_UNPAID))
787 { 736 {
788 strncpy (buf, query_cost_string (op, pl, F_BUY | F_SHOP), MAX_BUF); 737 next_item:
789 buf[MAX_BUF - 1] = '\0';
790 if (!pay_for_item (op, pl))
791 {
792 uint64 i = query_cost (op, pl, F_BUY | F_SHOP) - query_money (pl);
793 738
794 CLEAR_FLAG (op, FLAG_UNPAID); 739 for (object::depth_iterator op = pl->begin (); op != pl->end (); ++op)
795 new_draw_info_format (NDI_UNIQUE, 0, pl, "You lack %s to buy %s.", cost_string_from_value (i, 0), query_name (op));
796 SET_FLAG (op, FLAG_UNPAID);
797 return 0;
798 } 740 {
799 else
800 {
801 object *tmp;
802 tag_t c = op->count;
803
804 CLEAR_FLAG (op, FLAG_UNPAID); 741 if (QUERY_FLAG (op, FLAG_UNPAID))
805 CLEAR_FLAG (op, FLAG_PLAYER_SOLD);
806 new_draw_info_format (NDI_UNIQUE, 0, op, "You paid %s for %s.", buf, query_name (op));
807 tmp = merge_ob (op, NULL);
808 if (pl->type == PLAYER)
809 { 742 {
810 if (tmp) 743 char buf[MAX_BUF];
811 { /* it was merged */ 744 snprintf (buf, MAX_BUF, "%s", query_cost_string (op, pl, F_BUY | F_SHOP));
812 esrv_del_item (pl->contr, c); 745
813 op = tmp; 746 if (!pay_for_item (op, pl))
747 {
748 sint64 i = query_cost (op, pl, F_BUY | F_SHOP) - query_money (pl);
749
750 CLEAR_FLAG (op, FLAG_UNPAID);
751 new_draw_info_format (NDI_UNIQUE, 0, pl, "You lack %s to buy %s.", cost_string_from_value (i, 0), query_name (op));
752 SET_FLAG (op, FLAG_UNPAID);
753 return 0;
814 } 754 }
755 else
756 {
757 object *tmp;
758 tag_t c = op->count;
759
760 CLEAR_FLAG (op, FLAG_UNPAID);
761 CLEAR_FLAG (op, FLAG_PLAYER_SOLD);
762 new_draw_info_format (NDI_UNIQUE, 0, op, "You paid %s for %s.", buf, query_name (op));
763 tmp = merge_ob (op, NULL);
764
765 if (pl->type == PLAYER)
766 {
767 if (tmp)
768 { /* it was merged */
769 esrv_del_item (pl->contr, c);
770 op = tmp;
771 }
772
815 esrv_send_item (pl, op); 773 esrv_send_item (pl, op);
774 }
775
776 goto next_item;
777 }
816 } 778 }
817 } 779 }
818 } 780
819 return 1; 781 return 1;
782 }
820} 783}
821 784
822/* written by elmex: 785/* written by elmex:
823 * moved this code from sell_item () here to have a function 786 * moved this code from sell_item () here to have a function
824 * that pays the player an amount. Mainly put the code here to 787 * that pays the player an amount. Mainly put the code here to
829 * or put it on the ground under the player. This way the player can still 792 * or put it on the ground under the player. This way the player can still
830 * go somewhere and unload the money at a safe place. 793 * go somewhere and unload the money at a safe place.
831 * 794 *
832 */ 795 */
833void 796void
834pay_player (object *pl, uint64 amount) 797pay_player (object *pl, sint64 amount)
835{ 798{
836 int count = 0; 799 int count = 0;
837 archetype *at = 0; 800 archetype *at = 0;
838 object *pouch = 0, *tmp = 0; 801 object *pouch = 0, *tmp = 0;
839 802
860 if (pouch->weight_limit && (pouch->weight_limit - pouch->carrying) / w < n) 823 if (pouch->weight_limit && (pouch->weight_limit - pouch->carrying) / w < n)
861 n = (pouch->weight_limit - pouch->carrying) / w; 824 n = (pouch->weight_limit - pouch->carrying) / w;
862 825
863 tmp = arch_to_object (at); 826 tmp = arch_to_object (at);
864 tmp->nrof = n; 827 tmp->nrof = n;
865 amount -= (uint64) tmp->nrof * (uint64) tmp->value; 828 amount -= tmp->nrof * tmp->value;
866 tmp = insert_ob_in_ob (tmp, pouch); 829 tmp = insert_ob_in_ob (tmp, pouch);
867 esrv_send_item (pl, tmp); 830 esrv_send_item (pl, tmp);
868 esrv_send_item (pl, pouch); 831 esrv_send_item (pl, pouch);
869 esrv_update_item (UPD_WEIGHT, pl, pouch); 832 esrv_update_item (UPD_WEIGHT, pl, pouch);
870 esrv_send_item (pl, pl); 833 esrv_send_item (pl, pl);
874 837
875 if (amount / at->clone.value > 0) 838 if (amount / at->clone.value > 0)
876 { 839 {
877 tmp = arch_to_object (at); 840 tmp = arch_to_object (at);
878 tmp->nrof = amount / tmp->value; 841 tmp->nrof = amount / tmp->value;
879 amount -= (uint64) tmp->nrof * (uint64) tmp->value; 842 amount -= tmp->nrof * tmp->value;
880 tmp = insert_ob_in_ob (tmp, pl); 843 tmp = insert_ob_in_ob (tmp, pl);
881 esrv_send_item (pl, tmp); 844 esrv_send_item (pl, tmp);
882 esrv_send_item (pl, pl); 845 esrv_send_item (pl, pl);
883 } 846 }
884 } 847 }
891 LOG (llevError, "Warning - payment in pay_player () not zero: %I64u\n", amount); 854 LOG (llevError, "Warning - payment in pay_player () not zero: %I64u\n", amount);
892#endif 855#endif
893} 856}
894 857
895/* elmex: this is for the bank plugin :( */ 858/* elmex: this is for the bank plugin :( */
896uint64 859sint64
897pay_player_arch (object *pl, const char *arch, uint64 amount) 860pay_player_arch (object *pl, const char *arch, sint64 amount)
898{ 861{
899 archetype *at = find_archetype (arch); 862 archetype *at = find_archetype (arch);
900 object *tmp = NULL; 863 object *tmp = NULL;
901 864
902 if (at == NULL) 865 if (at == NULL)
922 * remaining coins in character's inventory. 885 * remaining coins in character's inventory.
923 */ 886 */
924void 887void
925sell_item (object *op, object *pl) 888sell_item (object *op, object *pl)
926{ 889{
927 uint64 amount = query_cost (op, pl, F_SELL | F_SHOP), extra_gain; 890 sint64 amount = query_cost (op, pl, F_SELL | F_SHOP), extra_gain;
928 891
929 if (pl == NULL || pl->type != PLAYER) 892 if (pl == NULL || pl->type != PLAYER)
930 { 893 {
931 LOG (llevDebug, "Object other than player tried to sell something.\n"); 894 LOG (llevDebug, "Object other than player tried to sell something.\n");
932 return; 895 return;
985 if (item == NULL) 948 if (item == NULL)
986 { 949 {
987 LOG (llevError, "shop_specialisation_ratio: passed a NULL item for map %s\n", map->path); 950 LOG (llevError, "shop_specialisation_ratio: passed a NULL item for map %s\n", map->path);
988 return 0; 951 return 0;
989 } 952 }
953
990 if (!item->type) 954 if (!item->type)
991 { 955 {
992 LOG (llevError, "shop_specialisation_ratio: passed an item with an invalid type\n"); 956 LOG (llevError, "shop_specialisation_ratio: passed an item with an invalid type\n");
993 /* 957 /*
994 * I'm not really sure what the /right/ thing to do here is, these types of 958 * I'm not really sure what the /right/ thing to do here is, these types of
995 * item shouldn't exist anyway, but returning the ratio is probably the best bet.." 959 * item shouldn't exist anyway, but returning the ratio is probably the best bet.."
996 */ 960 */
997 return ratio; 961 return ratio;
998 } 962 }
963
999 if (map->shopitems) 964 if (map->shopitems)
1000 { 965 {
1001 for (i = 0; i < items[0].index; i++) 966 for (i = 0; i < items[0].index; i++)
1002 if (items[i].typenum == item->type || (!items[i].typenum && likedness == 0.001)) 967 if (items[i].typenum == item->type || (!items[i].typenum && likedness == 0.001))
1003 likedness = items[i].strength / 100.0; 968 likedness = items[i].strength / 100.0;
1004 } 969 }
970
1005 if (likedness > 1.0) 971 if (likedness > 1.0)
1006 { /* someone has been rather silly with the map headers. */ 972 { /* someone has been rather silly with the map headers. */
1007 LOG (llevDebug, "shop_specialisation ratio: item type %d on map %s is above 100%%\n", item->type, map->path); 973 LOG (llevDebug, "shop_specialisation ratio: item type %d on map %s is above 100%%\n", item->type, map->path);
1008 likedness = 1.0; 974 likedness = 1.0;
1009 } 975 }
976
1010 if (likedness < -1.0) 977 if (likedness < -1.0)
1011 { 978 {
1012 LOG (llevDebug, "shop_specialisation ratio: item type %d on map %s is below -100%%\n", item->type, map->path); 979 LOG (llevDebug, "shop_specialisation ratio: item type %d on map %s is below -100%%\n", item->type, map->path);
1013 likedness = -1.0; 980 likedness = -1.0;
1014 } 981 }
982
1015 ratio = ratio + (1.0 - ratio) * likedness; 983 ratio = ratio + (1.0 - ratio) * likedness;
984
1016 if (ratio <= 0.1) 985 if (ratio <= 0.1)
1017 ratio = 0.1; /* if the ratio were much lower than this, we would get silly prices */ 986 ratio = 0.1; /* if the ratio were much lower than this, we would get silly prices */
987
1018 return ratio; 988 return ratio;
1019} 989}
1020 990
1021/*returns the greed of the shop on map, or 1 if it isn't specified. */ 991/*returns the greed of the shop on map, or 1 if it isn't specified. */
1022static double 992static double
1041 { 1011 {
1042 approval = NEUTRAL_RATIO; 1012 approval = NEUTRAL_RATIO;
1043 if (player->race && !strcmp (player->race, map->shoprace)) 1013 if (player->race && !strcmp (player->race, map->shoprace))
1044 approval = 1.0; 1014 approval = 1.0;
1045 } 1015 }
1016
1046 return approval; 1017 return approval;
1047} 1018}
1048 1019
1049/* limit the value of items based on the wealth of the shop. If the item is close 1020/* limit the value of items based on the wealth of the shop. If the item is close
1050 * to the maximum value a shop will offer, we start to reduce it, if the item is 1021 * to the maximum value a shop will offer, we start to reduce it, if the item is
1051 * below the minimum value the shop is prepared to trade in, then we don't 1022 * below the minimum value the shop is prepared to trade in, then we don't
1052 * want it and offer nothing. If it isn't a shop, check whether we should do generic 1023 * want it and offer nothing. If it isn't a shop, check whether we should do generic
1053 * value reduction. 1024 * value reduction.
1054 * 1025 *
1055 */ 1026 */
1056static uint64 1027static sint64
1057value_limit (uint64 val, int quantity, const object *who, int isshop) 1028value_limit (sint64 val, int quantity, const object *who, int isshop)
1058{ 1029{
1059 uint64 newval, unit_price, tmpshopmax; 1030 sint64 newval, unit_price, tmpshopmax;
1060 mapstruct *map; 1031 mapstruct *map;
1061 1032
1062 unit_price = val / quantity; 1033 unit_price = val / quantity;
1063 1034
1064 if (!isshop || !who) 1035 if (!isshop || !who)
1065 { 1036 {
1066 if (unit_price > 250000) 1037 if (unit_price > 250000)
1067 newval = (uint64) (250000. - pow (250000., .75) * 65. + pow (unit_price, .75) * 65.); 1038 newval = (sint64) (250000. - pow (250000., .75) * 65. + pow (unit_price, .75) * 65.);
1068 else 1039 else
1069 newval = unit_price; 1040 newval = unit_price;
1070 } 1041 }
1071 else 1042 else
1072 { 1043 {
1109 1080
1110 /*check if there is a shop specified for this map */ 1081 /*check if there is a shop specified for this map */
1111 if (map->shopitems || map->shopgreed || map->shoprace || map->shopmin || map->shopmax) 1082 if (map->shopitems || map->shopgreed || map->shoprace || map->shopmin || map->shopmax)
1112 { 1083 {
1113 new_draw_info (NDI_UNIQUE, 0, op, "From looking at the nearby shop you determine that it trades in:"); 1084 new_draw_info (NDI_UNIQUE, 0, op, "From looking at the nearby shop you determine that it trades in:");
1085
1114 if (map->shopitems) 1086 if (map->shopitems)
1115 {
1116 for (i = 0; i < map->shopitems[0].index; i++) 1087 for (i = 0; i < map->shopitems[0].index; i++)
1088 if (map->shopitems[i].name && map->shopitems[i].strength > 10)
1117 { 1089 {
1118 if (map->shopitems[i].name && map->shopitems[i].strength > 10)
1119 {
1120 snprintf (tmp + pos, sizeof (tmp) - pos, "%s, ", map->shopitems[i].name_pl); 1090 snprintf (tmp + pos, sizeof (tmp) - pos, "%s, ", map->shopitems[i].name_pl);
1121 pos += strlen (tmp + pos); 1091 pos += strlen (tmp + pos);
1122 }
1123 } 1092 }
1124 } 1093
1125 if (!pos) 1094 if (!pos)
1126 strcat (tmp, "a little of everything."); 1095 strcat (tmp, "a little of everything.");
1127 1096
1128 /* format the string into a list */ 1097 /* format the string into a list */
1129 make_list_like (tmp); 1098 make_list_like (tmp);
1130 new_draw_info_format (NDI_UNIQUE, 0, op, "%s", tmp); 1099 new_draw_info_format (NDI_UNIQUE, 0, op, "%s", tmp);
1131 1100
1132 if (map->shopmax) 1101 if (map->shopmax)
1133 new_draw_info_format (NDI_UNIQUE, 0, op, "It won't trade for items above %s.", cost_string_from_value (map->shopmax, 0)); 1102 new_draw_info_format (NDI_UNIQUE, 0, op, "It won't trade for items above %s.", cost_string_from_value (map->shopmax, 0));
1103
1134 if (map->shopmin) 1104 if (map->shopmin)
1135 new_draw_info_format (NDI_UNIQUE, 0, op, "It won't trade in items worth less than %s.", cost_string_from_value (map->shopmin, 0)); 1105 new_draw_info_format (NDI_UNIQUE, 0, op, "It won't trade in items worth less than %s.", cost_string_from_value (map->shopmin, 0));
1106
1136 if (map->shopgreed) 1107 if (map->shopgreed)
1137 { 1108 {
1138 if (map->shopgreed > 2.0) 1109 if (map->shopgreed > 2.0)
1139 new_draw_info (NDI_UNIQUE, 0, op, "It tends to overcharge massively."); 1110 new_draw_info (NDI_UNIQUE, 0, op, "It tends to overcharge massively.");
1140 else if (map->shopgreed > 1.5) 1111 else if (map->shopgreed > 1.5)
1142 else if (map->shopgreed > 1.1) 1113 else if (map->shopgreed > 1.1)
1143 new_draw_info (NDI_UNIQUE, 0, op, "It tends to overcharge slightly."); 1114 new_draw_info (NDI_UNIQUE, 0, op, "It tends to overcharge slightly.");
1144 else if (map->shopgreed < 0.9) 1115 else if (map->shopgreed < 0.9)
1145 new_draw_info (NDI_UNIQUE, 0, op, "It tends to undercharge."); 1116 new_draw_info (NDI_UNIQUE, 0, op, "It tends to undercharge.");
1146 } 1117 }
1118
1147 if (map->shoprace) 1119 if (map->shoprace)
1148 { 1120 {
1149 opinion = shopkeeper_approval (map, op); 1121 opinion = shopkeeper_approval (map, op);
1150 if (opinion > 0.8) 1122 if (opinion > 0.8)
1151 new_draw_info (NDI_UNIQUE, 0, op, "You think the shopkeeper likes you."); 1123 new_draw_info (NDI_UNIQUE, 0, op, "You think the shopkeeper likes you.");
1158 else 1130 else
1159 new_draw_info (NDI_UNIQUE, 0, op, "There is no shop nearby."); 1131 new_draw_info (NDI_UNIQUE, 0, op, "There is no shop nearby.");
1160 1132
1161 return 1; 1133 return 1;
1162} 1134}
1135
1163typedef struct shopinv 1136struct shopinv
1164{ 1137{
1165 char *item_sort; 1138 char *item_sort;
1166 char *item_real; 1139 char *item_real;
1167 uint16 type; 1140 uint16 type;
1168 uint32 nrof; 1141 uint32 nrof;
1169} shopinv; 1142};
1170 1143
1171/* There are a lot fo extra casts in here just to suppress warnings - it 1144/* There are a lot fo extra casts in here just to suppress warnings - it
1172 * makes it look uglier than it really it. 1145 * makes it look uglier than it really it.
1173 * The format of the strings we get is type:name. So we first want to 1146 * The format of the strings we get is type:name. So we first want to
1174 * sort by type (numerical) - if the same type, then sort by name. 1147 * sort by type (numerical) - if the same type, then sort by name.
1180 1153
1181 if (s1->type < s2->type) 1154 if (s1->type < s2->type)
1182 return -1; 1155 return -1;
1183 if (s1->type > s2->type) 1156 if (s1->type > s2->type)
1184 return 1; 1157 return 1;
1158
1185 /* the type is the same (what atoi gets), so do a strcasecmp to sort 1159 /* the type is the same (what atoi gets), so do a strcasecmp to sort
1186 * via alphabetical order 1160 * via alphabetical order
1187 */ 1161 */
1188 return strcasecmp (s1->item_sort, s2->item_sort); 1162 return strcasecmp (s1->item_sort, s2->item_sort);
1189} 1163}
1284 stack = stack->above; 1258 stack = stack->above;
1285 } 1259 }
1286 } 1260 }
1287 } 1261 }
1288 } 1262 }
1263
1289 free (map_mark); 1264 free (map_mark);
1265
1290 if (numitems == 0) 1266 if (numitems == 0)
1291 { 1267 {
1292 new_draw_info (NDI_UNIQUE, 0, op, "The shop is currently empty.\n"); 1268 new_draw_info (NDI_UNIQUE, 0, op, "The shop is currently empty.\n");
1293 free (items); 1269 free (items);
1294 return; 1270 return;
1295 } 1271 }
1272
1296 qsort (items, numitems, sizeof (shopinv), (int (*)(const void *, const void *)) shop_sort); 1273 qsort (items, numitems, sizeof (shopinv), (int (*)(const void *, const void *)) shop_sort);
1297 1274
1298 for (i = 0; i < numitems; i++) 1275 for (i = 0; i < numitems; i++)
1299 { 1276 {
1300 /* Collapse items of the same name together */ 1277 /* Collapse items of the same name together */

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines