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.49 by root, Tue Apr 22 07:01:47 2008 UTC vs.
Revision 1.81 by root, Wed Apr 28 19:20:48 2010 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines