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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines