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.55 by root, Sun Sep 21 23:21:49 2008 UTC vs.
Revision 1.81 by root, Wed Apr 28 19:20:48 2010 UTC

1/* 1/*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG. 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * 3 *
4 * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 4 * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team 5 * Copyright (©) 2002 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen 6 * Copyright (©) 1992 Frank Tore Johansen
7 * 7 *
8 * Deliantra is free software: you can redistribute it and/or modify 8 * Deliantra is free software: you can redistribute it and/or modify it under
9 * it under the terms of the GNU General Public License as published by 9 * the terms of the Affero GNU General Public License as published by the
10 * the Free Software Foundation, either version 3 of the License, or 10 * Free Software Foundation, either version 3 of the License, or (at your
11 * (at your option) any later version. 11 * option) any later version.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the Affero GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 * and the GNU General Public License along with this program. If not, see
20 * <http://www.gnu.org/licenses/>.
20 * 21 *
21 * The authors can be reached via e-mail to <support@deliantra.net> 22 * The authors can be reached via e-mail to <support@deliantra.net>
22 */ 23 */
23 24
24#include <global.h> 25#include <global.h>
25#include <spells.h> 26#include <spells.h>
26#include <skills.h> 27#include <skills.h>
27#include <living.h> 28#include <living.h>
28#include <sproto.h> 29#include <sproto.h>
29#include <math.h>
30 30
31/* this is a measure of how effective store specialisation is. A general store 31/* this is a measure of how effective store specialisation is. A general store
32 * will offer this proportion of the 'maximum' price, a specialised store will 32 * will offer this proportion of the 'maximum' price, a specialised store will
33 * offer a range of prices around it such that the maximum price is always one 33 * offer a range of prices around it such that the maximum price is always one
34 * therefore making this number higher, makes specialisation less effective. 34 * therefore making this number higher, makes specialisation less effective.
74 74
75sint64 75sint64
76query_cost (const object *tmp, object *who, int flag) 76query_cost (const object *tmp, object *who, int flag)
77{ 77{
78 double val; 78 double val;
79 int number; /* used to better calculate value */
80 int no_bargain; 79 int no_bargain;
81 int identified; 80 int identified;
82 int not_cursed; 81 int not_cursed;
83 int approximate; 82 int approximate;
84 int shop; 83 int shop;
91 not_cursed = flag & F_NOT_CURSED; 90 not_cursed = flag & F_NOT_CURSED;
92 approximate = flag & F_APPROX; 91 approximate = flag & F_APPROX;
93 shop = flag & F_SHOP; 92 shop = flag & F_SHOP;
94 flag &= ~(F_NO_BARGAIN | F_IDENTIFIED | F_NOT_CURSED | F_APPROX | F_SHOP); 93 flag &= ~(F_NO_BARGAIN | F_IDENTIFIED | F_NOT_CURSED | F_APPROX | F_SHOP);
95 94
95 int number = tmp->number_of ();
96
96 if (tmp->type == MONEY) 97 if (tmp->type == MONEY)
97 return tmp->nrof * tmp->value; 98 return number * tmp->value;
98 99
99 if (tmp->type == GEM) 100 if (tmp->type == GEM)
100 { 101 {
101 if (flag == F_TRUE) 102 if (flag == F_TRUE)
102 return (tmp->nrof * tmp->value); 103 return number * tmp->value;
103 104
104 if (flag == F_BUY) 105 if (flag == F_BUY)
105 return (sint64) (1.03 * tmp->nrof * tmp->value); 106 return 1.03 * number * tmp->value;
106 107
107 if (flag == F_SELL) 108 if (flag == F_SELL)
108 return (sint64) (0.97 * tmp->nrof * tmp->value); 109 return 0.97 * number * tmp->value;
109 110
110 LOG (llevError, "Query_cost: Gem type with unknown flag %d: %s\n", flag, tmp->debug_desc ()); 111 LOG (llevError, "Query_cost: Gem type with unknown flag %d: %s\n", flag, tmp->debug_desc ());
111 return 0; 112 return 0;
112 } 113 }
113 114
114 number = tmp->nrof;
115 if (number == 0)
116 number = 1;
117 if (QUERY_FLAG (tmp, FLAG_IDENTIFIED) || !need_identify (tmp) || identified) 115 if (tmp->flag [FLAG_IDENTIFIED] || !tmp->need_identify () || identified)
118 { 116 {
119 if (!not_cursed && (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED))) 117 if (!not_cursed && (tmp->flag [FLAG_CURSED] || tmp->flag [FLAG_DAMNED]))
120 return 0; 118 return 0;
121 else 119 else
122 val = tmp->value * number; 120 val = number * tmp->value;
123 } 121 }
124 /* This area deals with objects that are not identified, but can be */ 122 /* This area deals with objects that are not identified, but can be */
125 else 123 else
126 { 124 {
127 if (tmp->arch != NULL)
128 {
129 if (flag == F_BUY) 125 if (flag == F_BUY)
126 {
127 LOG (llevError | logBacktrace, "Asking for buy-value of unidentified object: %s\n", tmp->debug_desc ());
128 val = tmp->arch->value * 50 * number;
129 }
130 else
131 { /* Trying to sell something, or get true value */
132 if (tmp->type == POTION)
133 val = number * 40; /* Don't want to give anything away */
134 else
130 { 135 {
131 LOG (llevError | logBacktrace, "Asking for buy-value of unidentified object.\n"); 136 /* Get 2/3'rd value for applied objects, 1/3'rd for totally
132 val = tmp->arch->value * 50 * number; 137 * unknown objects
138 */
139 if (tmp->flag [FLAG_BEEN_APPLIED])
140 val = number * tmp->arch->value * 2 / 3;
141 else
142 val = number * tmp->arch->value / 3;
133 } 143 }
134 else
135 { /* Trying to sell something, or get true value */
136 if (tmp->type == POTION)
137 val = number * 40; /* Don't want to give anything away */
138 else
139 {
140 /* Get 2/3'rd value for applied objects, 1/3'rd for totally
141 * unknown objects
142 */
143 if (QUERY_FLAG (tmp, FLAG_BEEN_APPLIED))
144 val = number * tmp->arch->value * 2 / 3;
145 else
146 val = number * tmp->arch->value / 3;
147 }
148 }
149 }
150 else
151 { /* No archetype with this object */
152 LOG (llevDebug, "In sell item: Have object with no archetype: %s\n", &tmp->name);
153 if (flag == F_BUY)
154 {
155 LOG (llevError | logBacktrace, "Asking for buy-value of unidentified object without arch.\n");
156 val = number * tmp->value * 10;
157 }
158 else
159 val = number * tmp->value / 5;
160 } 144 }
161 } 145 }
162 146
163 /* If the item has been applied or identifed or does not need to be 147 /* If the item has been applied or identifed or does not need to be
164 * identified, AND the object is magical and the archetype is non 148 * identified, AND the object is magical and the archetype is non
167 * tmp->arch->magic for any magic. The check for archetype 151 * tmp->arch->magic for any magic. The check for archetype
168 * magic is to not give extra money for archetypes that are by 152 * magic is to not give extra money for archetypes that are by
169 * default magical. This is because the archetype value should have 153 * default magical. This is because the archetype value should have
170 * already figured in that value. 154 * already figured in that value.
171 */ 155 */
172 if ((QUERY_FLAG (tmp, FLAG_IDENTIFIED) || !need_identify (tmp) || identified || 156 if ((tmp->flag [FLAG_IDENTIFIED] || !tmp->need_identify () || identified || tmp->flag [FLAG_BEEN_APPLIED])
173 QUERY_FLAG (tmp, FLAG_BEEN_APPLIED)) && tmp->magic && (tmp->arch == NULL || !tmp->arch->magic)) 157 && tmp->magic && (!tmp->arch || !tmp->arch->magic))
174 { 158 {
175 if (tmp->magic > 0) 159 if (tmp->magic > 0)
176 val *= (3 * tmp->magic * tmp->magic * tmp->magic); 160 val *= 3 * tmp->magic * tmp->magic * tmp->magic;
177 else 161 else
178 /* Note that tmp->magic is negative, so that this 162 /* Note that tmp->magic is negative, so that this
179 * will actually be something like val /=2, /=3, etc. 163 * will actually be something like val /=2, /=3, etc.
180 */ 164 */
181 val /= (1 - tmp->magic); 165 val /= 1 - tmp->magic;
182 } 166 }
183 167
184 if (tmp->type == WAND) 168 if (tmp->type == WAND)
185 { 169 {
186 /* Value of the wand is multiplied by the number of 170 /* Value of the wand is multiplied by the number of
187 * charges. the treasure code already sets up the value 171 * charges. the treasure code already sets up the value
188 * 50 charges is used as the baseline. 172 * 50 charges is used as the baseline.
189 */ 173 */
190 if (QUERY_FLAG (tmp, FLAG_IDENTIFIED) || !need_identify (tmp) || identified) 174 if (tmp->flag [FLAG_IDENTIFIED] || !tmp->need_identify () || identified)
191 val = (val * tmp->stats.food) / 50; 175 val *= tmp->stats.food / 50;
192 else /* if not identified, presume one charge */ 176 else /* if not identified, presume one charge */
193 val /= 50; 177 val /= 50;
194 } 178 }
195 179
196 /* Limit amount of money you can get for really great items. */ 180 /* Limit amount of money you can get for really great items. */
197 if (flag == F_SELL) 181 if (flag == F_SELL)
198 val = value_limit ((sint64) val, number, who, shop); 182 val = value_limit (val, number, who, shop);
199 183
200 // use a nonlinear price adjustment. as my predecessor said, don't change 184 // use a nonlinear price adjustment. as my predecessor said, don't change
201 // the archetypes, its work required for balancing, and we don't care. 185 // the archetypes, its work required for balancing, and we don't care.
202 //val = pow (val, 1.05); 186 //val = pow (val, 1.05);
203 187
234 * will come from the basic stat charisma 218 * will come from the basic stat charisma
235 * the rest will come from the level in bargaining skill 219 * the rest will come from the level in bargaining skill
236 */ 220 */
237 const double cha_ratio = 0.40; 221 const double cha_ratio = 0.40;
238 222
239 diff = no_bargain ? 1.0 : 1. - pow (lev_bargain / (double) settings.max_level, 0.25); 223 diff = no_bargain ? 1.0 : 1. - pow (lev_bargain / MAXLEVEL_TREASURE, 0.25);
240 diff = (1. - cha_ratio) * diff + cha_ratio * (cha_bonus[who->stats.Cha] - 1.) / (cha_bonus[who->stats.Cha] + 1.); 224 diff = (1. - cha_ratio) * diff + cha_ratio * (cha_bonus[who->stats.Cha] - 1.) / (cha_bonus[who->stats.Cha] + 1.);
241 diff = .02 + (.80 - .02) * diff; 225 diff = .02 + (.80 - .02) * diff;
242 226
243 if (flag == F_BUY) 227 if (flag == F_BUY)
244 val += val * diff; 228 val += val * diff;
246 val -= val * diff; 230 val -= val * diff;
247 231
248 // now find a price range. the less good we can judge, the larger the range is 232 // now find a price range. the less good we can judge, the larger the range is
249 // then the range is adjusted randomly around the correct value 233 // then the range is adjusted randomly around the correct value
250 if (approximate) 234 if (approximate)
251 approx_range = sint64 (val / sqrt (lev_identify * 3 + 1)); 235 approx_range = val / sqrt (lev_identify * 3 + 1);
252 } 236 }
253 237
254 /* I don't think this should really happen - if it does, it indicates and 238 /* I don't think this should really happen - if it does, it indicates and
255 * overflow of diff above. That should only happen if 239 * overflow of diff above. That should only happen if
256 * we are selling objects - in that case, the person just 240 * we are selling objects - in that case, the person just
257 * gets no money. 241 * gets no money.
258 */ 242 */
259 if ((sint64) val < 0) 243 if ((sint64) val < 0)
260 val = 0; 244 val = 0;
261 245
262 /* Unidentified stuff won't sell for more than 60gp */ 246 /* Unidentified stuff won't sell for more than 10gp */
263 if (flag == F_SELL && !QUERY_FLAG (tmp, FLAG_IDENTIFIED) && need_identify (tmp) && !identified) 247 if (flag == F_SELL && !tmp->flag [FLAG_IDENTIFIED] && tmp->need_identify () && !identified)
264 { 248 min_it (val, 1000);
265 val = (val > 600) ? 600 : val;
266 }
267 249
268 /* if we are in a shop, check how the type of shop should affect the price */ 250 /* if we are in a shop, check how the type of shop should affect the price */
269 if (shop && who) 251 if (shop && who)
270 { 252 {
271 if (flag == F_SELL) 253 if (flag == F_SELL)
272 val = (val * shop_specialisation_ratio (tmp, who->map) * shopkeeper_approval (who->map, who) / shop_greed (who->map)); 254 val *= shop_specialisation_ratio (tmp, who->map) * shopkeeper_approval (who->map, who) / shop_greed (who->map);
273 else if (flag == F_BUY) 255 else if (flag == F_BUY)
274 { 256 {
275 /* 257 /*
276 * when buying, if the item was sold by another player, it is ok to 258 * when buying, if the item was sold by another player, it is ok to
277 * let the item be sold cheaper, according to the specialisation of 259 * let the item be sold cheaper, according to the specialisation of
283 * be sold for (otherwise players could camp map resets to make money). 265 * be sold for (otherwise players could camp map resets to make money).
284 * In game terms, a non-specialist shop, might not recognise the true 266 * In game terms, a non-specialist shop, might not recognise the true
285 * value of the items they sell (much like how people sometimes find 267 * value of the items they sell (much like how people sometimes find
286 * antiques in a junk shop in real life). 268 * antiques in a junk shop in real life).
287 */ 269 */
288 if (QUERY_FLAG (tmp, FLAG_PLAYER_SOLD)) 270 if (tmp->flag [FLAG_PLAYER_SOLD])
289 val = (val * shop_greed (who->map) * shop_specialisation_ratio (tmp, who->map) / shopkeeper_approval (who->map, who)); 271 val *= shop_specialisation_ratio (tmp, who->map);
290 else 272 else
291 val = (val * shop_greed (who->map) / (shop_specialisation_ratio (tmp, who->map) * shopkeeper_approval (who->map, who))); 273 val /= shop_specialisation_ratio (tmp, who->map);
274
275 val *= shop_greed (who->map) / shopkeeper_approval (who->map, who);
292 } 276 }
293 277
294 /* we will also have an extra 0-5% variation between shops of the same type 278 /* we will also have an extra 0-5% variation between shops of the same type
295 * for valuable items (below a value of 50 this effect wouldn't be very 279 * for valuable items (below a value of 50 this effect wouldn't be very
296 * pointful, and could give fun with rounding. 280 * pointful, and could give fun with rounding.
297 */ 281 */
298 //TODO: why use cosf at all, just % and scale linearly, gives more even distribution 282 //TODO: why use cosf at all, just % and scale linearly, gives more even distribution
299 if (val > 50) 283 if (val > 50)
300 val += float (val) * .05f * cosf ((tmp->uuid.seq & 0xffff) * float (M_PI * 2. / 0x10000)); 284 val *= 1 + .05f * cosf ((tmp->uuid.seq & 0xffff) * M_PI * 2. / 0x10000);
301 } 285 }
302 286
303 return (sint64) val; 287 return val;
304} 288}
305 289
306/* Find the coin type that is worth more the 'c'. Starts at the 290/* Find the coin type that is worth more the 'c'. Starts at the
307 * cointype placement. 291 * cointype placement.
308 */ 292 */
312{ 296{
313 archetype *coin; 297 archetype *coin;
314 298
315 do 299 do
316 { 300 {
317 if (coins[*cointype] == NULL) 301 if (!coins [*cointype])
318 return NULL; 302 return 0;
303
319 coin = archetype::find (coins[*cointype]); 304 coin = archetype::find (coins [*cointype]);
305
320 if (coin == NULL) 306 if (!coin)
321 return NULL; 307 return 0;
308
322 *cointype += 1; 309 *cointype += 1;
323 } 310 }
324 while (coin->value > c); 311 while (coin->value > c);
325 312
326 return coin; 313 return coin;
337 * 10,000 silver or something) 324 * 10,000 silver or something)
338 */ 325 */
339const char * 326const char *
340cost_string_from_value (sint64 cost, int approx) 327cost_string_from_value (sint64 cost, int approx)
341{ 328{
342 static char buf[MAX_BUF];
343 archetype *coin, *next_coin; 329 archetype *coin, *next_coin;
344 int num, cointype = 0; 330 int num, cointype = 0;
345 331
346 coin = find_next_coin (cost, &cointype); 332 coin = find_next_coin (cost, &cointype);
347 if (coin == NULL) 333 if (!coin)
348 return "nothing"; 334 return "nothing";
349 335
350 num = cost / coin->value; 336 num = cost / coin->value;
351 /* so long as nrof is 32 bit, this is true. 337 /* so long as nrof is 32 bit, this is true.
352 * If it takes more coins than a person can possibly carry, this 338 * If it takes more coins than a person can possibly carry, this
353 * is basically true. 339 * is basically true.
354 */ 340 */
355 if ((cost / coin->value) > UINT32_MAX) 341 if (cost / coin->value > UINT32_MAX)
356 {
357 strcpy (buf, "an unimaginable sum of money"); 342 return "an unimaginable sum of money";
358 return buf;
359 }
360 343
361 cost -= num * (sint64)coin->value; 344 cost -= num * (sint64)coin->value;
362 345
363 sprintf (buf, "%d %s", num, num > 1 ? &coin->object::name_pl : &coin->object::name); 346 char *buf = format ("%d %s", num, num > 1 ? &coin->object::name_pl : &coin->object::name);
364 347
365 next_coin = find_next_coin (cost, &cointype); 348 next_coin = find_next_coin (cost, &cointype);
366 if (next_coin == NULL || approx) 349 if (!next_coin || approx)
367 return buf; 350 return buf;
368 351
369 coin = next_coin; 352 coin = next_coin;
370 num = cost / coin->value; 353 num = cost / coin->value;
371 cost -= num * (sint64)coin->value; 354 cost -= num * (sint64)coin->value;
372 355
373 sprintf (buf + strlen (buf), " and %d %s", num, num > 1 ? &coin->object::name_pl : &coin->object::name); 356 return format ("%s and %d %s", buf, num, num > 1 ? &coin->object::name_pl : &coin->object::name);
374
375 return buf;
376} 357}
377 358
378const char * 359const char *
379query_cost_string (const object *tmp, object *who, int flag) 360query_cost_string (const object *tmp, object *who, int flag)
380{ 361{
401 { 382 {
402 if (!idskill2 || !find_skill_by_number (who, idskill2)) 383 if (!idskill2 || !find_skill_by_number (who, idskill2))
403 { 384 {
404 if (!find_skill_by_number (who, SK_BARGAINING)) 385 if (!find_skill_by_number (who, SK_BARGAINING))
405 { 386 {
406 static char buf[MAX_BUF];
407 int num, cointype = 0; 387 int num, cointype = 0;
408 archetype *coin = find_next_coin (real_value, &cointype); 388 archetype *coin = find_next_coin (real_value, &cointype);
409 389
410 if (coin == NULL) 390 if (!coin)
411 return "nothing"; 391 return "nothing";
412 392
413 num = real_value / coin->value; 393 num = real_value / coin->value;
414 394
415 if (num == 1) 395 if (num == 1)
416 sprintf (buf, "about one %s", &coin->object::name); 396 return format ("about one %s", &coin->object::name);
417 else if (num < 5) 397 else if (num < 5)
418 sprintf (buf, "a few %s", &coin->object::name_pl); 398 return format ("a few %s", &coin->object::name_pl);
419 else if (num < 10) 399 else if (num < 10)
420 sprintf (buf, "several %s", &coin->object::name_pl); 400 return format ("several %s", &coin->object::name_pl);
421 else if (num < 25) 401 else if (num < 25)
422 sprintf (buf, "a moderate amount of %s", &coin->object::name_pl); 402 return format ("a moderate amount of %s", &coin->object::name_pl);
423 else if (num < 100) 403 else if (num < 100)
424 sprintf (buf, "lots of %s", &coin->object::name_pl); 404 return format ("lots of %s", &coin->object::name_pl);
425 else if (num < 1000) 405 else if (num < 1000)
426 sprintf (buf, "a great many %s", &coin->object::name_pl); 406 return format ("a great many %s", &coin->object::name_pl);
427 else 407 else
428 sprintf (buf, "a vast quantity of %s", &coin->object::name_pl); 408 return format ("a vast quantity of %s", &coin->object::name_pl);
429
430 return buf;
431 } 409 }
432 } 410 }
433 } 411 }
434 412
435 int hash = ((unsigned int) tmp->count * 174364621) & 1023;
436
437 if (approx_range) 413 if (approx_range)
438 { 414 {
415 int hash = tmp->random_seed () & 1023;
439 sint64 lo = (sint64) real_value - (approx_range * hash >> 10); 416 sint64 lo = real_value - (approx_range * hash >> 10);
440 static char buf[MAX_BUF];
441 417
442 sprintf (buf, "between %s", cost_string_from_value (lo, 1)); 418 return format ("between %s and %s",
443 sprintf (buf + strlen (buf), " and %s", cost_string_from_value (lo + approx_range, 1)); 419 cost_string_from_value (lo, 1),
444 420 cost_string_from_value (lo + approx_range, 1));
445 return buf;
446 } 421 }
447 } 422 }
448 423
449 return cost_string_from_value (real_value, 0); 424 return cost_string_from_value (real_value, 0);
450} 425}
465 } 440 }
466 441
467 for (tmp = op->inv; tmp; tmp = tmp->below) 442 for (tmp = op->inv; tmp; tmp = tmp->below)
468 if (tmp->type == MONEY) 443 if (tmp->type == MONEY)
469 total += tmp->nrof * (sint64)tmp->value; 444 total += tmp->nrof * (sint64)tmp->value;
470 else if (tmp->type == CONTAINER && QUERY_FLAG (tmp, FLAG_APPLIED) && (tmp->race == NULL || strstr (tmp->race, "gold"))) 445 else if (tmp->type == CONTAINER && tmp->flag [FLAG_APPLIED] && (!tmp->race || tmp->race.contains ("gold")))
471 total += query_money (tmp); 446 total += query_money (tmp);
472 447
473 return total; 448 return total;
474} 449}
475 450
490 return 0; 465 return 0;
491 466
492 pay_from_container (pl, pl, to_pay); 467 pay_from_container (pl, pl, to_pay);
493 468
494 for (pouch = pl->inv; pouch && to_pay; pouch = pouch->below) 469 for (pouch = pl->inv; pouch && to_pay; pouch = pouch->below)
495 if (pouch->type == CONTAINER && QUERY_FLAG (pouch, FLAG_APPLIED) && (pouch->race == NULL || strstr (pouch->race, "gold"))) 470 if (pouch->type == CONTAINER && pouch->flag [FLAG_APPLIED] && (!pouch->race || pouch->race.contains ("gold")))
496 pay_from_container (pl, pouch, to_pay); 471 pay_from_container (pl, pouch, to_pay);
497 472
498 pl->update_stats (); 473 pl->update_stats ();
499 return 1; 474 return 1;
500} 475}
527 change_exp (pl, saved_money, "bargaining", SK_EXP_NONE); 502 change_exp (pl, saved_money, "bargaining", SK_EXP_NONE);
528 503
529 pay_from_container (pl, pl, to_pay); 504 pay_from_container (pl, pl, to_pay);
530 505
531 for (pouch = pl->inv; pouch && to_pay; pouch = pouch->below) 506 for (pouch = pl->inv; pouch && to_pay; pouch = pouch->below)
532 if (pouch->type == CONTAINER && QUERY_FLAG (pouch, FLAG_APPLIED) && (pouch->race == NULL || strstr (pouch->race, "gold"))) 507 if (pouch->type == CONTAINER && pouch->flag [FLAG_APPLIED] && (!pouch->race || pouch->race.contains ("gold")))
533 pay_from_container (pl, pouch, to_pay); 508 pay_from_container (pl, pouch, to_pay);
534 509
535 pl->update_stats (); 510 pl->update_stats ();
536 511
537 return 1; 512 return 1;
604 at = archetype::find (coins[NUM_COINS - 1 - i]); 579 at = archetype::find (coins[NUM_COINS - 1 - i]);
605 580
606 if (at == NULL) 581 if (at == NULL)
607 LOG (llevError, "Could not find %s archetype\n", coins[NUM_COINS - 1 - i]); 582 LOG (llevError, "Could not find %s archetype\n", coins[NUM_COINS - 1 - i]);
608 583
609 coin_objs[i] = arch_to_object (at); 584 coin_objs[i] = at->instance ();
610 coin_objs[i]->nrof = 0; 585 coin_objs[i]->nrof = 0;
611 } 586 }
612 587
613 for (i = 0; i < NUM_COINS; i++) 588 for (i = 0; i < NUM_COINS; i++)
614 { 589 {
615 object &coin = *coin_objs[i]; 590 object &coin = *coin_objs[i];
616 sint64 num_coins = min ((to_pay + coin.value - 1) / coin.value, coin.nrof); 591 sint64 num_coins = min ((to_pay + coin.value - 1) / coin.value, (sint64) coin.nrof);
617 to_pay -= num_coins * coin.value; 592 to_pay -= num_coins * coin.value;
618 593
619 coin.nrof -= num_coins; 594 coin.nrof -= num_coins;
620 /* Now start making change. Start at the coin value 595 /* Now start making change. Start at the coin value
621 * below the one we just did, and work down to 596 * below the one we just did, and work down to
631 count--; 606 count--;
632 } 607 }
633 } 608 }
634 609
635 for (i = 0; i < NUM_COINS; i++) 610 for (i = 0; i < NUM_COINS; i++)
636 {
637 if (coin_objs[i]->nrof) 611 if (coin_objs[i]->nrof)
638 insert_ob_in_ob (coin_objs [i], pouch); 612 insert_ob_in_ob (coin_objs [i], pouch);
639 else 613 else
640 coin_objs[i]->destroy (); 614 coin_objs[i]->destroy ();
641 }
642} 615}
643 616
644/* Checks all unpaid items in op's inventory, adds up all the money they 617/* Checks all unpaid items in op's inventory, adds up all the money they
645 * have, and checks that they can actually afford what they want to buy. 618 * have, and checks that they can actually afford what they want to buy.
646 * Returns 1 if they can, and 0 if they can't. also prints an appropriate message 619 * Returns 1 if they can, and 0 if they can't. also prints an appropriate message
658 LOG (llevError, "can_pay(): called against something that isn't a player\n"); 631 LOG (llevError, "can_pay(): called against something that isn't a player\n");
659 return 0; 632 return 0;
660 } 633 }
661 634
662 for (object::depth_iterator item = pl->begin (); item != pl->end (); ++item) 635 for (object::depth_iterator item = pl->begin (); item != pl->end (); ++item)
663 if (QUERY_FLAG (item, FLAG_UNPAID)) 636 if (item->flag [FLAG_UNPAID])
664 { 637 {
665 unpaid_count++; 638 unpaid_count++;
666 unpaid_price += query_cost (item, pl, F_BUY | F_SHOP); 639 unpaid_price += query_cost (item, pl, F_BUY | F_SHOP);
667 } 640 }
668 641
669 if (unpaid_price > player_wealth) 642 if (unpaid_price > player_wealth)
670 { 643 {
671 dynbuf_text buf; 644 dynbuf_text &buf = msg_dynbuf; buf.clear ();
672 645
673 buf << "You have " << unpaid_count 646 buf << "You have " << unpaid_count
674 << " unpaid item(s) that would cost you " << cost_string_from_value (unpaid_price, 0) 647 << " unpaid item(s) that would cost you " << cost_string_from_value (unpaid_price, 0)
675 << ". You need another " << cost_string_from_value (unpaid_price - player_wealth, 0) 648 << ". You need another " << cost_string_from_value (unpaid_price - player_wealth, 0)
676 << " to be able to afford that."; 649 << " to be able to afford that. "
650 "H<You cannot leave a shop without paying - drop unpaid items first to be able to leave.>";
677 651
678 pl->failmsg (buf); 652 pl->failmsg (buf);
679 653
680 return 0; 654 return 0;
681 } 655 }
696 { 670 {
697 next_item: 671 next_item:
698 672
699 for (object::depth_iterator op = pl->begin (); op != pl->end (); ++op) 673 for (object::depth_iterator op = pl->begin (); op != pl->end (); ++op)
700 { 674 {
701 if (QUERY_FLAG (op, FLAG_UNPAID)) 675 if (op->flag [FLAG_UNPAID])
702 { 676 {
703 char buf[MAX_BUF];
704 snprintf (buf, MAX_BUF, "%s", query_cost_string (op, pl, F_BUY | F_SHOP)); 677 const char *buf = query_cost_string (op, pl, F_BUY | F_SHOP);
705 678
706 if (!pay_for_item (op, pl)) 679 if (!pay_for_item (op, pl))
707 { 680 {
708 sint64 i = query_cost (op, pl, F_BUY | F_SHOP) - query_money (pl); 681 sint64 i = query_cost (op, pl, F_BUY | F_SHOP) - query_money (pl);
709 682
710 CLEAR_FLAG (op, FLAG_UNPAID); 683 op->clr_flag (FLAG_UNPAID);
711 new_draw_info_format (NDI_UNIQUE, 0, pl, "You lack %s to buy %s.", cost_string_from_value (i, 0), query_name (op)); 684 new_draw_info_format (NDI_UNIQUE, 0, pl, "You lack %s to buy %s.", cost_string_from_value (i, 0), query_name (op));
712 SET_FLAG (op, FLAG_UNPAID); 685 op->set_flag (FLAG_UNPAID);
713 return 0; 686 return 0;
714 } 687 }
715 else 688 else
716 { 689 {
717 CLEAR_FLAG (op, FLAG_UNPAID); 690 op->clr_flag (FLAG_UNPAID);
718 CLEAR_FLAG (op, FLAG_PLAYER_SOLD); 691 op->clr_flag (FLAG_PLAYER_SOLD);
719 new_draw_info_format (NDI_UNIQUE, 0, op, "You paid %s for %s.", buf, query_name (op)); 692 new_draw_info_format (NDI_UNIQUE, 0, pl, "You paid %s for %s.", buf, query_name (op));
720 693
721 if (!merge_ob (op, op->env->inv)) 694 if (!merge_ob (op, op->env->inv))
722 esrv_update_item (UPD_FLAGS, pl, op); 695 esrv_update_item (UPD_FLAGS, pl, op);
723 696
724 goto next_item; 697 goto next_item;
756 LOG (llevError, "Could not find %s archetype\n", coins[count]); 729 LOG (llevError, "Could not find %s archetype\n", coins[count]);
757 else if ((amount / at->value) > 0) 730 else if ((amount / at->value) > 0)
758 { 731 {
759 for (pouch = pl->inv; pouch; pouch = pouch->below) 732 for (pouch = pl->inv; pouch; pouch = pouch->below)
760 { 733 {
761 if (pouch->type == CONTAINER && QUERY_FLAG (pouch, FLAG_APPLIED) && pouch->race && strstr (pouch->race, "gold")) 734 if (pouch->type == CONTAINER && pouch->flag [FLAG_APPLIED] && pouch->race.contains ("gold"))
762 { 735 {
763 int w = at->weight * (100 - pouch->stats.Str) / 100; 736 int w = at->weight * (100 - pouch->stats.Str) / 100;
764 int n = amount / at->value; 737 int n = amount / at->value;
765 738
766 if (w == 0) 739 if (w == 0)
769 if (n > 0 && (!pouch->weight_limit || pouch->carrying + w <= pouch->weight_limit)) 742 if (n > 0 && (!pouch->weight_limit || pouch->carrying + w <= pouch->weight_limit))
770 { 743 {
771 if (pouch->weight_limit && (pouch->weight_limit - pouch->carrying) / w < n) 744 if (pouch->weight_limit && (pouch->weight_limit - pouch->carrying) / w < n)
772 n = (pouch->weight_limit - pouch->carrying) / w; 745 n = (pouch->weight_limit - pouch->carrying) / w;
773 746
774 object *tmp = arch_to_object (at); 747 object *tmp = at->instance ();
775 tmp->nrof = n; 748 tmp->nrof = n;
776 amount -= tmp->nrof * tmp->value; 749 amount -= tmp->nrof * tmp->value;
777 pouch->insert (tmp); 750 pouch->insert (tmp);
778 } 751 }
779 } 752 }
780 } 753 }
781 754
782 if (amount / at->value > 0) 755 if (amount / at->value > 0)
783 { 756 {
784 object *tmp = arch_to_object (at); 757 object *tmp = at->instance ();
785 tmp->nrof = amount / tmp->value; 758 tmp->nrof = amount / tmp->value;
786 amount -= tmp->nrof * tmp->value; 759 amount -= tmp->nrof * tmp->value;
787 pl->insert (tmp); 760 pl->insert (tmp);
788 } 761 }
789 } 762 }
854 827
855 new_draw_info_format (NDI_UNIQUE, 0, pl, "You receive %s for %s.", 828 new_draw_info_format (NDI_UNIQUE, 0, pl, "You receive %s for %s.",
856 query_cost_string (op, pl, F_SELL | F_SHOP), query_name (op)); 829 query_cost_string (op, pl, F_SELL | F_SHOP), query_name (op));
857 pl->play_sound (sound_find ("shop_sell")); 830 pl->play_sound (sound_find ("shop_sell"));
858 831
859 SET_FLAG (op, FLAG_UNPAID); 832 op->set_flag (FLAG_UNPAID);
860 identify (op); 833 identify (op);
861 834
862 return true; 835 return true;
863} 836}
864 837
868 */ 841 */
869static double 842static double
870shop_specialisation_ratio (const object *item, const maptile *map) 843shop_specialisation_ratio (const object *item, const maptile *map)
871{ 844{
872 shopitems *items = map->shopitems; 845 shopitems *items = map->shopitems;
873 double likedness = 0.; 846 int likedness = 0;
874 int i; 847 int i;
875 848
876 if (item == NULL) 849 if (item == NULL)
877 { 850 {
878 LOG (llevError, "shop_specialisation_ratio: passed a NULL item for map %s\n", &map->path); 851 LOG (llevError, "shop_specialisation_ratio: passed a NULL item for map %s\n", &map->path);
888 */ 861 */
889 return SPECIALISATION_EFFECT; 862 return SPECIALISATION_EFFECT;
890 } 863 }
891 864
892 if (map->shopitems) 865 if (map->shopitems)
893 {
894 for (i = 0; i < items[0].index; i++) 866 for (i = 0; i < items[0].index; i++)
895 if (items[i].typenum == item->type || (!items[i].typenum && likedness == 0.001)) 867 if (items[i].typenum == item->type || (!items[i].typenum && !likedness))
896 likedness = items[i].strength / 100.0; 868 likedness = items[i].strength;
897 }
898 869
899 if (likedness > 1.0) 870 if (likedness > 100)
900 { /* someone has been rather silly with the map headers. */ 871 { /* someone has been rather silly with the map headers. */
901 LOG (llevDebug, "shop_specialisation ratio: item type %d on map %s is above 100%%\n", item->type, &map->path); 872 LOG (llevDebug, "shop_specialisation ratio: item type %d on map %s is above 100%%\n", item->type, &map->path);
902 likedness = 1.0; 873 likedness = 100;
903 } 874 }
904 875
905 if (likedness < -1.0) 876 if (likedness < -100)
906 { 877 {
907 LOG (llevDebug, "shop_specialisation ratio: item type %d on map %s is below -100%%\n", item->type, &map->path); 878 LOG (llevDebug, "shop_specialisation ratio: item type %d on map %s is below -100%%\n", item->type, &map->path);
908 likedness = -1.0; 879 likedness = -100;
909 } 880 }
910 881
911 return lerp (likedness, -1., 1., SPECIALISATION_EFFECT, 1.); 882 return lerp (double (likedness), -100., 100., SPECIALISATION_EFFECT, 1.);
912} 883}
913 884
914/*returns the greed of the shop on map, or 1 if it isn't specified. */ 885/*returns the greed of the shop on map, or 1 if it isn't specified. */
915static double 886static double
916shop_greed (const maptile *map) 887shop_greed (const maptile *map)
966 tmpshopmax = map->shopmax ? map->shopmax : 100000; // 20 royalties default 937 tmpshopmax = map->shopmax ? map->shopmax : 100000; // 20 royalties default
967 938
968 if (map->shopmin && unit_price < map->shopmin) 939 if (map->shopmin && unit_price < map->shopmin)
969 return 0; 940 return 0;
970 else if (unit_price > tmpshopmax / 2) 941 else if (unit_price > tmpshopmax / 2)
971 newval = MIN ((tmpshopmax / 2) + isqrt (unit_price - tmpshopmax / 2), tmpshopmax); 942 newval = min ((tmpshopmax / 2) + isqrt (unit_price - tmpshopmax / 2), tmpshopmax);
972 else 943 else
973 newval = unit_price; 944 newval = unit_price;
974 } 945 }
975 946
976 newval *= quantity; 947 newval *= quantity;
980 951
981/* gives a desciption of the shop on their current map to the player op. */ 952/* gives a desciption of the shop on their current map to the player op. */
982int 953int
983describe_shop (const object *op) 954describe_shop (const object *op)
984{ 955{
956 dynbuf_text buf;
985 maptile *map = op->map; 957 maptile *map = op->map;
986 958
987 /*shopitems *items=map->shopitems; */ 959 /*shopitems *items=map->shopitems; */
988 int pos = 0, i; 960 int pos = 0, i;
989 double opinion = 0; 961 double opinion = 0;
990 char tmp[MAX_BUF] = "\0";
991 962
992 if (op->type != PLAYER) 963 if (op->type != PLAYER)
993 return 0; 964 return 0;
994 965
995 /*check if there is a shop specified for this map */ 966 /*check if there is a shop specified for this map */
996 if (map->shopitems || map->shopgreed || map->shoprace || map->shopmin || map->shopmax) 967 if (map->shopitems || map->shopgreed || map->shoprace || map->shopmin || map->shopmax)
997 { 968 {
998 new_draw_info (NDI_UNIQUE, 0, op, "From looking at the nearby shop you determine that it trades in:"); 969 buf << "From looking at the nearby shop you determine that it trades in ";
970 int lastcomma = 0, prevcomma = 0;
999 971
1000 if (map->shopitems) 972 if (map->shopitems)
1001 for (i = 0; i < map->shopitems[0].index; i++) 973 for (i = 0; i < map->shopitems[0].index; i++)
1002 if (map->shopitems[i].name && map->shopitems[i].strength > 10) 974 if (map->shopitems[i].name && map->shopitems[i].strength > 10)
1003 { 975 {
1004 snprintf (tmp + pos, sizeof (tmp) - pos, "%s, ", map->shopitems[i].name_pl); 976 buf << map->shopitems[i].name_pl;
1005 pos += strlen (tmp + pos); 977 prevcomma = lastcomma;
978 lastcomma = buf.size (); // remember offset
979 buf << ", ";
1006 } 980 }
1007 981
1008 if (!pos) 982 if (lastcomma)
983 {
984 buf.splice (lastcomma, 2);
985
986 if (prevcomma)
987 buf.splice (prevcomma, 2, " and ");
988 }
989 else
1009 strcat (tmp, "a little of everything."); 990 buf << "a little of everything.";
1010 991
1011 /* format the string into a list */ 992 buf << ".\n\n";
1012 make_list_like (tmp);
1013 new_draw_info_format (NDI_UNIQUE, 0, op, "%s", tmp);
1014 993
1015 if (map->shopmax) 994 if (map->shopmax)
1016 new_draw_info_format (NDI_UNIQUE, 0, op, "It won't trade for items above %s.", cost_string_from_value (map->shopmax, 0)); 995 buf << "It won't trade for items above " << cost_string_from_value (map->shopmax, 0) << ".\n\n";
1017 996
1018 if (map->shopmin) 997 if (map->shopmin)
1019 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)); 998 buf << "It won't trade in items worth less than " << cost_string_from_value (map->shopmin, 0) << ".\n\n";
1020 999
1021 if (map->shopgreed) 1000 if (map->shopgreed)
1022 { 1001 {
1023 if (map->shopgreed > 2.0) 1002 if (map->shopgreed > 2.0)
1024 new_draw_info (NDI_UNIQUE, 0, op, "It tends to overcharge massively."); 1003 buf << "It tends to overcharge massively.\n\n";
1025 else if (map->shopgreed > 1.5) 1004 else if (map->shopgreed > 1.5)
1026 new_draw_info (NDI_UNIQUE, 0, op, "It tends to overcharge substantially."); 1005 buf << "It tends to overcharge substantially.\n\n";
1027 else if (map->shopgreed > 1.1) 1006 else if (map->shopgreed > 1.1)
1028 new_draw_info (NDI_UNIQUE, 0, op, "It tends to overcharge slightly."); 1007 buf << "It tends to overcharge slightly.\n\n";
1029 else if (map->shopgreed < 0.9) 1008 else if (map->shopgreed < 0.9)
1030 new_draw_info (NDI_UNIQUE, 0, op, "It tends to undercharge."); 1009 buf << "It tends to undercharge.\n\n";
1031 } 1010 }
1032 1011
1033 if (map->shoprace) 1012 if (map->shoprace)
1034 { 1013 {
1035 opinion = shopkeeper_approval (map, op); 1014 opinion = shopkeeper_approval (map, op);
1015
1036 if (opinion > 0.8) 1016 if (opinion > 0.8)
1037 new_draw_info (NDI_UNIQUE, 0, op, "You think the shopkeeper likes you."); 1017 buf << "You think the shopkeeper likes you.\n\n";
1038 else if (opinion > 0.5) 1018 else if (opinion > 0.5)
1039 new_draw_info (NDI_UNIQUE, 0, op, "The shopkeeper seems unconcerned by you."); 1019 buf << "The shopkeeper seems unconcerned by you.\n\n";
1040 else 1020 else
1041 new_draw_info (NDI_UNIQUE, 0, op, "The shopkeeper seems to have taken a dislike to you."); 1021 buf << "The shopkeeper seems to have taken a dislike to you.\n\n";
1042 } 1022 }
1043 } 1023 }
1044 else 1024 else
1045 new_draw_info (NDI_UNIQUE, 0, op, "There is no shop nearby."); 1025 buf << "There is no shop nearby.\n\n";
1026
1027 op->contr->infobox (MSG_CHANNEL ("shopinfo"), buf);
1046 1028
1047 return 1; 1029 return 1;
1048} 1030}
1049 1031
1050struct shopinv 1032struct shopinv
1078} 1060}
1079 1061
1080static void 1062static void
1081add_shop_item (object *tmp, shopinv * items, int *numitems, int *numallocated) 1063add_shop_item (object *tmp, shopinv * items, int *numitems, int *numallocated)
1082{ 1064{
1083#if 0
1084 char buf[MAX_BUF];
1085#endif
1086 /* clear unpaid flag so that doesn't come up in query 1065 /* clear unpaid flag so that doesn't come up in query
1087 * string. We clear nrof so that we can better sort 1066 * string. We clear nrof so that we can better sort
1088 * the object names. 1067 * the object names.
1089 */ 1068 */
1090 1069
1091 CLEAR_FLAG (tmp, FLAG_UNPAID); 1070 tmp->clr_flag (FLAG_UNPAID);
1092 items[*numitems].nrof = tmp->nrof; 1071 items[*numitems].nrof = tmp->nrof;
1093 /* Non mergable items have nrof of 0, but count them as one 1072 /* Non mergable items have nrof of 0, but count them as one
1094 * so the display is properly. 1073 * so the display is properly.
1095 */ 1074 */
1096 if (tmp->nrof == 0) 1075 if (tmp->nrof == 0)
1118 items[*numitems].item_sort = strdup (query_base_name (tmp, 0)); 1097 items[*numitems].item_sort = strdup (query_base_name (tmp, 0));
1119 items[*numitems].item_real = strdup (query_base_name (tmp, 1)); 1098 items[*numitems].item_real = strdup (query_base_name (tmp, 1));
1120 (*numitems)++; 1099 (*numitems)++;
1121 break; 1100 break;
1122 } 1101 }
1123 SET_FLAG (tmp, FLAG_UNPAID); 1102
1103 tmp->set_flag (FLAG_UNPAID);
1124} 1104}
1125 1105
1126void 1106void
1127shop_listing (object *sign, object *op) 1107shop_listing (object *sign, object *op)
1128{ 1108{
1129 int i, j, numitems = 0, numallocated = 0, x1, x2, y1, y2; 1109 int i, j, x1, x2, y1, y2;
1130 const char *shop_coords = sign->kv (shstr_shop_coords); 1110 const char *shop_coords = sign->kv (shstr_shop_coords);
1131 object *stack; 1111 object *stack;
1132 shopinv *items; 1112 shopinv *items;
1133 1113
1134 /* Should never happen, but just in case a monster does apply a sign */ 1114 /* Should never happen, but just in case a monster does apply a sign */
1135 if (op->type != PLAYER) 1115 if (!op->is_player ())
1136 return; 1116 return;
1117
1118 dynbuf_text &buf = msg_dynbuf; buf.clear ();
1137 1119
1138 if (!(shop_coords && sscanf (shop_coords, "%d,%d,%d,%d", &x1, &y1, &x2, &y2))) 1120 if (!(shop_coords && sscanf (shop_coords, "%d,%d,%d,%d", &x1, &y1, &x2, &y2)))
1139 { 1121 {
1140 x1 = 0; 1122 x1 = 0;
1141 y1 = 0; 1123 y1 = 0;
1142 x2 = op->map->width - 1; 1124 x2 = op->map->width - 1;
1143 y2 = op->map->height - 1; 1125 y2 = op->map->height - 1;
1144 } 1126 }
1145 1127
1146 items = (shopinv *) malloc (40 * sizeof (shopinv));
1147 numallocated = 40; 1128 int numallocated = 40;
1129 int numitems = 0;
1130 items = (shopinv *)malloc (sizeof (shopinv) * numallocated);
1148 1131
1149 /* Find all the appropriate items */ 1132 /* Find all the appropriate items */
1150 for (i = x1; i <= x2; i++) 1133 for (i = x1; i <= x2; i++)
1151 {
1152 for (j = y1; j < y2; j++) 1134 for (j = y1; j < y2; j++)
1135 if (op->map->is_in_shop (i, j))
1153 { 1136 {
1154 if (is_in_shop (op->map, i, j)) 1137 stack = GET_MAP_OB (op->map, i, j);
1138
1139 while (stack)
1155 { 1140 {
1156 stack = GET_MAP_OB (op->map, i, j); 1141 if (stack->flag [FLAG_UNPAID])
1157
1158 while (stack)
1159 { 1142 {
1160 if (QUERY_FLAG (stack, FLAG_UNPAID))
1161 {
1162 if (numitems == numallocated) 1143 if (numitems == numallocated)
1163 {
1164 items = (shopinv *) realloc (items, sizeof (shopinv) * (numallocated + 10)); 1144 items = (shopinv *)realloc (items, sizeof (shopinv) * (numallocated *= 2));
1165 numallocated += 10;
1166 }
1167 1145
1168 add_shop_item (stack, items, &numitems, &numallocated); 1146 add_shop_item (stack, items, &numitems, &numallocated);
1169 }
1170
1171 stack = stack->above;
1172 } 1147 }
1148
1149 stack = stack->above;
1173 } 1150 }
1174 } 1151 }
1175 }
1176 1152
1177 if (numitems == 0) 1153 buf << (numitems ? "T<This shop contains:>\n\n"
1178 { 1154 : "T<This shop is currently empty.>");
1179 new_draw_info (NDI_UNIQUE, 0, op, "The shop is currently empty.\n");
1180 free (items);
1181 return;
1182 }
1183 1155
1184 qsort (items, numitems, sizeof (shopinv), (int (*)(const void *, const void *)) shop_sort); 1156 qsort (items, numitems, sizeof (shopinv), (int (*)(const void *, const void *)) shop_sort);
1185
1186 new_draw_info (NDI_UNIQUE, 0, op, "\nThe shop contains:");
1187 1157
1188 for (i = 0; i < numitems; i++) 1158 for (i = 0; i < numitems; i++)
1189 { 1159 {
1190 /* Collapse items of the same name together */ 1160 /* Collapse items of the same name together */
1191 if ((i + 1) < numitems && !strcmp (items[i].item_real, items[i + 1].item_real)) 1161 if ((i + 1) < numitems && !strcmp (items[i].item_real, items[i + 1].item_real))
1192 {
1193 items[i + 1].nrof += items[i].nrof; 1162 items[i + 1].nrof += items[i].nrof;
1194 free (items[i].item_sort);
1195 free (items[i].item_real);
1196 }
1197 else 1163 else
1198 {
1199 new_draw_info_format (NDI_UNIQUE, 0, op, "%d %s",
1200 items[i].nrof ? items[i].nrof : 1, items[i].nrof == 1 ? items[i].item_sort : items[i].item_real); 1164 buf.printf (" %4d %s\n", items[i].nrof ? items[i].nrof : 1, items[i].nrof == 1 ? items[i].item_sort : items[i].item_real);
1165
1201 free (items[i].item_sort); 1166 free (items[i].item_sort);
1202 free (items[i].item_real); 1167 free (items[i].item_real);
1203 }
1204 } 1168 }
1169
1170 op->contr->infobox (MSG_CHANNEL ("shopitems"), buf);
1205 1171
1206 free (items); 1172 free (items);
1207}
1208
1209/* elmex: this function checks whether the object is in a shop */
1210bool
1211is_in_shop (object *o)
1212{
1213 if (!o->is_on_map ())
1214 return false;
1215
1216 return is_in_shop (o->map, o->x, o->y);
1217} 1173}
1218 1174
1219/* elmex: this function checks whether we are in a shop or not 1175/* elmex: this function checks whether we are in a shop or not
1220 - change 2007-11-26: enhanced the O(n) case by stopping at the first 1176 - change 2007-11-26: enhanced the O(n) case by stopping at the first
1221 floor tile. this possibly will make map bugs where shopfloors are above 1177 floor tile. this possibly will make map bugs where shopfloors are above
1222 floors more obvious. 1178 floors more obvious.
1223*/ 1179*/
1224
1225bool 1180bool
1226is_in_shop (maptile *map, int x, int y) 1181maptile::is_in_shop (int x, int y) const
1227{ 1182{
1228 for (object *floor = GET_MAP_OB (map, x, y); floor; floor = floor->above) 1183 for (object *floor = at (x, y).bot; floor; floor = floor->above)
1229 if (QUERY_FLAG (floor, FLAG_IS_FLOOR)) 1184 if (floor->flag [FLAG_IS_FLOOR])
1230 return floor->type == SHOP_FLOOR; 1185 return floor->type == SHOP_FLOOR;
1231 1186
1232 return false; 1187 return false;
1233} 1188}
1234 1189

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines