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.70 by root, Mon Oct 12 14:00:59 2009 UTC vs.
Revision 1.83 by root, Fri Apr 30 21:00:40 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,2009 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 it under 8 * Deliantra is free software: you can redistribute it and/or modify it under
9 * the terms of the Affero GNU General Public License as published by the 9 * the terms of the Affero GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your 10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version. 11 * option) any later version.
25#include <global.h> 25#include <global.h>
26#include <spells.h> 26#include <spells.h>
27#include <skills.h> 27#include <skills.h>
28#include <living.h> 28#include <living.h>
29#include <sproto.h> 29#include <sproto.h>
30#include <math.h>
31 30
32/* 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
33 * 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
34 * 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
35 * therefore making this number higher, makes specialisation less effective. 34 * therefore making this number higher, makes specialisation less effective.
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;
85 double diff;
86 84
87 approx_range = 0; 85 approx_range = 0;
88 86
89 no_bargain = flag & F_NO_BARGAIN; 87 no_bargain = flag & F_NO_BARGAIN;
90 identified = flag & F_IDENTIFIED; 88 identified = flag & F_IDENTIFIED;
91 not_cursed = flag & F_NOT_CURSED; 89 not_cursed = flag & F_NOT_CURSED;
92 approximate = flag & F_APPROX; 90 approximate = flag & F_APPROX;
93 shop = flag & F_SHOP; 91 shop = flag & F_SHOP;
94 flag &= ~(F_NO_BARGAIN | F_IDENTIFIED | F_NOT_CURSED | F_APPROX | F_SHOP); 92 flag &= ~(F_NO_BARGAIN | F_IDENTIFIED | F_NOT_CURSED | F_APPROX | F_SHOP);
95 93
94 int number = tmp->number_of ();
95
96 if (tmp->type == MONEY) 96 if (tmp->type == MONEY)
97 return tmp->nrof * tmp->value; 97 return number * tmp->value;
98 98
99 if (tmp->type == GEM) 99 if (tmp->type == GEM)
100 { 100 {
101 if (flag == F_TRUE) 101 if (flag == F_TRUE)
102 return (tmp->nrof * tmp->value); 102 return number * tmp->value;
103 103
104 if (flag == F_BUY) 104 if (flag == F_BUY)
105 return (sint64) (1.03 * tmp->nrof * tmp->value); 105 return 1.03 * number * tmp->value;
106 106
107 if (flag == F_SELL) 107 if (flag == F_SELL)
108 return (sint64) (0.97 * tmp->nrof * tmp->value); 108 return 0.97 * number * tmp->value;
109 109
110 LOG (llevError, "Query_cost: Gem type with unknown flag %d: %s\n", flag, tmp->debug_desc ()); 110 LOG (llevError, "Query_cost: Gem type with unknown flag %d: %s\n", flag, tmp->debug_desc ());
111 return 0; 111 return 0;
112 } 112 }
113 113
114 int number = tmp->number_of ();
115
116 if (QUERY_FLAG (tmp, FLAG_IDENTIFIED) || !need_identify (tmp) || identified) 114 if (tmp->flag [FLAG_IDENTIFIED] || !tmp->need_identify () || identified)
117 { 115 {
118 if (!not_cursed && (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED))) 116 if (!not_cursed && (tmp->flag [FLAG_CURSED] || tmp->flag [FLAG_DAMNED]))
119 return 0; 117 return 0;
120 else 118 else
121 val = tmp->value * number; 119 val = number * tmp->value;
122 } 120 }
123 /* This area deals with objects that are not identified, but can be */ 121 /* This area deals with objects that are not identified, but can be */
124 else 122 else
125 { 123 {
126 if (flag == F_BUY) 124 if (flag == F_BUY)
135 else 133 else
136 { 134 {
137 /* Get 2/3'rd value for applied objects, 1/3'rd for totally 135 /* Get 2/3'rd value for applied objects, 1/3'rd for totally
138 * unknown objects 136 * unknown objects
139 */ 137 */
140 if (QUERY_FLAG (tmp, FLAG_BEEN_APPLIED)) 138 if (tmp->flag [FLAG_BEEN_APPLIED])
141 val = number * tmp->arch->value * 2 / 3; 139 val = number * tmp->arch->value * 2 / 3;
142 else 140 else
143 val = number * tmp->arch->value / 3; 141 val = number * tmp->arch->value / 3;
144 } 142 }
145 } 143 }
146 } 144 }
147 145
148 /* If the item has been applied or identifed or does not need to be 146 /* If the item has been applied or identifed or does not need to be
152 * tmp->arch->magic for any magic. The check for archetype 150 * tmp->arch->magic for any magic. The check for archetype
153 * magic is to not give extra money for archetypes that are by 151 * magic is to not give extra money for archetypes that are by
154 * default magical. This is because the archetype value should have 152 * default magical. This is because the archetype value should have
155 * already figured in that value. 153 * already figured in that value.
156 */ 154 */
157 if ((QUERY_FLAG (tmp, FLAG_IDENTIFIED) || !need_identify (tmp) || identified || 155 if ((tmp->flag [FLAG_IDENTIFIED] || !tmp->need_identify () || identified || tmp->flag [FLAG_BEEN_APPLIED])
158 QUERY_FLAG (tmp, FLAG_BEEN_APPLIED)) && tmp->magic && (tmp->arch == NULL || !tmp->arch->magic)) 156 && tmp->magic && (!tmp->arch || !tmp->arch->magic))
159 { 157 {
160 if (tmp->magic > 0) 158 if (tmp->magic > 0)
161 val *= (3 * tmp->magic * tmp->magic * tmp->magic); 159 val *= 3 * tmp->magic * tmp->magic * tmp->magic;
162 else 160 else
163 /* Note that tmp->magic is negative, so that this 161 /* Note that tmp->magic is negative, so that this
164 * will actually be something like val /=2, /=3, etc. 162 * will actually be something like val /=2, /=3, etc.
165 */ 163 */
166 val /= (1 - tmp->magic); 164 val /= 1 - tmp->magic;
167 } 165 }
168 166
169 if (tmp->type == WAND) 167 if (tmp->type == WAND)
170 { 168 {
171 /* Value of the wand is multiplied by the number of 169 /* Value of the wand is multiplied by the number of
172 * charges. the treasure code already sets up the value 170 * charges. the treasure code already sets up the value
173 * 50 charges is used as the baseline. 171 * 50 charges is used as the baseline.
174 */ 172 */
175 if (QUERY_FLAG (tmp, FLAG_IDENTIFIED) || !need_identify (tmp) || identified) 173 if (tmp->flag [FLAG_IDENTIFIED] || !tmp->need_identify () || identified)
176 val = (val * tmp->stats.food) / 50; 174 val *= tmp->stats.food / 50;
177 else /* if not identified, presume one charge */ 175 else /* if not identified, presume one charge */
178 val /= 50; 176 val /= 50;
179 } 177 }
180 178
181 /* Limit amount of money you can get for really great items. */ 179 /* Limit amount of money you can get for really great items. */
182 if (flag == F_SELL) 180 if (flag == F_SELL)
183 val = value_limit ((sint64) val, number, who, shop); 181 val = value_limit (val, number, who, shop);
184 182
185 // use a nonlinear price adjustment. as my predecessor said, don't change 183 // use a nonlinear price adjustment. as my predecessor said, don't change
186 // the archetypes, its work required for balancing, and we don't care. 184 // the archetypes, its work required for balancing, and we don't care.
187 //val = pow (val, 1.05); 185 //val = pow (val, 1.05);
188 186
193 * -b.e. edler@heydernet.de 191 * -b.e. edler@heydernet.de
194 */ 192 */
195 193
196 if (who && who->type == PLAYER) 194 if (who && who->type == PLAYER)
197 { 195 {
198 int lev_bargain = 0; 196 int lev_bargain = 0;
199 int lev_identify = 0; 197 int lev_identify = 0;
200 198
201 if (find_skill_by_number (who, SK_BARGAINING)) 199 if (!no_bargain)
202 lev_bargain = find_skill_by_number (who, SK_BARGAINING)->level; 200 if (object *skill = find_skill_by_name (who, shstr_bargaining))
201 lev_bargain = skill->level;
203 202
204 if (const typedata *tmptype = get_typedata (tmp->type)) 203 if (const typedata *tmptype = get_typedata (tmp->type))
205 { 204 {
206 if (int idskill1 = tmptype->identifyskill) 205 if (int idskill1 = tmptype->identifyskill)
207 { 206 {
218 /* ratio determines how much of the price modification 217 /* ratio determines how much of the price modification
219 * will come from the basic stat charisma 218 * will come from the basic stat charisma
220 * the rest will come from the level in bargaining skill 219 * the rest will come from the level in bargaining skill
221 */ 220 */
222 const double cha_ratio = 0.40; 221 const double cha_ratio = 0.40;
223 222 double bargaining = min (0., 1. - powf (lev_bargain / MAXLEVEL_TREASURE, 0.25));
224 diff = no_bargain ? 1.0 : 1. - pow (lev_bargain / (double) settings.max_level, 0.25);
225 diff = (1. - cha_ratio) * diff + cha_ratio * (cha_bonus[who->stats.Cha] - 1.) / (cha_bonus[who->stats.Cha] + 1.); 223 double charisma = (cha_bonus[who->stats.Cha] - 1.) / (cha_bonus[who->stats.Cha] + 1.);
226 diff = .02 + (.80 - .02) * diff; 224
225 double factor = (1. - cha_ratio) * bargaining + cha_ratio * charisma;
226
227 // scale 0..1 to 2 .. 80%
228 factor = lerp (factor, 0., 1., 0.02, 0.80);
227 229
228 if (flag == F_BUY) 230 if (flag == F_BUY)
229 val += val * diff; 231 val += val * factor;
230 else if (flag == F_SELL) 232 else if (flag == F_SELL)
231 val -= val * diff; 233 val -= val * factor;
232 234
233 // now find a price range. the less good we can judge, the larger the range is 235 // now find a price range. the less good we can judge, the larger the range is
234 // then the range is adjusted randomly around the correct value 236 // then the range is adjusted randomly around the correct value
235 if (approximate) 237 if (approximate)
236 approx_range = sint64 (val / sqrt (lev_identify * 3 + 1)); 238 approx_range = val / sqrt (lev_identify * 3 + 1);
237 } 239 }
238 240
239 /* I don't think this should really happen - if it does, it indicates and 241 /* I don't think this should really happen - if it does, it indicates and
240 * overflow of diff above. That should only happen if 242 * overflow of diff above. That should only happen if
241 * we are selling objects - in that case, the person just 243 * we are selling objects - in that case, the person just
242 * gets no money. 244 * gets no money.
243 */ 245 */
244 if ((sint64) val < 0) 246 if ((sint64) val < 0)
245 val = 0; 247 val = 0;
246 248
247 /* Unidentified stuff won't sell for more than 60gp */ 249 /* Unidentified stuff won't sell for more than 10gp */
248 if (flag == F_SELL && !QUERY_FLAG (tmp, FLAG_IDENTIFIED) && need_identify (tmp) && !identified) 250 if (flag == F_SELL && !tmp->flag [FLAG_IDENTIFIED] && tmp->need_identify () && !identified)
249 { 251 min_it (val, 1000);
250 val = (val > 600) ? 600 : val;
251 }
252 252
253 /* if we are in a shop, check how the type of shop should affect the price */ 253 /* if we are in a shop, check how the type of shop should affect the price */
254 if (shop && who) 254 if (shop && who)
255 { 255 {
256 if (flag == F_SELL) 256 if (flag == F_SELL)
257 val = (val * shop_specialisation_ratio (tmp, who->map) * shopkeeper_approval (who->map, who) / shop_greed (who->map)); 257 val *= shop_specialisation_ratio (tmp, who->map) * shopkeeper_approval (who->map, who) / shop_greed (who->map);
258 else if (flag == F_BUY) 258 else if (flag == F_BUY)
259 { 259 {
260 /* 260 /*
261 * when buying, if the item was sold by another player, it is ok to 261 * when buying, if the item was sold by another player, it is ok to
262 * let the item be sold cheaper, according to the specialisation of 262 * let the item be sold cheaper, according to the specialisation of
268 * be sold for (otherwise players could camp map resets to make money). 268 * be sold for (otherwise players could camp map resets to make money).
269 * In game terms, a non-specialist shop, might not recognise the true 269 * In game terms, a non-specialist shop, might not recognise the true
270 * value of the items they sell (much like how people sometimes find 270 * value of the items they sell (much like how people sometimes find
271 * antiques in a junk shop in real life). 271 * antiques in a junk shop in real life).
272 */ 272 */
273 if (QUERY_FLAG (tmp, FLAG_PLAYER_SOLD)) 273 if (tmp->flag [FLAG_PLAYER_SOLD])
274 val = (val * shop_greed (who->map) * shop_specialisation_ratio (tmp, who->map) / shopkeeper_approval (who->map, who)); 274 val *= shop_specialisation_ratio (tmp, who->map);
275 else 275 else
276 val = (val * shop_greed (who->map) / (shop_specialisation_ratio (tmp, who->map) * shopkeeper_approval (who->map, who))); 276 val /= shop_specialisation_ratio (tmp, who->map);
277
278 val *= shop_greed (who->map) / shopkeeper_approval (who->map, who);
277 } 279 }
278 280
279 /* we will also have an extra 0-5% variation between shops of the same type 281 /* we will also have an extra 0-5% variation between shops of the same type
280 * for valuable items (below a value of 50 this effect wouldn't be very 282 * for valuable items (below a value of 50 this effect wouldn't be very
281 * pointful, and could give fun with rounding. 283 * pointful, and could give fun with rounding.
282 */ 284 */
283 //TODO: why use cosf at all, just % and scale linearly, gives more even distribution 285 //TODO: why use cosf at all, just % and scale linearly, gives more even distribution
284 if (val > 50) 286 if (val > 50)
285 val += float (val) * .05f * cosf ((tmp->uuid.seq & 0xffff) * float (M_PI * 2. / 0x10000)); 287 val *= 1 + .05f * cosf ((tmp->uuid.seq & 0xffff) * M_PI * 2. / 0x10000);
286 } 288 }
287 289
288 return (sint64) val; 290 return val;
289} 291}
290 292
291/* Find the coin type that is worth more the 'c'. Starts at the 293/* Find the coin type that is worth more the 'c'. Starts at the
292 * cointype placement. 294 * cointype placement.
293 */ 295 */
297{ 299{
298 archetype *coin; 300 archetype *coin;
299 301
300 do 302 do
301 { 303 {
302 if (coins[*cointype] == NULL) 304 if (!coins [*cointype])
303 return NULL; 305 return 0;
306
304 coin = archetype::find (coins[*cointype]); 307 coin = archetype::find (coins [*cointype]);
308
305 if (coin == NULL) 309 if (!coin)
306 return NULL; 310 return 0;
311
307 *cointype += 1; 312 *cointype += 1;
308 } 313 }
309 while (coin->value > c); 314 while (coin->value > c);
310 315
311 return coin; 316 return coin;
322 * 10,000 silver or something) 327 * 10,000 silver or something)
323 */ 328 */
324const char * 329const char *
325cost_string_from_value (sint64 cost, int approx) 330cost_string_from_value (sint64 cost, int approx)
326{ 331{
327 static char buf[MAX_BUF];
328 archetype *coin, *next_coin; 332 archetype *coin, *next_coin;
329 int num, cointype = 0; 333 int num, cointype = 0;
330 334
331 coin = find_next_coin (cost, &cointype); 335 coin = find_next_coin (cost, &cointype);
332 if (coin == NULL) 336 if (!coin)
333 return "nothing"; 337 return "nothing";
334 338
335 num = cost / coin->value; 339 num = cost / coin->value;
336 /* so long as nrof is 32 bit, this is true. 340 /* so long as nrof is 32 bit, this is true.
337 * If it takes more coins than a person can possibly carry, this 341 * If it takes more coins than a person can possibly carry, this
338 * is basically true. 342 * is basically true.
339 */ 343 */
340 if ((cost / coin->value) > UINT32_MAX) 344 if (cost / coin->value > UINT32_MAX)
341 {
342 strcpy (buf, "an unimaginable sum of money"); 345 return "an unimaginable sum of money";
343 return buf;
344 }
345 346
346 cost -= num * (sint64)coin->value; 347 cost -= num * (sint64)coin->value;
347 348
348 sprintf (buf, "%d %s", num, num > 1 ? &coin->object::name_pl : &coin->object::name); 349 char *buf = format ("%d %s", num, num > 1 ? &coin->object::name_pl : &coin->object::name);
349 350
350 next_coin = find_next_coin (cost, &cointype); 351 next_coin = find_next_coin (cost, &cointype);
351 if (next_coin == NULL || approx) 352 if (!next_coin || approx)
352 return buf; 353 return buf;
353 354
354 coin = next_coin; 355 coin = next_coin;
355 num = cost / coin->value; 356 num = cost / coin->value;
356 cost -= num * (sint64)coin->value; 357 cost -= num * (sint64)coin->value;
357 358
358 sprintf (buf + strlen (buf), " and %d %s", num, num > 1 ? &coin->object::name_pl : &coin->object::name); 359 return format ("%s and %d %s", buf, num, num > 1 ? &coin->object::name_pl : &coin->object::name);
359
360 return buf;
361} 360}
362 361
363const char * 362const char *
364query_cost_string (const object *tmp, object *who, int flag) 363query_cost_string (const object *tmp, object *who, int flag)
365{ 364{
384 { 383 {
385 if (!idskill1 || !find_skill_by_number (who, idskill1)) 384 if (!idskill1 || !find_skill_by_number (who, idskill1))
386 { 385 {
387 if (!idskill2 || !find_skill_by_number (who, idskill2)) 386 if (!idskill2 || !find_skill_by_number (who, idskill2))
388 { 387 {
389 if (!find_skill_by_number (who, SK_BARGAINING)) 388 if (!find_skill_by_name (who, shstr_bargaining))
390 { 389 {
391 static char buf[MAX_BUF];
392 int num, cointype = 0; 390 int num, cointype = 0;
393 archetype *coin = find_next_coin (real_value, &cointype); 391 archetype *coin = find_next_coin (real_value, &cointype);
394 392
395 if (coin == NULL) 393 if (!coin)
396 return "nothing"; 394 return "nothing";
397 395
398 num = real_value / coin->value; 396 num = real_value / coin->value;
399 397
400 if (num == 1) 398 if (num == 1)
401 sprintf (buf, "about one %s", &coin->object::name); 399 return format ("about one %s", &coin->object::name);
402 else if (num < 5) 400 else if (num < 5)
403 sprintf (buf, "a few %s", &coin->object::name_pl); 401 return format ("a few %s", &coin->object::name_pl);
404 else if (num < 10) 402 else if (num < 10)
405 sprintf (buf, "several %s", &coin->object::name_pl); 403 return format ("several %s", &coin->object::name_pl);
406 else if (num < 25) 404 else if (num < 25)
407 sprintf (buf, "a moderate amount of %s", &coin->object::name_pl); 405 return format ("a moderate amount of %s", &coin->object::name_pl);
408 else if (num < 100) 406 else if (num < 100)
409 sprintf (buf, "lots of %s", &coin->object::name_pl); 407 return format ("lots of %s", &coin->object::name_pl);
410 else if (num < 1000) 408 else if (num < 1000)
411 sprintf (buf, "a great many %s", &coin->object::name_pl); 409 return format ("a great many %s", &coin->object::name_pl);
412 else 410 else
413 sprintf (buf, "a vast quantity of %s", &coin->object::name_pl); 411 return format ("a vast quantity of %s", &coin->object::name_pl);
414
415 return buf;
416 } 412 }
417 } 413 }
418 } 414 }
419 415
420 int hash = ((unsigned int) tmp->count * 174364621) & 1023;
421
422 if (approx_range) 416 if (approx_range)
423 { 417 {
418 int hash = tmp->random_seed () & 1023;
424 sint64 lo = (sint64) real_value - (approx_range * hash >> 10); 419 sint64 lo = real_value - (approx_range * hash >> 10);
425 static char buf[MAX_BUF];
426 420
427 sprintf (buf, "between %s", cost_string_from_value (lo, 1)); 421 return format ("between %s and %s",
428 sprintf (buf + strlen (buf), " and %s", cost_string_from_value (lo + approx_range, 1)); 422 cost_string_from_value (lo, 1),
429 423 cost_string_from_value (lo + approx_range, 1));
430 return buf;
431 } 424 }
432 } 425 }
433 426
434 return cost_string_from_value (real_value, 0); 427 return cost_string_from_value (real_value, 0);
435} 428}
450 } 443 }
451 444
452 for (tmp = op->inv; tmp; tmp = tmp->below) 445 for (tmp = op->inv; tmp; tmp = tmp->below)
453 if (tmp->type == MONEY) 446 if (tmp->type == MONEY)
454 total += tmp->nrof * (sint64)tmp->value; 447 total += tmp->nrof * (sint64)tmp->value;
455 else if (tmp->type == CONTAINER && QUERY_FLAG (tmp, FLAG_APPLIED) && (!tmp->race || tmp->race.contains ("gold"))) 448 else if (tmp->type == CONTAINER && tmp->flag [FLAG_APPLIED] && (!tmp->race || tmp->race.contains ("gold")))
456 total += query_money (tmp); 449 total += query_money (tmp);
457 450
458 return total; 451 return total;
459} 452}
460 453
475 return 0; 468 return 0;
476 469
477 pay_from_container (pl, pl, to_pay); 470 pay_from_container (pl, pl, to_pay);
478 471
479 for (pouch = pl->inv; pouch && to_pay; pouch = pouch->below) 472 for (pouch = pl->inv; pouch && to_pay; pouch = pouch->below)
480 if (pouch->type == CONTAINER && QUERY_FLAG (pouch, FLAG_APPLIED) && (!pouch->race || pouch->race.contains ("gold"))) 473 if (pouch->type == CONTAINER && pouch->flag [FLAG_APPLIED] && (!pouch->race || pouch->race.contains ("gold")))
481 pay_from_container (pl, pouch, to_pay); 474 pay_from_container (pl, pouch, to_pay);
482 475
483 pl->update_stats (); 476 pl->update_stats ();
484 return 1; 477 return 1;
485} 478}
507 * This determins the amount of exp (if any) gained for bargaining. 500 * This determins the amount of exp (if any) gained for bargaining.
508 */ 501 */
509 saved_money = query_cost (op, pl, F_BUY | F_NO_BARGAIN | F_SHOP) - to_pay; 502 saved_money = query_cost (op, pl, F_BUY | F_NO_BARGAIN | F_SHOP) - to_pay;
510 503
511 if (saved_money > 0) 504 if (saved_money > 0)
512 change_exp (pl, saved_money, "bargaining", SK_EXP_NONE); 505 change_exp (pl, saved_money, shstr_bargaining, SK_EXP_NONE);
513 506
514 pay_from_container (pl, pl, to_pay); 507 pay_from_container (pl, pl, to_pay);
515 508
516 for (pouch = pl->inv; pouch && to_pay; pouch = pouch->below) 509 for (pouch = pl->inv; pouch && to_pay; pouch = pouch->below)
517 if (pouch->type == CONTAINER && QUERY_FLAG (pouch, FLAG_APPLIED) && (!pouch->race || pouch->race.contains ("gold"))) 510 if (pouch->type == CONTAINER && pouch->flag [FLAG_APPLIED] && (!pouch->race || pouch->race.contains ("gold")))
518 pay_from_container (pl, pouch, to_pay); 511 pay_from_container (pl, pouch, to_pay);
519 512
520 pl->update_stats (); 513 pl->update_stats ();
521 514
522 return 1; 515 return 1;
589 at = archetype::find (coins[NUM_COINS - 1 - i]); 582 at = archetype::find (coins[NUM_COINS - 1 - i]);
590 583
591 if (at == NULL) 584 if (at == NULL)
592 LOG (llevError, "Could not find %s archetype\n", coins[NUM_COINS - 1 - i]); 585 LOG (llevError, "Could not find %s archetype\n", coins[NUM_COINS - 1 - i]);
593 586
594 coin_objs[i] = arch_to_object (at); 587 coin_objs[i] = at->instance ();
595 coin_objs[i]->nrof = 0; 588 coin_objs[i]->nrof = 0;
596 } 589 }
597 590
598 for (i = 0; i < NUM_COINS; i++) 591 for (i = 0; i < NUM_COINS; i++)
599 { 592 {
641 LOG (llevError, "can_pay(): called against something that isn't a player\n"); 634 LOG (llevError, "can_pay(): called against something that isn't a player\n");
642 return 0; 635 return 0;
643 } 636 }
644 637
645 for (object::depth_iterator item = pl->begin (); item != pl->end (); ++item) 638 for (object::depth_iterator item = pl->begin (); item != pl->end (); ++item)
646 if (QUERY_FLAG (item, FLAG_UNPAID)) 639 if (item->flag [FLAG_UNPAID])
647 { 640 {
648 unpaid_count++; 641 unpaid_count++;
649 unpaid_price += query_cost (item, pl, F_BUY | F_SHOP); 642 unpaid_price += query_cost (item, pl, F_BUY | F_SHOP);
650 } 643 }
651 644
680 { 673 {
681 next_item: 674 next_item:
682 675
683 for (object::depth_iterator op = pl->begin (); op != pl->end (); ++op) 676 for (object::depth_iterator op = pl->begin (); op != pl->end (); ++op)
684 { 677 {
685 if (QUERY_FLAG (op, FLAG_UNPAID)) 678 if (op->flag [FLAG_UNPAID])
686 { 679 {
687 char buf[MAX_BUF];
688 snprintf (buf, MAX_BUF, "%s", query_cost_string (op, pl, F_BUY | F_SHOP)); 680 const char *buf = query_cost_string (op, pl, F_BUY | F_SHOP);
689 681
690 if (!pay_for_item (op, pl)) 682 if (!pay_for_item (op, pl))
691 { 683 {
692 sint64 i = query_cost (op, pl, F_BUY | F_SHOP) - query_money (pl); 684 sint64 i = query_cost (op, pl, F_BUY | F_SHOP) - query_money (pl);
693 685
694 CLEAR_FLAG (op, FLAG_UNPAID); 686 op->clr_flag (FLAG_UNPAID);
695 new_draw_info_format (NDI_UNIQUE, 0, pl, "You lack %s to buy %s.", cost_string_from_value (i, 0), query_name (op)); 687 new_draw_info_format (NDI_UNIQUE, 0, pl, "You lack %s to buy %s.", cost_string_from_value (i, 0), query_name (op));
696 SET_FLAG (op, FLAG_UNPAID); 688 op->set_flag (FLAG_UNPAID);
697 return 0; 689 return 0;
698 } 690 }
699 else 691 else
700 { 692 {
701 CLEAR_FLAG (op, FLAG_UNPAID); 693 op->clr_flag (FLAG_UNPAID);
702 CLEAR_FLAG (op, FLAG_PLAYER_SOLD); 694 op->clr_flag (FLAG_PLAYER_SOLD);
703 new_draw_info_format (NDI_UNIQUE, 0, op, "You paid %s for %s.", buf, query_name (op)); 695 new_draw_info_format (NDI_UNIQUE, 0, pl, "You paid %s for %s.", buf, query_name (op));
704 696
705 if (!merge_ob (op, op->env->inv)) 697 if (!merge_ob (op, op->env->inv))
706 esrv_update_item (UPD_FLAGS, pl, op); 698 esrv_update_item (UPD_FLAGS, pl, op);
707 699
708 goto next_item; 700 goto next_item;
740 LOG (llevError, "Could not find %s archetype\n", coins[count]); 732 LOG (llevError, "Could not find %s archetype\n", coins[count]);
741 else if ((amount / at->value) > 0) 733 else if ((amount / at->value) > 0)
742 { 734 {
743 for (pouch = pl->inv; pouch; pouch = pouch->below) 735 for (pouch = pl->inv; pouch; pouch = pouch->below)
744 { 736 {
745 if (pouch->type == CONTAINER && QUERY_FLAG (pouch, FLAG_APPLIED) && pouch->race.contains ("gold")) 737 if (pouch->type == CONTAINER && pouch->flag [FLAG_APPLIED] && pouch->race.contains ("gold"))
746 { 738 {
747 int w = at->weight * (100 - pouch->stats.Str) / 100; 739 int w = at->weight * (100 - pouch->stats.Str) / 100;
748 int n = amount / at->value; 740 int n = amount / at->value;
749 741
750 if (w == 0) 742 if (w == 0)
753 if (n > 0 && (!pouch->weight_limit || pouch->carrying + w <= pouch->weight_limit)) 745 if (n > 0 && (!pouch->weight_limit || pouch->carrying + w <= pouch->weight_limit))
754 { 746 {
755 if (pouch->weight_limit && (pouch->weight_limit - pouch->carrying) / w < n) 747 if (pouch->weight_limit && (pouch->weight_limit - pouch->carrying) / w < n)
756 n = (pouch->weight_limit - pouch->carrying) / w; 748 n = (pouch->weight_limit - pouch->carrying) / w;
757 749
758 object *tmp = arch_to_object (at); 750 object *tmp = at->instance ();
759 tmp->nrof = n; 751 tmp->nrof = n;
760 amount -= tmp->nrof * tmp->value; 752 amount -= tmp->nrof * tmp->value;
761 pouch->insert (tmp); 753 pouch->insert (tmp);
762 } 754 }
763 } 755 }
764 } 756 }
765 757
766 if (amount / at->value > 0) 758 if (amount / at->value > 0)
767 { 759 {
768 object *tmp = arch_to_object (at); 760 object *tmp = at->instance ();
769 tmp->nrof = amount / tmp->value; 761 tmp->nrof = amount / tmp->value;
770 amount -= tmp->nrof * tmp->value; 762 amount -= tmp->nrof * tmp->value;
771 pl->insert (tmp); 763 pl->insert (tmp);
772 } 764 }
773 } 765 }
830 * exp/10 -> 1 for each gold coin 822 * exp/10 -> 1 for each gold coin
831 */ 823 */
832 extra_gain = amount - query_cost (op, pl, F_SELL | F_NO_BARGAIN | F_SHOP); 824 extra_gain = amount - query_cost (op, pl, F_SELL | F_NO_BARGAIN | F_SHOP);
833 825
834 if (extra_gain > 0) 826 if (extra_gain > 0)
835 change_exp (pl, extra_gain / 10, "bargaining", SK_EXP_NONE); 827 change_exp (pl, extra_gain / 10, shstr_bargaining, SK_EXP_NONE);
836 828
837 pay_player (pl, amount); 829 pay_player (pl, amount);
838 830
839 new_draw_info_format (NDI_UNIQUE, 0, pl, "You receive %s for %s.", 831 new_draw_info_format (NDI_UNIQUE, 0, pl, "You receive %s for %s.",
840 query_cost_string (op, pl, F_SELL | F_SHOP), query_name (op)); 832 query_cost_string (op, pl, F_SELL | F_SHOP), query_name (op));
841 pl->play_sound (sound_find ("shop_sell")); 833 pl->play_sound (sound_find ("shop_sell"));
842 834
843 SET_FLAG (op, FLAG_UNPAID); 835 op->set_flag (FLAG_UNPAID);
844 identify (op); 836 identify (op);
845 837
846 return true; 838 return true;
847} 839}
848 840
852 */ 844 */
853static double 845static double
854shop_specialisation_ratio (const object *item, const maptile *map) 846shop_specialisation_ratio (const object *item, const maptile *map)
855{ 847{
856 shopitems *items = map->shopitems; 848 shopitems *items = map->shopitems;
857 double likedness = 0.; 849 int likedness = 0;
858 int i; 850 int i;
859 851
860 if (item == NULL) 852 if (item == NULL)
861 { 853 {
862 LOG (llevError, "shop_specialisation_ratio: passed a NULL item for map %s\n", &map->path); 854 LOG (llevError, "shop_specialisation_ratio: passed a NULL item for map %s\n", &map->path);
872 */ 864 */
873 return SPECIALISATION_EFFECT; 865 return SPECIALISATION_EFFECT;
874 } 866 }
875 867
876 if (map->shopitems) 868 if (map->shopitems)
877 {
878 for (i = 0; i < items[0].index; i++) 869 for (i = 0; i < items[0].index; i++)
879 if (items[i].typenum == item->type || (!items[i].typenum && likedness == 0.001)) 870 if (items[i].typenum == item->type || (!items[i].typenum && !likedness))
880 likedness = items[i].strength / 100.0; 871 likedness = items[i].strength;
881 }
882 872
883 if (likedness > 1.0) 873 if (likedness > 100)
884 { /* someone has been rather silly with the map headers. */ 874 { /* someone has been rather silly with the map headers. */
885 LOG (llevDebug, "shop_specialisation ratio: item type %d on map %s is above 100%%\n", item->type, &map->path); 875 LOG (llevDebug, "shop_specialisation ratio: item type %d on map %s is above 100%%\n", item->type, &map->path);
886 likedness = 1.0; 876 likedness = 100;
887 } 877 }
888 878
889 if (likedness < -1.0) 879 if (likedness < -100)
890 { 880 {
891 LOG (llevDebug, "shop_specialisation ratio: item type %d on map %s is below -100%%\n", item->type, &map->path); 881 LOG (llevDebug, "shop_specialisation ratio: item type %d on map %s is below -100%%\n", item->type, &map->path);
892 likedness = -1.0; 882 likedness = -100;
893 } 883 }
894 884
895 return lerp (likedness, -1., 1., SPECIALISATION_EFFECT, 1.); 885 return lerp (double (likedness), -100., 100., SPECIALISATION_EFFECT, 1.);
896} 886}
897 887
898/*returns the greed of the shop on map, or 1 if it isn't specified. */ 888/*returns the greed of the shop on map, or 1 if it isn't specified. */
899static double 889static double
900shop_greed (const maptile *map) 890shop_greed (const maptile *map)
950 tmpshopmax = map->shopmax ? map->shopmax : 100000; // 20 royalties default 940 tmpshopmax = map->shopmax ? map->shopmax : 100000; // 20 royalties default
951 941
952 if (map->shopmin && unit_price < map->shopmin) 942 if (map->shopmin && unit_price < map->shopmin)
953 return 0; 943 return 0;
954 else if (unit_price > tmpshopmax / 2) 944 else if (unit_price > tmpshopmax / 2)
955 newval = MIN ((tmpshopmax / 2) + isqrt (unit_price - tmpshopmax / 2), tmpshopmax); 945 newval = min ((tmpshopmax / 2) + isqrt (unit_price - tmpshopmax / 2), tmpshopmax);
956 else 946 else
957 newval = unit_price; 947 newval = unit_price;
958 } 948 }
959 949
960 newval *= quantity; 950 newval *= quantity;
964 954
965/* gives a desciption of the shop on their current map to the player op. */ 955/* gives a desciption of the shop on their current map to the player op. */
966int 956int
967describe_shop (const object *op) 957describe_shop (const object *op)
968{ 958{
959 dynbuf_text buf;
969 maptile *map = op->map; 960 maptile *map = op->map;
970 961
971 /*shopitems *items=map->shopitems; */ 962 /*shopitems *items=map->shopitems; */
972 int pos = 0, i; 963 int pos = 0, i;
973 double opinion = 0; 964 double opinion = 0;
974 char tmp[MAX_BUF] = "\0";
975 965
976 if (op->type != PLAYER) 966 if (op->type != PLAYER)
977 return 0; 967 return 0;
978 968
979 /*check if there is a shop specified for this map */ 969 /*check if there is a shop specified for this map */
980 if (map->shopitems || map->shopgreed || map->shoprace || map->shopmin || map->shopmax) 970 if (map->shopitems || map->shopgreed || map->shoprace || map->shopmin || map->shopmax)
981 { 971 {
982 new_draw_info (NDI_UNIQUE, 0, op, "From looking at the nearby shop you determine that it trades in:"); 972 buf << "From looking at the nearby shop you determine that it trades in ";
973 int lastcomma = 0, prevcomma = 0;
983 974
984 if (map->shopitems) 975 if (map->shopitems)
985 for (i = 0; i < map->shopitems[0].index; i++) 976 for (i = 0; i < map->shopitems[0].index; i++)
986 if (map->shopitems[i].name && map->shopitems[i].strength > 10) 977 if (map->shopitems[i].name && map->shopitems[i].strength > 10)
987 { 978 {
988 snprintf (tmp + pos, sizeof (tmp) - pos, "%s, ", map->shopitems[i].name_pl); 979 buf << map->shopitems[i].name_pl;
989 pos += strlen (tmp + pos); 980 prevcomma = lastcomma;
981 lastcomma = buf.size (); // remember offset
982 buf << ", ";
990 } 983 }
991 984
992 if (!pos) 985 if (lastcomma)
986 {
987 buf.splice (lastcomma, 2);
988
989 if (prevcomma)
990 buf.splice (prevcomma, 2, " and ");
991 }
992 else
993 strcat (tmp, "a little of everything."); 993 buf << "a little of everything.";
994 994
995 /* format the string into a list */ 995 buf << ".\n\n";
996 make_list_like (tmp);
997 new_draw_info_format (NDI_UNIQUE, 0, op, "%s", tmp);
998 996
999 if (map->shopmax) 997 if (map->shopmax)
1000 new_draw_info_format (NDI_UNIQUE, 0, op, "It won't trade for items above %s.", cost_string_from_value (map->shopmax, 0)); 998 buf << "It won't trade for items above " << cost_string_from_value (map->shopmax, 0) << ".\n\n";
1001 999
1002 if (map->shopmin) 1000 if (map->shopmin)
1003 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)); 1001 buf << "It won't trade in items worth less than " << cost_string_from_value (map->shopmin, 0) << ".\n\n";
1004 1002
1005 if (map->shopgreed) 1003 if (map->shopgreed)
1006 { 1004 {
1007 if (map->shopgreed > 2.0) 1005 if (map->shopgreed > 2.0)
1008 new_draw_info (NDI_UNIQUE, 0, op, "It tends to overcharge massively."); 1006 buf << "It tends to overcharge massively.\n\n";
1009 else if (map->shopgreed > 1.5) 1007 else if (map->shopgreed > 1.5)
1010 new_draw_info (NDI_UNIQUE, 0, op, "It tends to overcharge substantially."); 1008 buf << "It tends to overcharge substantially.\n\n";
1011 else if (map->shopgreed > 1.1) 1009 else if (map->shopgreed > 1.1)
1012 new_draw_info (NDI_UNIQUE, 0, op, "It tends to overcharge slightly."); 1010 buf << "It tends to overcharge slightly.\n\n";
1013 else if (map->shopgreed < 0.9) 1011 else if (map->shopgreed < 0.9)
1014 new_draw_info (NDI_UNIQUE, 0, op, "It tends to undercharge."); 1012 buf << "It tends to undercharge.\n\n";
1015 } 1013 }
1016 1014
1017 if (map->shoprace) 1015 if (map->shoprace)
1018 { 1016 {
1019 opinion = shopkeeper_approval (map, op); 1017 opinion = shopkeeper_approval (map, op);
1018
1020 if (opinion > 0.8) 1019 if (opinion > 0.8)
1021 new_draw_info (NDI_UNIQUE, 0, op, "You think the shopkeeper likes you."); 1020 buf << "You think the shopkeeper likes you.\n\n";
1022 else if (opinion > 0.5) 1021 else if (opinion > 0.5)
1023 new_draw_info (NDI_UNIQUE, 0, op, "The shopkeeper seems unconcerned by you."); 1022 buf << "The shopkeeper seems unconcerned by you.\n\n";
1024 else 1023 else
1025 new_draw_info (NDI_UNIQUE, 0, op, "The shopkeeper seems to have taken a dislike to you."); 1024 buf << "The shopkeeper seems to have taken a dislike to you.\n\n";
1026 } 1025 }
1027 } 1026 }
1028 else 1027 else
1029 new_draw_info (NDI_UNIQUE, 0, op, "There is no shop nearby."); 1028 buf << "There is no shop nearby.\n\n";
1029
1030 op->contr->infobox (MSG_CHANNEL ("shopinfo"), buf);
1030 1031
1031 return 1; 1032 return 1;
1032} 1033}
1033 1034
1034struct shopinv 1035struct shopinv
1062} 1063}
1063 1064
1064static void 1065static void
1065add_shop_item (object *tmp, shopinv * items, int *numitems, int *numallocated) 1066add_shop_item (object *tmp, shopinv * items, int *numitems, int *numallocated)
1066{ 1067{
1067#if 0
1068 char buf[MAX_BUF];
1069#endif
1070 /* clear unpaid flag so that doesn't come up in query 1068 /* clear unpaid flag so that doesn't come up in query
1071 * string. We clear nrof so that we can better sort 1069 * string. We clear nrof so that we can better sort
1072 * the object names. 1070 * the object names.
1073 */ 1071 */
1074 1072
1075 CLEAR_FLAG (tmp, FLAG_UNPAID); 1073 tmp->clr_flag (FLAG_UNPAID);
1076 items[*numitems].nrof = tmp->nrof; 1074 items[*numitems].nrof = tmp->nrof;
1077 /* Non mergable items have nrof of 0, but count them as one 1075 /* Non mergable items have nrof of 0, but count them as one
1078 * so the display is properly. 1076 * so the display is properly.
1079 */ 1077 */
1080 if (tmp->nrof == 0) 1078 if (tmp->nrof == 0)
1103 items[*numitems].item_real = strdup (query_base_name (tmp, 1)); 1101 items[*numitems].item_real = strdup (query_base_name (tmp, 1));
1104 (*numitems)++; 1102 (*numitems)++;
1105 break; 1103 break;
1106 } 1104 }
1107 1105
1108 SET_FLAG (tmp, FLAG_UNPAID); 1106 tmp->set_flag (FLAG_UNPAID);
1109} 1107}
1110 1108
1111void 1109void
1112shop_listing (object *sign, object *op) 1110shop_listing (object *sign, object *op)
1113{ 1111{
1135 items = (shopinv *)malloc (sizeof (shopinv) * numallocated); 1133 items = (shopinv *)malloc (sizeof (shopinv) * numallocated);
1136 1134
1137 /* Find all the appropriate items */ 1135 /* Find all the appropriate items */
1138 for (i = x1; i <= x2; i++) 1136 for (i = x1; i <= x2; i++)
1139 for (j = y1; j < y2; j++) 1137 for (j = y1; j < y2; j++)
1140 if (is_in_shop (op->map, i, j)) 1138 if (op->map->is_in_shop (i, j))
1141 { 1139 {
1142 stack = GET_MAP_OB (op->map, i, j); 1140 stack = GET_MAP_OB (op->map, i, j);
1143 1141
1144 while (stack) 1142 while (stack)
1145 { 1143 {
1146 if (QUERY_FLAG (stack, FLAG_UNPAID)) 1144 if (stack->flag [FLAG_UNPAID])
1147 { 1145 {
1148 if (numitems == numallocated) 1146 if (numitems == numallocated)
1149 items = (shopinv *)realloc (items, sizeof (shopinv) * (numallocated *= 2)); 1147 items = (shopinv *)realloc (items, sizeof (shopinv) * (numallocated *= 2));
1150 1148
1151 add_shop_item (stack, items, &numitems, &numallocated); 1149 add_shop_item (stack, items, &numitems, &numallocated);
1175 op->contr->infobox (MSG_CHANNEL ("shopitems"), buf); 1173 op->contr->infobox (MSG_CHANNEL ("shopitems"), buf);
1176 1174
1177 free (items); 1175 free (items);
1178} 1176}
1179 1177
1180/* elmex: this function checks whether the object is in a shop */
1181bool
1182is_in_shop (object *o)
1183{
1184 if (!o->is_on_map ())
1185 return false;
1186
1187 return is_in_shop (o->map, o->x, o->y);
1188}
1189
1190/* elmex: this function checks whether we are in a shop or not 1178/* elmex: this function checks whether we are in a shop or not
1191 - change 2007-11-26: enhanced the O(n) case by stopping at the first 1179 - change 2007-11-26: enhanced the O(n) case by stopping at the first
1192 floor tile. this possibly will make map bugs where shopfloors are above 1180 floor tile. this possibly will make map bugs where shopfloors are above
1193 floors more obvious. 1181 floors more obvious.
1194*/ 1182*/
1195
1196bool 1183bool
1197is_in_shop (maptile *map, int x, int y) 1184maptile::is_in_shop (int x, int y) const
1198{ 1185{
1199 for (object *floor = GET_MAP_OB (map, x, y); floor; floor = floor->above) 1186 for (object *floor = at (x, y).bot; floor; floor = floor->above)
1200 if (QUERY_FLAG (floor, FLAG_IS_FLOOR)) 1187 if (floor->flag [FLAG_IS_FLOOR])
1201 return floor->type == SHOP_FLOOR; 1188 return floor->type == SHOP_FLOOR;
1202 1189
1203 return false; 1190 return false;
1204} 1191}
1205 1192

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines