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.46 by root, Wed Apr 9 14:36:47 2008 UTC vs.
Revision 1.93 by root, Wed Nov 16 23:42:03 2016 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 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 4 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 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;
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 number = tmp->nrof;
115 if (number == 0)
116 number = 1;
117 if (QUERY_FLAG (tmp, FLAG_IDENTIFIED) || !need_identify (tmp) || identified) 114 if (tmp->flag [FLAG_IDENTIFIED] || !tmp->need_identify () || identified)
118 { 115 {
119 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]))
120 return 0; 117 return 0;
121 else 118 else
122 val = tmp->value * number; 119 val = number * tmp->value;
123 } 120 }
124 /* 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 */
125 else 122 else
126 { 123 {
127 if (tmp->arch != NULL)
128 {
129 if (flag == F_BUY) 124 if (flag == F_BUY)
125 {
126 LOG (llevError | logBacktrace, "Asking for buy-value of unidentified object: %s\n", tmp->debug_desc ());
127 val = tmp->arch->value * 50 * number;
128 }
129 else
130 { /* Trying to sell something, or get true value */
131 if (tmp->type == POTION)
132 val = number * 40; /* Don't want to give anything away */
133 else
130 { 134 {
131 LOG (llevError, "Asking for buy-value of unidentified object.\n"); 135 /* Get 2/3'rd value for applied objects, 1/3'rd for totally
132 val = tmp->arch->value * 50 * number; 136 * unknown objects
137 */
138 if (tmp->flag [FLAG_BEEN_APPLIED])
139 val = number * tmp->arch->value * 2 / 3;
140 else
141 val = number * tmp->arch->value / 3;
133 } 142 }
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, "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 } 143 }
161 } 144 }
162 145
163 /* 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
164 * identified, AND the object is magical and the archetype is non 147 * identified, AND the object is magical and the archetype is non
167 * tmp->arch->magic for any magic. The check for archetype 150 * tmp->arch->magic for any magic. The check for archetype
168 * 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
169 * default magical. This is because the archetype value should have 152 * default magical. This is because the archetype value should have
170 * already figured in that value. 153 * already figured in that value.
171 */ 154 */
172 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])
173 QUERY_FLAG (tmp, FLAG_BEEN_APPLIED)) && tmp->magic && (tmp->arch == NULL || !tmp->arch->magic)) 156 && tmp->magic && (!tmp->arch || !tmp->arch->magic))
174 { 157 {
175 if (tmp->magic > 0) 158 if (tmp->magic > 0)
176 val *= (3 * tmp->magic * tmp->magic * tmp->magic); 159 val *= 3 * tmp->magic * tmp->magic * tmp->magic;
177 else 160 else
178 /* Note that tmp->magic is negative, so that this 161 /* Note that tmp->magic is negative, so that this
179 * will actually be something like val /=2, /=3, etc. 162 * will actually be something like val /=2, /=3, etc.
180 */ 163 */
181 val /= (1 - tmp->magic); 164 val /= 1 - tmp->magic;
182 } 165 }
183 166
184 if (tmp->type == WAND) 167 if (tmp->type == WAND)
185 { 168 {
186 /* Value of the wand is multiplied by the number of 169 /* Value of the wand is multiplied by the number of
187 * charges. the treasure code already sets up the value 170 * charges. the treasure code already sets up the value
188 * 50 charges is used as the baseline. 171 * 50 charges is used as the baseline.
189 */ 172 */
190 if (QUERY_FLAG (tmp, FLAG_IDENTIFIED) || !need_identify (tmp) || identified) 173 if (tmp->flag [FLAG_IDENTIFIED] || !tmp->need_identify () || identified)
191 val = (val * tmp->stats.food) / 50; 174 val *= tmp->stats.food;
192 else /* if not identified, presume one charge */ 175 /* if not identified, presume one charge */
193 val /= 50; 176 val /= 50;
194 } 177 }
195 178
196 /* Limit amount of money you can get for really great items. */ 179 /* Limit amount of money you can get for really great items. */
197 if (flag == F_SELL) 180 if (flag == F_SELL)
198 val = value_limit ((sint64) val, number, who, shop); 181 val = value_limit (val, number, who, shop);
199 182
200 // 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
201 // 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.
202 //val = pow (val, 1.05); 185 //val = pow (val, 1.05);
203 186
206 * AND Cha = 30 will get optimal price. 189 * AND Cha = 30 will get optimal price.
207 * Thus charisma will never get useless. 190 * Thus charisma will never get useless.
208 * -b.e. edler@heydernet.de 191 * -b.e. edler@heydernet.de
209 */ 192 */
210 193
211 if (who != NULL && who->type == PLAYER) 194 if (who && who->is_player ())
212 { 195 {
213 int lev_bargain = 0; 196 int lev_bargain = 0;
214 int lev_identify = 0; 197 int lev_identify = 0;
215 int idskill1 = 0;
216 int idskill2 = 0;
217 const typedata *tmptype;
218 198
199 if (!no_bargain)
200 if (object *skill = find_skill_by_name (who, shstr_bargaining))
201 lev_bargain = skill->level;
202
219 tmptype = get_typedata (tmp->type); 203 if (const typedata *tmptype = get_typedata (tmp->type))
220
221 if (find_skill_by_number (who, SK_BARGAINING))
222 lev_bargain = find_skill_by_number (who, SK_BARGAINING)->level;
223
224 if (tmptype)
225 { 204 {
226 idskill1 = tmptype->identifyskill; 205 if (int idskill1 = tmptype->identifyskill)
227
228 if (idskill1)
229 { 206 {
230 idskill2 = tmptype->identifyskill2; 207 int idskill2 = tmptype->identifyskill2;
231 208
232 if (find_skill_by_number (who, idskill1)) 209 if (find_skill_by_number (who, idskill1))
233 lev_identify = find_skill_by_number (who, idskill1)->level; 210 lev_identify = find_skill_by_number (who, idskill1)->level;
234 211
235 if (idskill2 && find_skill_by_number (who, idskill2)) 212 if (idskill2 && find_skill_by_number (who, idskill2))
236 lev_identify += find_skill_by_number (who, idskill2)->level; 213 lev_identify += find_skill_by_number (who, idskill2)->level;
237 } 214 }
238 } 215 }
239 else
240 LOG (llevError, "Query_cost: item %s hasn't got a valid type\n", tmp->debug_desc ());
241 216
242 /* ratio determines how much of the price modification 217 /* ratio determines how much of the price modification
243 * will come from the basic stat charisma 218 * will come from the basic stat charisma
244 * the rest will come from the level in bargaining skill 219 * the rest will come from the level in bargaining skill
245 */ 220 */
246 const double cha_ratio = 0.40; 221 const double cha_ratio = 0.40;
247 222 double bargaining = max (0., 1. - powf (double (lev_bargain) / MAXLEVEL_TREASURE, 0.25));
248 diff = no_bargain ? 1.0 : 1. - pow (lev_bargain / (double) settings.max_level, 0.25);
249 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.);
250 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);
251 229
252 if (flag == F_BUY) 230 if (flag == F_BUY)
253 val += val * diff; 231 val += val * factor;
254 else if (flag == F_SELL) 232 else if (flag == F_SELL)
255 val -= val * diff; 233 val -= val * factor;
256 234
257 // 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
258 // then the range is adjusted randomly around the correct value 236 // then the range is adjusted randomly around the correct value
259 if (approximate) 237 if (approximate)
260 approx_range = sint64 (val / sqrt (lev_identify * 3 + 1)); 238 approx_range = val / sqrt (lev_identify * 3 + 1);
261 } 239 }
262 240
263 /* 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
264 * overflow of diff above. That should only happen if 242 * overflow of diff above. That should only happen if
265 * we are selling objects - in that case, the person just 243 * we are selling objects - in that case, the person just
266 * gets no money. 244 * gets no money.
267 */ 245 */
268 if ((sint64) val < 0) 246 if ((sint64) val < 0)
269 val = 0; 247 val = 0;
270 248
271 /* Unidentified stuff won't sell for more than 60gp */ 249 /* Unidentified stuff won't sell for more than 10gp */
272 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)
273 { 251 min_it (val, 1000);
274 val = (val > 600) ? 600 : val;
275 }
276 252
277 /* 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 */
278 if (shop && who) 254 if (shop && who)
279 { 255 {
280 if (flag == F_SELL) 256 if (flag == F_SELL)
281 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);
282 else if (flag == F_BUY) 258 else if (flag == F_BUY)
283 { 259 {
284 /* 260 /*
285 * 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
286 * let the item be sold cheaper, according to the specialisation of 262 * let the item be sold cheaper, according to the specialisation of
292 * 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).
293 * 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
294 * 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
295 * antiques in a junk shop in real life). 271 * antiques in a junk shop in real life).
296 */ 272 */
297 if (QUERY_FLAG (tmp, FLAG_PLAYER_SOLD)) 273 if (tmp->flag [FLAG_PLAYER_SOLD])
298 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);
299 else 275 else
300 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);
301 } 279 }
302 280
303 /* 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
304 * 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
305 * pointful, and could give fun with rounding. 283 * pointful, and could give fun with rounding.
306 */ 284 */
307 //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
308 if (val > 50) 286 if (val > 50)
309 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);
310 } 288 }
311 289
312 return (sint64) val; 290 return val;
313} 291}
314 292
315/* 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
316 * cointype placement. 294 * cointype placement.
317 */ 295 */
321{ 299{
322 archetype *coin; 300 archetype *coin;
323 301
324 do 302 do
325 { 303 {
326 if (coins[*cointype] == NULL) 304 if (!coins [*cointype])
327 return NULL; 305 return 0;
306
328 coin = archetype::find (coins[*cointype]); 307 coin = archetype::find (coins [*cointype]);
308
329 if (coin == NULL) 309 if (!coin)
330 return NULL; 310 return 0;
311
331 *cointype += 1; 312 *cointype += 1;
332 } 313 }
333 while (coin->value > c); 314 while (coin->value > c);
334 315
335 return coin; 316 return coin;
346 * 10,000 silver or something) 327 * 10,000 silver or something)
347 */ 328 */
348const char * 329const char *
349cost_string_from_value (sint64 cost, int approx) 330cost_string_from_value (sint64 cost, int approx)
350{ 331{
351 static char buf[MAX_BUF];
352 archetype *coin, *next_coin; 332 archetype *coin, *next_coin;
353 int num, cointype = 0; 333 int num, cointype = 0;
354 334
355 coin = find_next_coin (cost, &cointype); 335 coin = find_next_coin (cost, &cointype);
356 if (coin == NULL) 336 if (!coin)
357 return "nothing"; 337 return "nothing";
358 338
359 num = cost / coin->value; 339 num = cost / coin->value;
360 /* so long as nrof is 32 bit, this is true. 340 /* so long as nrof is 32 bit, this is true.
361 * 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
362 * is basically true. 342 * is basically true.
363 */ 343 */
364 if ((cost / coin->value) > UINT32_MAX) 344 if (cost / coin->value > UINT32_MAX)
365 {
366 strcpy (buf, "an unimaginable sum of money"); 345 return "an unimaginable sum of money";
367 return buf;
368 }
369 346
370 cost -= num * (sint64)coin->value; 347 cost -= num * (sint64)coin->value;
371 348
372 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);
373 350
374 next_coin = find_next_coin (cost, &cointype); 351 next_coin = find_next_coin (cost, &cointype);
375 if (next_coin == NULL || approx) 352 if (!next_coin || approx)
376 return buf; 353 return buf;
377 354
378 coin = next_coin; 355 coin = next_coin;
379 num = cost / coin->value; 356 num = cost / coin->value;
380 cost -= num * (sint64)coin->value; 357 cost -= num * (sint64)coin->value;
381 358
382 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);
383
384 return buf;
385} 360}
386 361
387const char * 362const char *
388query_cost_string (const object *tmp, object *who, int flag) 363query_cost_string (const object *tmp, object *who, int flag)
389{ 364{
408 { 383 {
409 if (!idskill1 || !find_skill_by_number (who, idskill1)) 384 if (!idskill1 || !find_skill_by_number (who, idskill1))
410 { 385 {
411 if (!idskill2 || !find_skill_by_number (who, idskill2)) 386 if (!idskill2 || !find_skill_by_number (who, idskill2))
412 { 387 {
413 if (!find_skill_by_number (who, SK_BARGAINING)) 388 if (!find_skill_by_name (who, shstr_bargaining))
414 { 389 {
415 static char buf[MAX_BUF];
416 int num, cointype = 0; 390 int num, cointype = 0;
417 archetype *coin = find_next_coin (real_value, &cointype); 391 archetype *coin = find_next_coin (real_value, &cointype);
418 392
419 if (coin == NULL) 393 if (!coin)
420 return "nothing"; 394 return "nothing";
421 395
422 num = real_value / coin->value; 396 num = real_value / coin->value;
397
423 if (num == 1) 398 if (num == 1)
424 sprintf (buf, "about one %s", &coin->object::name); 399 return format ("about one %s", &coin->object::name);
425 else if (num < 5) 400 else if (num < 5)
426 sprintf (buf, "a few %s", &coin->object::name_pl); 401 return format ("a few %s", &coin->object::name_pl);
427 else if (num < 10) 402 else if (num < 10)
428 sprintf (buf, "several %s", &coin->object::name_pl); 403 return format ("several %s", &coin->object::name_pl);
429 else if (num < 25) 404 else if (num < 25)
430 sprintf (buf, "a moderate amount of %s", &coin->object::name_pl); 405 return format ("a moderate amount of %s", &coin->object::name_pl);
431 else if (num < 100) 406 else if (num < 100)
432 sprintf (buf, "lots of %s", &coin->object::name_pl); 407 return format ("lots of %s", &coin->object::name_pl);
433 else if (num < 1000) 408 else if (num < 1000)
434 sprintf (buf, "a great many %s", &coin->object::name_pl); 409 return format ("a great many %s", &coin->object::name_pl);
435 else 410 else
436 sprintf (buf, "a vast quantity of %s", &coin->object::name_pl); 411 return format ("a vast quantity of %s", &coin->object::name_pl);
437 return buf;
438 } 412 }
439 } 413 }
440 } 414 }
441 415
442 int hash = ((unsigned int) tmp->count * 174364621) & 1023;
443
444 if (approx_range) 416 if (approx_range)
445 { 417 {
418 int hash = tmp->random_seed () & 1023;
446 sint64 lo = (sint64) real_value - (approx_range * hash >> 10); 419 sint64 lo = real_value - (approx_range * hash >> 10);
447 static char buf[MAX_BUF];
448 420
449 sprintf (buf, "between %s", cost_string_from_value (lo, 1)); 421 return format ("between %s and %s",
450 sprintf (buf + strlen (buf), " and %s", cost_string_from_value (lo + approx_range, 1)); 422 cost_string_from_value (lo, 1),
451 423 cost_string_from_value (lo + approx_range, 1));
452 return buf;
453 } 424 }
454 } 425 }
455 426
456 return cost_string_from_value (real_value, 0); 427 return cost_string_from_value (real_value, 0);
457} 428}
472 } 443 }
473 444
474 for (tmp = op->inv; tmp; tmp = tmp->below) 445 for (tmp = op->inv; tmp; tmp = tmp->below)
475 if (tmp->type == MONEY) 446 if (tmp->type == MONEY)
476 total += tmp->nrof * (sint64)tmp->value; 447 total += tmp->nrof * (sint64)tmp->value;
477 else if (tmp->type == CONTAINER && QUERY_FLAG (tmp, FLAG_APPLIED) && (tmp->race == NULL || strstr (tmp->race, "gold"))) 448 else if (tmp->type == CONTAINER && tmp->flag [FLAG_APPLIED] && (!tmp->race || tmp->race.contains (shstr_gold)))
478 total += query_money (tmp); 449 total += query_money (tmp);
479 450
480 return total; 451 return total;
481} 452}
482 453
497 return 0; 468 return 0;
498 469
499 pay_from_container (pl, pl, to_pay); 470 pay_from_container (pl, pl, to_pay);
500 471
501 for (pouch = pl->inv; pouch && to_pay; pouch = pouch->below) 472 for (pouch = pl->inv; pouch && to_pay; pouch = pouch->below)
502 if (pouch->type == CONTAINER && QUERY_FLAG (pouch, FLAG_APPLIED) && (pouch->race == NULL || strstr (pouch->race, "gold"))) 473 if (pouch->type == CONTAINER && pouch->flag [FLAG_APPLIED] && (!pouch->race || pouch->race.contains (shstr_gold)))
503 pay_from_container (pl, pouch, to_pay); 474 pay_from_container (pl, pouch, to_pay);
504 475
505 pl->update_stats (); 476 pl->update_stats ();
506 return 1; 477 return 1;
507} 478}
529 * This determins the amount of exp (if any) gained for bargaining. 500 * This determins the amount of exp (if any) gained for bargaining.
530 */ 501 */
531 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;
532 503
533 if (saved_money > 0) 504 if (saved_money > 0)
534 change_exp (pl, saved_money, "bargaining", SK_EXP_NONE); 505 change_exp (pl, saved_money, shstr_bargaining, SK_EXP_NONE);
535 506
536 pay_from_container (pl, pl, to_pay); 507 pay_from_container (pl, pl, to_pay);
537 508
538 for (pouch = pl->inv; pouch && to_pay; pouch = pouch->below) 509 for (pouch = pl->inv; pouch && to_pay; pouch = pouch->below)
539 if (pouch->type == CONTAINER && QUERY_FLAG (pouch, FLAG_APPLIED) && (pouch->race == NULL || strstr (pouch->race, "gold"))) 510 if (pouch->type == CONTAINER && pouch->flag [FLAG_APPLIED] && (!pouch->race || pouch->race.contains (shstr_gold)))
540 pay_from_container (pl, pouch, to_pay); 511 pay_from_container (pl, pouch, to_pay);
541 512
542 pl->update_stats (); 513 pl->update_stats ();
543 514
544 return 1; 515 return 1;
583 { 554 {
584 // This should not happen, but if it does, just merge the two. 555 // This should not happen, but if it does, just merge the two.
585 if (coin_objs [i]) 556 if (coin_objs [i])
586 { 557 {
587 LOG (llevError, "%s has two money entries of (%s)\n", &pouch->name, coins[NUM_COINS - 1 - i]); 558 LOG (llevError, "%s has two money entries of (%s)\n", &pouch->name, coins[NUM_COINS - 1 - i]);
588 tmp->remove ();
589 coin_objs[i]->nrof += tmp->nrof; 559 coin_objs[i]->nrof += tmp->nrof;
590 esrv_del_item (pl->contr, tmp->count);
591 tmp->destroy (); 560 tmp->destroy ();
592 } 561 }
593 else 562 else
594 { 563 {
595 tmp->remove (); 564 tmp->remove ();
596
597 if (pouch->type == PLAYER)
598 esrv_del_item (pl->contr, tmp->count);
599
600 coin_objs[i] = tmp; 565 coin_objs[i] = tmp;
601 } 566 }
602 567
603 break; 568 break;
604 } 569 }
617 at = archetype::find (coins[NUM_COINS - 1 - i]); 582 at = archetype::find (coins[NUM_COINS - 1 - i]);
618 583
619 if (at == NULL) 584 if (at == NULL)
620 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]);
621 586
622 coin_objs[i] = arch_to_object (at); 587 coin_objs[i] = at->instance ();
623 coin_objs[i]->nrof = 0; 588 coin_objs[i]->nrof = 0;
624 } 589 }
625 590
626 for (i = 0; i < NUM_COINS; i++) 591 for (i = 0; i < NUM_COINS; i++)
627 { 592 {
628 object &coin = *coin_objs[i]; 593 object &coin = *coin_objs[i];
629 sint64 num_coins = min ((to_pay + coin.value - 1) / coin.value, coin.nrof); 594 sint64 num_coins = min ((to_pay + coin.value - 1) / coin.value, (sint64) coin.nrof);
630 to_pay -= num_coins * coin.value; 595 to_pay -= num_coins * coin.value;
631 596
632 coin.nrof -= num_coins; 597 coin.nrof -= num_coins;
633 /* Now start making change. Start at the coin value 598 /* Now start making change. Start at the coin value
634 * below the one we just did, and work down to 599 * below the one we just did, and work down to
644 count--; 609 count--;
645 } 610 }
646 } 611 }
647 612
648 for (i = 0; i < NUM_COINS; i++) 613 for (i = 0; i < NUM_COINS; i++)
649 {
650 if (coin_objs[i]->nrof) 614 if (coin_objs[i]->nrof)
651 {
652 object *tmp = insert_ob_in_ob (coin_objs[i], pouch); 615 insert_ob_in_ob (coin_objs [i], pouch);
653
654 esrv_send_item (pl, tmp);
655 esrv_send_item (pl, pouch);
656
657 if (pl != pouch)
658 esrv_update_item (UPD_WEIGHT, pl, pouch);
659
660 if (pl->type != PLAYER)
661 esrv_send_item (pl, pl);
662 }
663 else 616 else
664 coin_objs[i]->destroy (); 617 coin_objs[i]->destroy ();
665 }
666} 618}
667 619
668/* Checks all unpaid items in op's inventory, adds up all the money they 620/* Checks all unpaid items in op's inventory, adds up all the money they
669 * have, and checks that they can actually afford what they want to buy. 621 * have, and checks that they can actually afford what they want to buy.
670 * Returns 1 if they can, and 0 if they can't. also prints an appropriate message 622 * Returns 1 if they can, and 0 if they can't. also prints an appropriate message
682 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");
683 return 0; 635 return 0;
684 } 636 }
685 637
686 for (object::depth_iterator item = pl->begin (); item != pl->end (); ++item) 638 for (object::depth_iterator item = pl->begin (); item != pl->end (); ++item)
687 if (QUERY_FLAG (item, FLAG_UNPAID)) 639 if (item->flag [FLAG_UNPAID])
688 { 640 {
689 unpaid_count++; 641 unpaid_count++;
690 unpaid_price += query_cost (item, pl, F_BUY | F_SHOP); 642 unpaid_price += query_cost (item, pl, F_BUY | F_SHOP);
691 } 643 }
692 644
693 if (unpaid_price > player_wealth) 645 if (unpaid_price > player_wealth)
694 { 646 {
695 char buf[MAX_BUF]; 647 dynbuf_text &buf = msg_dynbuf; buf.clear ();
696 char cost[MAX_BUF];
697 char missing[MAX_BUF];
698 648
699 snprintf (cost, MAX_BUF, "%s", cost_string_from_value (unpaid_price, 0)); 649 buf << "You have " << unpaid_count
700 snprintf (missing, MAX_BUF, "%s", cost_string_from_value (unpaid_price - player_wealth, 0)); 650 << " unpaid item(s) that would cost you " << cost_string_from_value (unpaid_price, 0)
651 << ". You need another " << cost_string_from_value (unpaid_price - player_wealth, 0)
652 << " to be able to afford that. "
653 "H<You cannot leave a shop without paying - drop unpaid items first to be able to leave.>";
701 654
702 snprintf (buf, MAX_BUF, "You have %d unpaid items that would cost you %s. You need another %s to be able to afford that.", 655 pl->failmsg (buf);
703 unpaid_count, cost, missing);
704 new_draw_info (NDI_UNIQUE, 0, pl, buf);
705 656
706 return 0; 657 return 0;
707 } 658 }
708 else 659 else
709 return 1; 660 return 1;
722 { 673 {
723 next_item: 674 next_item:
724 675
725 for (object::depth_iterator op = pl->begin (); op != pl->end (); ++op) 676 for (object::depth_iterator op = pl->begin (); op != pl->end (); ++op)
726 { 677 {
727 if (QUERY_FLAG (op, FLAG_UNPAID)) 678 if (op->flag [FLAG_UNPAID])
728 { 679 {
729 char buf[MAX_BUF];
730 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);
731 681
732 if (!pay_for_item (op, pl)) 682 if (!pay_for_item (op, pl))
733 { 683 {
734 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);
735 685
736 CLEAR_FLAG (op, FLAG_UNPAID); 686 op->clr_flag (FLAG_UNPAID);
737 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));
738 SET_FLAG (op, FLAG_UNPAID); 688 op->set_flag (FLAG_UNPAID);
739 return 0; 689 return 0;
740 } 690 }
741 else 691 else
742 { 692 {
743 object *tmp; 693 op->clr_flag (FLAG_UNPAID);
744 694 op->clr_flag (FLAG_PLAYER_SOLD);
745 CLEAR_FLAG (op, FLAG_UNPAID);
746 CLEAR_FLAG (op, FLAG_PLAYER_SOLD);
747 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));
748 tmp = merge_ob (op, NULL);
749 696
750 if (pl->type == PLAYER) 697 if (!merge_ob (op, op->env->inv))
751 {
752 if (tmp)
753 { /* it was merged */
754 esrv_del_item (pl->contr, op->count);
755 op = tmp;
756 }
757
758 esrv_send_item (pl, op); 698 esrv_update_item (UPD_FLAGS, pl, op);
759 }
760 699
761 goto next_item; 700 goto next_item;
762 } 701 }
763 } 702 }
764 } 703 }
781void 720void
782pay_player (object *pl, sint64 amount) 721pay_player (object *pl, sint64 amount)
783{ 722{
784 int count = 0; 723 int count = 0;
785 archetype *at = 0; 724 archetype *at = 0;
786 object *pouch = 0, *tmp = 0; 725 object *pouch = 0;
787 726
788 for (count = 0; coins[count]; count++) 727 for (count = 0; coins[count]; count++)
789 { 728 {
790 at = archetype::find (coins[count]); 729 at = archetype::find (coins[count]);
791 730
793 LOG (llevError, "Could not find %s archetype\n", coins[count]); 732 LOG (llevError, "Could not find %s archetype\n", coins[count]);
794 else if ((amount / at->value) > 0) 733 else if ((amount / at->value) > 0)
795 { 734 {
796 for (pouch = pl->inv; pouch; pouch = pouch->below) 735 for (pouch = pl->inv; pouch; pouch = pouch->below)
797 { 736 {
798 if (pouch->type == CONTAINER && QUERY_FLAG (pouch, FLAG_APPLIED) && pouch->race && strstr (pouch->race, "gold")) 737 if (pouch->type == CONTAINER && pouch->flag [FLAG_APPLIED] && pouch->race.contains (shstr_gold))
799 { 738 {
800 int w = at->weight * (100 - pouch->stats.Str) / 100; 739 int w = at->weight * (100 - pouch->stats.Str) / 100;
801 int n = amount / at->value; 740 int n = amount / at->value;
802 741
803 if (w == 0) 742 if (w == 0)
806 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))
807 { 746 {
808 if (pouch->weight_limit && (pouch->weight_limit - pouch->carrying) / w < n) 747 if (pouch->weight_limit && (pouch->weight_limit - pouch->carrying) / w < n)
809 n = (pouch->weight_limit - pouch->carrying) / w; 748 n = (pouch->weight_limit - pouch->carrying) / w;
810 749
811 tmp = arch_to_object (at); 750 object *tmp = at->instance ();
812 tmp->nrof = n; 751 tmp->nrof = n;
813 amount -= tmp->nrof * tmp->value; 752 amount -= tmp->nrof * tmp->value;
814 tmp = insert_ob_in_ob (tmp, pouch); 753 pouch->insert (tmp);
815 esrv_send_item (pl, tmp);
816 esrv_send_item (pl, pouch);
817 esrv_update_item (UPD_WEIGHT, pl, pouch);
818 esrv_send_item (pl, pl);
819 } 754 }
820 } 755 }
821 } 756 }
822 757
823 if (amount / at->value > 0) 758 if (amount / at->value > 0)
824 { 759 {
825 tmp = arch_to_object (at); 760 object *tmp = at->instance ();
826 tmp->nrof = amount / tmp->value; 761 tmp->nrof = amount / tmp->value;
827 amount -= tmp->nrof * tmp->value; 762 amount -= tmp->nrof * tmp->value;
828 tmp = insert_ob_in_ob (tmp, pl); 763 pl->insert (tmp);
829 esrv_send_item (pl, tmp);
830 esrv_send_item (pl, pl);
831 } 764 }
832 } 765 }
833 } 766 }
834 767
835 if (amount != 0) 768 if (amount != 0)
838 771
839/* elmex: this is for the bank plugin :( */ 772/* elmex: this is for the bank plugin :( */
840sint64 773sint64
841pay_player_arch (object *pl, const char *arch, sint64 amount) 774pay_player_arch (object *pl, const char *arch, sint64 amount)
842{ 775{
843 archetype *at = archetype::find (arch);
844 object *tmp = NULL;
845
846 if (at == NULL)
847 return 0;
848
849 if (amount > 0) 776 if (amount)
850 { 777 {
851 tmp = arch_to_object (at); 778 object *ob = archetype::get (arch);
779
780 if (!ob)
781 return 0;
782
852 tmp->nrof = amount; 783 ob->nrof = amount;
853 tmp = insert_ob_in_ob (tmp, pl); 784 pl->insert (ob);
854 esrv_send_item (pl, tmp);
855 esrv_send_item (pl, pl);
856 } 785 }
857 786
858 return 1; 787 return 1;
859} 788}
860 789
863 * buy item. 792 * buy item.
864 * 793 *
865 * Modified to fill available race: gold containers before dumping 794 * Modified to fill available race: gold containers before dumping
866 * remaining coins in character's inventory. 795 * remaining coins in character's inventory.
867 */ 796 */
868void 797bool
869sell_item (object *op, object *pl) 798sell_item (object *op, object *pl)
870{ 799{
871 sint64 amount = query_cost (op, pl, F_SELL | F_SHOP), extra_gain; 800 sint64 amount = query_cost (op, pl, F_SELL | F_SHOP), extra_gain;
872 801
873 if (pl == NULL || pl->type != PLAYER) 802 if (pl == NULL || pl->type != PLAYER)
874 { 803 {
875 LOG (llevDebug, "Object other than player tried to sell something.\n"); 804 LOG (llevDebug, "Object other than player tried to sell something.\n");
876 return; 805 return false;
877 } 806 }
878 807
879 op->custom_name = 0; 808 op->custom_name = 0;
880 809
881 if (!amount) 810 if (!amount)
882 { 811 {
883 new_draw_info_format (NDI_UNIQUE, 0, pl, "We're not interested in %s.", query_name (op)); 812 new_draw_info_format (NDI_UNIQUE, 0, pl, "We're not interested in %s.",
884 813 query_name (op));
885 /* Even if the character doesn't get anything for it, it may still be 814 // elmex: change: the player now gets the item back if the shop is not
886 * worth something. If so, make it unpaid 815 // interested in it.
887 */
888 if (op->value)
889 {
890 SET_FLAG (op, FLAG_UNPAID);
891 SET_FLAG (op, FLAG_PLAYER_SOLD);
892 }
893
894 identify (op);
895 return; 816 return false;
896 } 817 }
897 818
898 /* We compare the price with the one for a player 819 /* We compare the price with the one for a player
899 * without bargaining skill. 820 * without bargaining skill.
900 * This determins the amount of exp (if any) gained for bargaining. 821 * This determins the amount of exp (if any) gained for bargaining.
901 * exp/10 -> 1 for each gold coin 822 * exp/10 -> 1 for each gold coin
902 */ 823 */
903 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);
904 825
905 if (extra_gain > 0) 826 if (extra_gain > 0)
906 change_exp (pl, extra_gain / 10, "bargaining", SK_EXP_NONE); 827 change_exp (pl, extra_gain / 10, shstr_bargaining, SK_EXP_NONE);
907 828
908 pay_player (pl, amount); 829 pay_player (pl, amount);
909 830
910 new_draw_info_format (NDI_UNIQUE, 0, pl, "You receive %s for %s.", query_cost_string (op, pl, F_SELL | F_SHOP), query_name (op)); 831 new_draw_info_format (NDI_UNIQUE, 0, pl, "You receive %s for %s.",
832 query_cost_string (op, pl, F_SELL | F_SHOP), query_name (op));
911 pl->play_sound (sound_find ("shop_sell")); 833 pl->play_sound (sound_find ("shop_sell"));
912 834
913 SET_FLAG (op, FLAG_UNPAID); 835 op->set_flag (FLAG_UNPAID);
914 identify (op); 836 identify (op);
837
838 return true;
915} 839}
916 840
917/* returns a double that is the ratio of the price that a shop will offer for 841/* returns a double that is the ratio of the price that a shop will offer for
918 * item based on the shops specialisation. Does not take account of greed, 842 * item based on the shops specialisation. Does not take account of greed,
919 * returned value is between SPECIALISATION_EFFECT and 1. 843 * returned value is between SPECIALISATION_EFFECT and 1.
920 */ 844 */
921static double 845static double
922shop_specialisation_ratio (const object *item, const maptile *map) 846shop_specialisation_ratio (const object *item, const maptile *map)
923{ 847{
924 shopitems *items = map->shopitems; 848 shopitems *items = map->shopitems;
925 double likedness = 0.; 849 int likedness = 0;
926 int i; 850 int i;
927 851
928 if (item == NULL) 852 if (item == NULL)
929 { 853 {
930 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);
931 return 0; 855 return 0;
932 } 856 }
933 857
934 if (!item->type) 858 if (!item->type)
935 { 859 {
936 LOG (llevError, "shop_specialisation_ratio: passed an item with an invalid type\n"); 860 LOG (llevError, "shop_specialisation_ratio: passed an item with an invalid type: %s\n", item->debug_desc ());
937 /* 861 /*
938 * I'm not really sure what the /right/ thing to do here is, these types of 862 * I'm not really sure what the /right/ thing to do here is, these types of
939 * item shouldn't exist anyway, but returning the ratio is probably the best bet.." 863 * item shouldn't exist anyway, but returning the ratio is probably the best bet.."
940 */ 864 */
941 return SPECIALISATION_EFFECT; 865 return SPECIALISATION_EFFECT;
942 } 866 }
943 867
944 if (map->shopitems) 868 if (map->shopitems)
945 {
946 for (i = 0; i < items[0].index; i++) 869 for (i = 0; i < items[0].index; i++)
947 if (items[i].typenum == item->type || (!items[i].typenum && likedness == 0.001)) 870 if (items[i].typenum == item->type || (!items[i].typenum && !likedness))
948 likedness = items[i].strength / 100.0; 871 likedness = items[i].strength;
949 }
950 872
951 if (likedness > 1.0) 873 if (likedness > 100)
952 { /* someone has been rather silly with the map headers. */ 874 { /* someone has been rather silly with the map headers. */
953 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 %s on map %s is above 100%%\n", item->debug_desc (), &map->path);
954 likedness = 1.0; 876 likedness = 100;
955 } 877 }
956 878
957 if (likedness < -1.0) 879 if (likedness < -100)
958 { 880 {
959 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 %s on map %s is below -100%%\n", item->debug_desc (), &map->path);
960 likedness = -1.0; 882 likedness = -100;
961 } 883 }
962 884
963 return lerp (likedness, -1., 1., SPECIALISATION_EFFECT, 1.); 885 return lerp (double (likedness), -100., 100., SPECIALISATION_EFFECT, 1.);
964} 886}
965 887
966/*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. */
967static double 889static double
968shop_greed (const maptile *map) 890shop_greed (const maptile *map)
986/* limit the value of items based on the wealth of the shop. If the item is close 908/* limit the value of items based on the wealth of the shop. If the item is close
987 * to the maximum value a shop will offer, we start to reduce it, if the item is 909 * to the maximum value a shop will offer, we start to reduce it, if the item is
988 * below the minimum value the shop is prepared to trade in, then we don't 910 * below the minimum value the shop is prepared to trade in, then we don't
989 * want it and offer nothing. If it isn't a shop, check whether we should do generic 911 * want it and offer nothing. If it isn't a shop, check whether we should do generic
990 * value reduction. 912 * value reduction.
991 * 913 *
992 */ 914 */
993static sint64 915static sint64
994value_limit (sint64 val, int quantity, const object *who, int isshop) 916value_limit (sint64 val, int quantity, const object *who, int isshop)
995{ 917{
996 sint64 newval, unit_price, tmpshopmax; 918 sint64 newval, unit_price, tmpshopmax;
1018 tmpshopmax = map->shopmax ? map->shopmax : 100000; // 20 royalties default 940 tmpshopmax = map->shopmax ? map->shopmax : 100000; // 20 royalties default
1019 941
1020 if (map->shopmin && unit_price < map->shopmin) 942 if (map->shopmin && unit_price < map->shopmin)
1021 return 0; 943 return 0;
1022 else if (unit_price > tmpshopmax / 2) 944 else if (unit_price > tmpshopmax / 2)
1023 newval = MIN ((tmpshopmax / 2) + isqrt (unit_price - tmpshopmax / 2), tmpshopmax); 945 newval = min ((tmpshopmax / 2) + isqrt (unit_price - tmpshopmax / 2), tmpshopmax);
1024 else 946 else
1025 newval = unit_price; 947 newval = unit_price;
1026 } 948 }
1027 949
1028 newval *= quantity; 950 newval *= quantity;
1032 954
1033/* 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. */
1034int 956int
1035describe_shop (const object *op) 957describe_shop (const object *op)
1036{ 958{
959 dynbuf_text buf;
1037 maptile *map = op->map; 960 maptile *map = op->map;
1038 961
1039 /*shopitems *items=map->shopitems; */ 962 /*shopitems *items=map->shopitems; */
1040 int pos = 0, i; 963 int i;
1041 double opinion = 0; 964 double opinion = 0;
1042 char tmp[MAX_BUF] = "\0";
1043 965
1044 if (op->type != PLAYER) 966 if (op->type != PLAYER)
1045 return 0; 967 return 0;
1046 968
1047 /*check if there is a shop specified for this map */ 969 /*check if there is a shop specified for this map */
1048 if (map->shopitems || map->shopgreed || map->shoprace || map->shopmin || map->shopmax) 970 if (map->shopitems || map->shopgreed || map->shoprace || map->shopmin || map->shopmax)
1049 { 971 {
1050 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;
1051 974
1052 if (map->shopitems) 975 if (map->shopitems)
1053 for (i = 0; i < map->shopitems[0].index; i++) 976 for (i = 0; i < map->shopitems[0].index; i++)
1054 if (map->shopitems[i].name && map->shopitems[i].strength > 10) 977 if (map->shopitems[i].name && map->shopitems[i].strength > 10)
1055 { 978 {
1056 snprintf (tmp + pos, sizeof (tmp) - pos, "%s, ", map->shopitems[i].name_pl); 979 buf << map->shopitems[i].name_pl;
1057 pos += strlen (tmp + pos); 980 prevcomma = lastcomma;
981 lastcomma = buf.size (); // remember offset
982 buf << ", ";
1058 } 983 }
1059 984
1060 if (!pos) 985 if (lastcomma)
986 {
987 buf.splice (lastcomma, 2);
988
989 if (prevcomma)
990 buf.splice (prevcomma, 2, " and ");
991 }
992 else
1061 strcat (tmp, "a little of everything."); 993 buf << "a little of everything.";
1062 994
1063 /* format the string into a list */ 995 buf << ".\n\n";
1064 make_list_like (tmp);
1065 new_draw_info_format (NDI_UNIQUE, 0, op, "%s", tmp);
1066 996
1067 if (map->shopmax) 997 if (map->shopmax)
1068 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";
1069 999
1070 if (map->shopmin) 1000 if (map->shopmin)
1071 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";
1072 1002
1073 if (map->shopgreed) 1003 if (map->shopgreed)
1074 { 1004 {
1075 if (map->shopgreed > 2.0) 1005 if (map->shopgreed > 2.0)
1076 new_draw_info (NDI_UNIQUE, 0, op, "It tends to overcharge massively."); 1006 buf << "It tends to overcharge massively.\n\n";
1077 else if (map->shopgreed > 1.5) 1007 else if (map->shopgreed > 1.5)
1078 new_draw_info (NDI_UNIQUE, 0, op, "It tends to overcharge substantially."); 1008 buf << "It tends to overcharge substantially.\n\n";
1079 else if (map->shopgreed > 1.1) 1009 else if (map->shopgreed > 1.1)
1080 new_draw_info (NDI_UNIQUE, 0, op, "It tends to overcharge slightly."); 1010 buf << "It tends to overcharge slightly.\n\n";
1081 else if (map->shopgreed < 0.9) 1011 else if (map->shopgreed < 0.9)
1082 new_draw_info (NDI_UNIQUE, 0, op, "It tends to undercharge."); 1012 buf << "It tends to undercharge.\n\n";
1083 } 1013 }
1084 1014
1085 if (map->shoprace) 1015 if (map->shoprace)
1086 { 1016 {
1087 opinion = shopkeeper_approval (map, op); 1017 opinion = shopkeeper_approval (map, op);
1018
1088 if (opinion > 0.8) 1019 if (opinion > 0.8)
1089 new_draw_info (NDI_UNIQUE, 0, op, "You think the shopkeeper likes you."); 1020 buf << "You think the shopkeeper likes you.\n\n";
1090 else if (opinion > 0.5) 1021 else if (opinion > 0.5)
1091 new_draw_info (NDI_UNIQUE, 0, op, "The shopkeeper seems unconcerned by you."); 1022 buf << "The shopkeeper seems unconcerned by you.\n\n";
1092 else 1023 else
1093 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";
1094 } 1025 }
1095 } 1026 }
1096 else 1027 else
1097 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);
1098 1031
1099 return 1; 1032 return 1;
1100} 1033}
1101 1034
1102struct shopinv 1035struct shopinv
1103{ 1036{
1104 char *item_sort; 1037 char *item_sort;
1105 char *item_real; 1038 char *item_real;
1039 sint64 value;
1106 uint16 type; 1040 uint16 type;
1107 uint32 nrof; 1041 uint32 nrof;
1108}; 1042};
1109 1043
1110/* There are a lot fo extra casts in here just to suppress warnings - it 1044/* There are a lot fo extra casts in here just to suppress warnings - it
1117{ 1051{
1118 shopinv *s1 = (shopinv *) a1, *s2 = (shopinv *) a2; 1052 shopinv *s1 = (shopinv *) a1, *s2 = (shopinv *) a2;
1119 1053
1120 if (s1->type < s2->type) 1054 if (s1->type < s2->type)
1121 return -1; 1055 return -1;
1056
1122 if (s1->type > s2->type) 1057 if (s1->type > s2->type)
1123 return 1; 1058 return 1;
1124 1059
1125 /* the type is the same (what atoi gets), so do a strcasecmp to sort 1060 /* the type is the same (what atoi gets), so do a strcasecmp to sort
1126 * via alphabetical order 1061 * via alphabetical order
1129} 1064}
1130 1065
1131static void 1066static void
1132add_shop_item (object *tmp, shopinv * items, int *numitems, int *numallocated) 1067add_shop_item (object *tmp, shopinv * items, int *numitems, int *numallocated)
1133{ 1068{
1134#if 0
1135 char buf[MAX_BUF];
1136#endif
1137 /* clear unpaid flag so that doesn't come up in query 1069 /* clear unpaid flag so that doesn't come up in query
1138 * string. We clear nrof so that we can better sort 1070 * string. We clear nrof so that we can better sort
1139 * the object names. 1071 * the object names.
1140 */ 1072 */
1141 1073
1142 CLEAR_FLAG (tmp, FLAG_UNPAID); 1074 tmp->clr_flag (FLAG_UNPAID);
1143 items[*numitems].nrof = tmp->nrof; 1075 items[*numitems].nrof = tmp->nrof;
1144 /* Non mergable items have nrof of 0, but count them as one 1076 /* Non mergable items have nrof of 0, but count them as one
1145 * so the display is properly. 1077 * so the display is properly.
1146 */ 1078 */
1147 if (tmp->nrof == 0) 1079 if (tmp->nrof == 0)
1148 items[*numitems].nrof++; 1080 items[*numitems].nrof++;
1149 items[*numitems].type = tmp->type; 1081 items[*numitems].type = tmp->type;
1082
1083 items[*numitems].value = tmp->value;
1150 1084
1151 switch (tmp->type) 1085 switch (tmp->type)
1152 { 1086 {
1153#if 0 1087#if 0
1154 case BOOTS: 1088 case BOOTS:
1166#endif 1100#endif
1167 1101
1168 default: 1102 default:
1169 items[*numitems].item_sort = strdup (query_base_name (tmp, 0)); 1103 items[*numitems].item_sort = strdup (query_base_name (tmp, 0));
1170 items[*numitems].item_real = strdup (query_base_name (tmp, 1)); 1104 items[*numitems].item_real = strdup (query_base_name (tmp, 1));
1105 items[*numitems].value += tmp->value;
1171 (*numitems)++; 1106 (*numitems)++;
1172 break; 1107 break;
1173 } 1108 }
1174 SET_FLAG (tmp, FLAG_UNPAID); 1109
1110 tmp->set_flag (FLAG_UNPAID);
1175} 1111}
1176 1112
1177void 1113void
1178shop_listing (object *sign, object *op) 1114shop_listing (object *sign, object *op)
1179{ 1115{
1180 int i, j, numitems = 0, numallocated = 0, x1, x2, y1, y2; 1116 int i, j, x1, x2, y1, y2;
1181 const char *shop_coords = get_ob_key_value (sign, "shop_coords"); 1117 const char *shop_coords = sign->kv [shstr_shop_coords];
1182 object *stack; 1118 object *stack;
1183 shopinv *items; 1119 shopinv *items;
1184 1120
1185 /* Should never happen, but just in case a monster does apply a sign */ 1121 /* Should never happen, but just in case a monster does apply a sign */
1186 if (op->type != PLAYER) 1122 if (!op->is_player ())
1187 return; 1123 return;
1124
1125 dynbuf_text &buf = msg_dynbuf; buf.clear ();
1188 1126
1189 if (!(shop_coords && sscanf (shop_coords, "%d,%d,%d,%d", &x1, &y1, &x2, &y2))) 1127 if (!(shop_coords && sscanf (shop_coords, "%d,%d,%d,%d", &x1, &y1, &x2, &y2)))
1190 { 1128 {
1191 x1 = 0; 1129 x1 = 0;
1192 y1 = 0; 1130 y1 = 0;
1193 x2 = op->map->width - 1; 1131 x2 = op->map->width - 1;
1194 y2 = op->map->height - 1; 1132 y2 = op->map->height - 1;
1195 } 1133 }
1196 1134
1197 items = (shopinv *) malloc (40 * sizeof (shopinv));
1198 numallocated = 40; 1135 int numallocated = 40;
1136 int numitems = 0;
1137 items = (shopinv *)malloc (sizeof (shopinv) * numallocated);
1199 1138
1200 /* Find all the appropriate items */ 1139 /* Find all the appropriate items */
1201 for (i = x1; i <= x2; i++) 1140 for (i = x1; i <= x2; i++)
1202 {
1203 for (j = y1; j < y2; j++) 1141 for (j = y1; j < y2; j++)
1142 if (op->map->is_in_shop (i, j))
1204 { 1143 {
1205 if (is_in_shop (op->map, i, j)) 1144 stack = GET_MAP_OB (op->map, i, j);
1145
1146 while (stack)
1206 { 1147 {
1207 stack = GET_MAP_OB (op->map, i, j); 1148 if (stack->flag [FLAG_UNPAID])
1208
1209 while (stack)
1210 { 1149 {
1211 if (QUERY_FLAG (stack, FLAG_UNPAID))
1212 {
1213 if (numitems == numallocated) 1150 if (numitems == numallocated)
1214 {
1215 items = (shopinv *) realloc (items, sizeof (shopinv) * (numallocated + 10)); 1151 items = (shopinv *)realloc (items, sizeof (shopinv) * (numallocated *= 2));
1216 numallocated += 10;
1217 }
1218 1152
1219 add_shop_item (stack, items, &numitems, &numallocated); 1153 add_shop_item (stack, items, &numitems, &numallocated);
1220 }
1221
1222 stack = stack->above;
1223 } 1154 }
1155
1156 stack = stack->above;
1224 } 1157 }
1225 } 1158 }
1226 }
1227 1159
1228 if (numitems == 0) 1160 buf << (numitems ? "T<This shop contains:>\n\n"
1229 { 1161 : "T<This shop is currently empty.>");
1230 new_draw_info (NDI_UNIQUE, 0, op, "The shop is currently empty.\n");
1231 free (items);
1232 return;
1233 }
1234 1162
1235 qsort (items, numitems, sizeof (shopinv), (int (*)(const void *, const void *)) shop_sort); 1163 qsort (items, numitems, sizeof (shopinv), (int (*)(const void *, const void *)) shop_sort);
1236
1237 new_draw_info (NDI_UNIQUE, 0, op, "\nThe shop contains:");
1238 1164
1239 for (i = 0; i < numitems; i++) 1165 for (i = 0; i < numitems; i++)
1240 { 1166 {
1241 /* Collapse items of the same name together */ 1167 /* Collapse items of the same name together */
1242 if ((i + 1) < numitems && !strcmp (items[i].item_real, items[i + 1].item_real)) 1168 if ((i + 1) < numitems && !strcmp (items[i].item_real, items[i + 1].item_real))
1243 {
1244 items[i + 1].nrof += items[i].nrof; 1169 items[i + 1].nrof += items[i].nrof;
1245 free (items[i].item_sort);
1246 free (items[i].item_real);
1247 }
1248 else 1170 else
1249 { 1171 {
1250 new_draw_info_format (NDI_UNIQUE, 0, op, "%d %s", 1172 buf.printf (
1251 items[i].nrof ? items[i].nrof : 1, items[i].nrof == 1 ? items[i].item_sort : items[i].item_real); 1173 " %4d %s\n for %s\n",
1174 items[i].nrof ? items[i].nrof : 1,
1175 items[i].nrof == 1 ? items[i].item_sort : items[i].item_real,
1176 cost_string_from_value (items[i].value, op->flag [FLAG_WIZ] ? 0 : 1));
1177 }
1178
1252 free (items[i].item_sort); 1179 free (items[i].item_sort);
1253 free (items[i].item_real); 1180 free (items[i].item_real);
1254 }
1255 } 1181 }
1182
1183 op->contr->infobox (MSG_CHANNEL ("shopitems"), buf);
1256 1184
1257 free (items); 1185 free (items);
1258}
1259
1260/* elmex: this function checks whether the object is in a shop */
1261bool
1262is_in_shop (object *o)
1263{
1264 if (!o->map)
1265 return false;
1266
1267 return is_in_shop (o->map, o->x, o->y);
1268} 1186}
1269 1187
1270/* elmex: this function checks whether we are in a shop or not 1188/* elmex: this function checks whether we are in a shop or not
1271 - change 2007-11-26: enhanced the O(n) case by stopping at the first 1189 - change 2007-11-26: enhanced the O(n) case by stopping at the first
1272 floor tile. this possibly will make map bugs where shopfloors are above 1190 floor tile. this possibly will make map bugs where shopfloors are above
1273 floors more obvious. 1191 floors more obvious.
1274*/ 1192*/
1275
1276bool 1193bool
1277is_in_shop (maptile *map, int x, int y) 1194maptile::is_in_shop (int x, int y) const
1278{ 1195{
1279 for (object *floor = GET_MAP_OB (map, x, y); floor; floor = floor->above) 1196 for (object *floor = at (x, y).bot; floor; floor = floor->above)
1280 if (QUERY_FLAG (floor, FLAG_IS_FLOOR)) 1197 if (floor->flag [FLAG_IS_FLOOR])
1281 return floor->type == SHOP_FLOOR; 1198 return floor->type == SHOP_FLOOR;
1199
1282 return false; 1200 return false;
1283} 1201}
1284 1202

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines