1 /**
2  * \file obj-power.c
3  * \brief calculation of object power and value
4  *
5  * Copyright (c) 2001 Chris Carr, Chris Robertson
6  * Revised in 2009-11 by Chris Carr, Peter Denison
7  *
8  * This work is free software; you can redistribute it and/or modify it
9  * under the terms of either:
10  *
11  * a) the GNU General Public License as published by the Free Software
12  *    Foundation, version 2, or
13  *
14  * b) the "Angband licence":
15  *    This software may be copied and distributed for educational, research,
16  *    and not for profit purposes provided that this copyright and statement
17  *    are included in all such copies.  Other copyrights may also apply.
18  */
19 #include "angband.h"
20 #include "obj-curse.h"
21 #include "obj-gear.h"
22 #include "obj-knowledge.h"
23 #include "obj-power.h"
24 #include "obj-slays.h"
25 #include "obj-tval.h"
26 #include "obj-util.h"
27 #include "init.h"
28 #include "effects.h"
29 #include "monster.h"
30 
31 /**
32  * ------------------------------------------------------------------------
33  * Object power data and assumptions
34  * ------------------------------------------------------------------------ */
35 
36 /**
37  * Define a set of constants for dealing with launchers and ammo:
38  * - the assumed average damage of ammo (for rating launchers)
39  * (the current values assume normal (non-seeker) ammo enchanted to +9)
40  * - the assumed bonus on launchers (for rating ego ammo)
41  * - twice the assumed multiplier (for rating any ammo)
42  * N.B. Ammo tvals are assumed to be consecutive! We access this array using
43  * (obj->tval - TV_SHOT) for ammo, and
44  * (obj->sval / 10) for launchers
45  */
46 static struct archery {
47 	int ammo_tval;
48 	int ammo_dam;
49 	int launch_dam;
50 	int launch_mult;
51 } archery[] = {
52 	{TV_SHOT, 10, 9, 4},
53 	{TV_ARROW, 12, 9, 5},
54 	{TV_BOLT, 14, 9, 7}
55 };
56 
57 /**
58  * Set the weightings of flag types:
59  * - factor for power increment for multiple flags
60  * - additional power bonus for a "full set" of these flags
61  * - number of these flags which constitute a "full set"
62  */
63 static struct flag_set {
64 	int type;
65 	int factor;
66 	int bonus;
67 	int size;
68 	int count;
69 	const char *desc;
70 } flag_sets[] = {
71 	{ OFT_SUST, 1, 10, 5, 0, "sustains" },
72 	{ OFT_PROT, 3, 15, 4, 0, "protections" },
73 	{ OFT_MISC, 1, 25, 8, 0, "misc abilities" }
74 };
75 
76 
77 enum {
78 	T_LRES,
79 	T_HRES
80 };
81 
82 /**
83  * Similar data for elements
84  */
85 static struct element_set {
86 	int type;
87 	int res_level;
88 	int factor;
89 	int bonus;
90 	int size;
91 	int count;
92 	const char *desc;
93 } element_sets[] = {
94 	{ T_LRES, 3, 6, INHIBIT_POWER, 4,    0,     "immunities" },
95 	{ T_LRES, 1, 1, 10,            4,    0,     "low resists" },
96 	{ T_HRES, 1, 2, 10,            9,    0,     "high resists" },
97 };
98 
99 /**
100  * Power data for elements
101  */
102 static struct element_powers {
103 	const char *name;
104 	int type;
105 	int ignore_power;
106 	int vuln_power;
107 	int res_power;
108 	int im_power;
109 } el_powers[] = {
110 	{ "acid",			T_LRES,	3,	-6,	5,	38 },
111 	{ "electricity",	T_LRES,	1,	-6,	6,	35 },
112 	{ "fire",			T_LRES,	3,	-6,	6,	40 },
113 	{ "cold",			T_LRES,	1,	-6,	6,	37 },
114 	{ "poison",			T_HRES,	0,	0,	28,	0 },
115 	{ "light",			T_HRES,	0,	0,	6,	0 },
116 	{ "dark",			T_HRES,	0,	0,	16,	0 },
117 	{ "sound",			T_HRES,	0,	0,	14,	0 },
118 	{ "shards",			T_HRES,	0,	0,	8,	0 },
119 	{ "nexus",			T_HRES,	0,	0,	15,	0 },
120 	{ "nether",			T_HRES,	0,	0,	20,	0 },
121 	{ "chaos",			T_HRES,	0,	0,	20,	0 },
122 	{ "disenchantment",	T_HRES,	0,	0,	20,	0 }
123 };
124 
125 /**
126  * Boost ratings for combinations of ability bonuses
127  * We go up to +24 here - anything higher is inhibited
128  * N.B. Not all stats count equally towards this total
129  */
130 static s16b ability_power[25] =
131 	{0, 0, 0, 0, 0, 0, 0, 2, 4, 6, 8,
132 	12, 16, 20, 24, 30, 36, 42, 48, 56, 64,
133 	74, 84, 96, 110};
134 
135 /* Log file declared here for simplicity */
136 static ang_file *object_log;
137 
138 /**
139  * Log progress info to the object log
140  */
log_obj(char * message)141 void log_obj(char *message)
142 {
143 	file_putf(object_log, "%s", message);
144 }
145 
146 /**
147  * ------------------------------------------------------------------------
148  * Object power calculations
149  * ------------------------------------------------------------------------ */
150 
151 /**
152  * Calculate the multiplier we'll get with a given bow type.
153  */
bow_multiplier(const struct object * obj)154 static int bow_multiplier(const struct object *obj)
155 {
156 	int mult = 1;
157 
158 	if (obj->tval != TV_BOW)
159 		return mult;
160 	else
161 		mult = obj->pval;
162 
163 	log_obj(format("Base mult for this weapon is %d\n", mult));
164 	return mult;
165 }
166 
167 /**
168  * To damage power
169  */
to_damage_power(const struct object * obj)170 static int to_damage_power(const struct object *obj)
171 {
172 	int p;
173 
174 	p = (obj->to_d * DAMAGE_POWER / 2);
175 	if (p) log_obj(format("%d power from to_dam\n", p));
176 
177 	/* Add second lot of damage power for non-weapons */
178 	if ((wield_slot(obj) != slot_by_name(player, "shooting")) &&
179 		!tval_is_melee_weapon(obj) &&
180 		!tval_is_ammo(obj)) {
181 		int q = (obj->to_d * DAMAGE_POWER);
182 		p += q;
183 		if (q)
184 			log_obj(format("Add %d from non-weapon to_dam, total %d\n", q, p));
185 	}
186 	return p;
187 }
188 
189 /**
190  * Damage dice power or equivalent
191  */
damage_dice_power(const struct object * obj)192 static int damage_dice_power(const struct object *obj)
193 {
194 	int dice = 0;
195 
196 	/* Add damage from dice for any wieldable weapon or ammo */
197 	if (tval_is_melee_weapon(obj) || tval_is_ammo(obj)) {
198 		dice = ((obj->dd * (obj->ds + 1) * DAMAGE_POWER) / 4);
199 		log_obj(format("Add %d power for damage dice, ", dice));
200 	} else if (wield_slot(obj) != slot_by_name(player, "shooting")) {
201 		/* Add power boost for nonweapons with combat flags */
202 		if (obj->brands || obj->slays ||
203 			(obj->modifiers[OBJ_MOD_BLOWS] > 0) ||
204 			(obj->modifiers[OBJ_MOD_SHOTS] > 0) ||
205 			(obj->modifiers[OBJ_MOD_MIGHT] > 0)) {
206 			dice = (WEAP_DAMAGE * DAMAGE_POWER);
207 			log_obj(format("Add %d power for non-weapon combat bonuses, ",
208 						   dice));
209 		}
210 	}
211 	return dice;
212 }
213 
214 /**
215  * Add ammo damage for launchers, get multiplier and rescale
216  */
ammo_damage_power(const struct object * obj,int p)217 static int ammo_damage_power(const struct object *obj, int p)
218 {
219 	int q = 0;
220 	int launcher = -1;
221 
222 	if (wield_slot(obj) == slot_by_name(player, "shooting")) {
223 		if (kf_has(obj->kind->kind_flags, KF_SHOOTS_SHOTS))
224 			launcher = 0;
225 		else if (kf_has(obj->kind->kind_flags, KF_SHOOTS_ARROWS))
226 			launcher = 1;
227 		else if (kf_has(obj->kind->kind_flags, KF_SHOOTS_BOLTS))
228 			launcher = 2;
229 
230 		if (launcher != -1) {
231 			q = (archery[launcher].ammo_dam * DAMAGE_POWER / 2);
232 			log_obj(format("Adding %d power from ammo, total is %d\n", q,
233 						   p + q));
234 		}
235 	}
236 	return q;
237 }
238 
239 /**
240  * Add launcher bonus for ego ammo, multiply for launcher and rescale
241  */
launcher_ammo_damage_power(const struct object * obj,int p)242 static int launcher_ammo_damage_power(const struct object *obj, int p)
243 {
244 	int ammo_type = 0;
245 
246 	if (tval_is_ammo(obj)) {
247 		if (obj->tval == TV_ARROW) ammo_type = 1;
248 		if (obj->tval == TV_BOLT) ammo_type = 2;
249 		if (obj->ego)
250 			p += (archery[ammo_type].launch_dam * DAMAGE_POWER / 2);
251 		p = p * archery[ammo_type].launch_mult / (2 * MAX_BLOWS);
252 		log_obj(format("After multiplying ammo and rescaling, power is %d\n",
253 					   p));
254 	}
255 	return p;
256 }
257 
258 /**
259  * Add power for extra blows
260  */
extra_blows_power(const struct object * obj,int p)261 static int extra_blows_power(const struct object *obj, int p)
262 {
263 	int q = p;
264 
265 	if (obj->modifiers[OBJ_MOD_BLOWS] == 0)
266 		return p;
267 
268 	if (obj->modifiers[OBJ_MOD_BLOWS] >= INHIBIT_BLOWS) {
269 		p += INHIBIT_POWER;
270 		log_obj("INHIBITING - too many extra blows - quitting\n");
271 		return p;
272 	} else {
273 		p = p * (MAX_BLOWS + obj->modifiers[OBJ_MOD_BLOWS]) / MAX_BLOWS;
274 		/* Add boost for assumed off-weapon damage */
275 		p += (NONWEAP_DAMAGE * obj->modifiers[OBJ_MOD_BLOWS]
276 			  * DAMAGE_POWER / 2);
277 		log_obj(format("Add %d power for extra blows, total is %d\n",
278 					   p - q, p));
279 	}
280 	return p;
281 }
282 
283 /**
284  * Add power for extra shots - note that we cannot handle negative shots
285  */
extra_shots_power(const struct object * obj,int p)286 static int extra_shots_power(const struct object *obj, int p)
287 {
288 	if (obj->modifiers[OBJ_MOD_SHOTS] == 0)
289 		return p;
290 
291 	if (obj->modifiers[OBJ_MOD_SHOTS] >= INHIBIT_SHOTS) {
292 		p += INHIBIT_POWER;
293 		log_obj("INHIBITING - too many extra shots - quitting\n");
294 		return p;
295 	} else if (obj->modifiers[OBJ_MOD_SHOTS] > 0) {
296 		/* Multiply by effective number of shots */
297 		int q = obj->modifiers[OBJ_MOD_SHOTS];
298 		p *= (10 + q);
299 		p /= 10;
300 		log_obj(format("Adding %d%% power for extra shots, total is %d\n",
301 					   10 * q, p));
302 	}
303 	return p;
304 }
305 
306 
307 /**
308  * Add power for extra might
309  */
extra_might_power(const struct object * obj,int p,int mult)310 static int extra_might_power(const struct object *obj, int p, int mult)
311 {
312 	if (obj->modifiers[OBJ_MOD_MIGHT] >= INHIBIT_MIGHT) {
313 		p += INHIBIT_POWER;
314 		log_obj("INHIBITING - too much extra might - quitting\n");
315 		return p;
316 	} else {
317 		mult += obj->modifiers[OBJ_MOD_MIGHT];
318 	}
319 	log_obj(format("Mult after extra might is %d\n", mult));
320 	p *= mult;
321 	log_obj(format("After multiplying power for might, total is %d\n", p));
322 	return p;
323 }
324 
325 /**
326  * Calculate the rating for a given slay combination
327  */
slay_power(const struct object * obj,int p,int verbose,int dice_pwr)328 static s32b slay_power(const struct object *obj, int p, int verbose,
329 					   int dice_pwr)
330 {
331 	int i, q, num_brands = 0, num_slays = 0, num_kills = 0;
332 	int best_power = 1;
333 
334 	/* Count the brands and slays */
335 	if (obj->brands) {
336 		for (i = 1; i < z_info->brand_max; i++) {
337 			if (obj->brands[i]) {
338 				num_brands++;
339 				if (brands[i].power > best_power)
340 					best_power = brands[i].power;
341 			}
342 		}
343 	}
344 	if (obj->slays) {
345 		for (i = 1; i < z_info->slay_max; i++) {
346 			if (obj->slays[i]) {
347 				if (slays[i].multiplier <= 3) {
348 					num_slays++;
349 				} else {
350 					num_kills++;
351 				}
352 				if (slays[i].power > best_power)
353 					best_power = slays[i].power;
354 			}
355 		}
356 	}
357 
358 	/* If there are no slays or brands return */
359 	if ((num_slays + num_brands + num_kills) == 0)
360 		return p;
361 
362 	/* Write the best power */
363 	if (verbose) {
364 		/* Write info about the slay combination and multiplier */
365 		log_obj("Slay and brands: ");
366 
367 		if (obj->brands) {
368 			for (i = 1; i < z_info->brand_max; i++) {
369 				if (obj->brands[i]) {
370 					struct brand *b = &brands[i];
371 					log_obj(format("%sx%d ", b->name, b->multiplier));
372 				}
373 			}
374 		}
375 		if (obj->slays) {
376 			for (i = 1; i < z_info->slay_max; i++) {
377 				if (obj->slays[i]) {
378 					struct slay *s = &slays[i];
379 					log_obj(format("%sx%d ", s->name, s->multiplier));
380 				}
381 			}
382 		}
383 		log_obj(format("\nbest power is : %d\n", best_power));
384 	}
385 
386 	q = (dice_pwr * dice_pwr * (best_power - 100)) / 2500;
387 	p += q;
388 	log_obj(format("Add %d for slay power, total is %d\n", q, p));
389 
390 	/* Bonuses for multiple brands and slays */
391 	if (num_slays > 1) {
392 		q = (num_slays * num_slays * dice_pwr) / (DAMAGE_POWER * 5);
393 		p += q;
394 		log_obj(format("Add %d power for multiple slays, total is %d\n", q, p));
395 	}
396 	if (num_brands > 1) {
397 		q = (2 * num_brands * num_brands * dice_pwr) / (DAMAGE_POWER * 5);
398 		p += q;
399 		log_obj(format("Add %d power for multiple brands, total is %d\n",q, p));
400 	}
401 	if (num_slays && num_brands) {
402 		q = (num_slays * num_brands * dice_pwr) / (DAMAGE_POWER * 5);
403 		p += q;
404 		log_obj(format("Add %d power for slay and brand, total is %d\n", q, p));
405 	}
406 	if (num_kills > 1) {
407 		q = (3 * num_kills * num_kills * dice_pwr) / (DAMAGE_POWER * 5);
408 		p += q;
409 		log_obj(format("Add %d power for multiple kills, total is %d\n", q, p));
410 	}
411 	if (num_slays == 8) {
412 		p += 10;
413 		log_obj(format("Add 10 power for full set of slays, total is %d\n", p));
414 	}
415 	if (num_brands == 5) {
416 		p += 20;
417 		log_obj(format("Add 20 power for full set of brands, total is %d\n",p));
418 	}
419 	if (num_kills == 3) {
420 		p += 20;
421 		log_obj(format("Add 20 power for full set of kills, total is %d\n", p));
422 	}
423 
424 	return p;
425 }
426 
427 /**
428  * Melee weapons assume MAX_BLOWS per turn, so we must divide by MAX_BLOWS
429  * to get equal ratings for launchers.
430  */
rescale_bow_power(const struct object * obj,int p)431 static int rescale_bow_power(const struct object *obj, int p)
432 {
433 	if (wield_slot(obj) == slot_by_name(player, "shooting")) {
434 		p /= MAX_BLOWS;
435 		log_obj(format("Rescaling bow power, total is %d\n", p));
436 	}
437 	return p;
438 }
439 
440 /**
441  * Add power for +to_hit
442  */
to_hit_power(const struct object * obj,int p)443 static int to_hit_power(const struct object *obj, int p)
444 {
445 	int q = (obj->to_h * TO_HIT_POWER / 2);
446 	p += q;
447 	if (p)
448 		log_obj(format("Add %d power for to hit, total is %d\n", q, p));
449 	return p;
450 }
451 
452 /**
453  * Add power for base AC and adjust for weight
454  */
ac_power(const struct object * obj,int p)455 static int ac_power(const struct object *obj, int p)
456 {
457 	int q = 0;
458 
459 	if (obj->ac) {
460 		p += BASE_ARMOUR_POWER;
461 		q += (obj->ac * BASE_AC_POWER / 2);
462 		log_obj(format("Adding %d power for base AC value\n", q));
463 
464 		/* Add power for AC per unit weight */
465 		if (obj->weight > 0) {
466 			int i = 750 * (obj->ac + obj->to_a) / obj->weight;
467 
468 			/* Avoid overpricing Elven Cloaks */
469 			if (i > 450) i = 450;
470 
471 			q *= i;
472 			q /= 100;
473 
474 			/* Weightless (ethereal) armour items get fixed boost */
475 		} else
476 			q *= 5;
477 		p += q;
478 		log_obj(format("Add %d power for AC per unit weight, now %d\n",	q, p));
479 	}
480 	return p;
481 }
482 
483 
484 /**
485  * Add power for +to_ac
486  */
to_ac_power(const struct object * obj,int p)487 static int to_ac_power(const struct object *obj, int p)
488 {
489 	int q;
490 
491 	if (obj->to_a == 0) return p;
492 
493 	q = (obj->to_a * TO_AC_POWER / 2);
494 	p += q;
495 	log_obj(format("Add %d power for to_ac of %d, total is %d\n",
496 				   q, obj->to_a, p));
497 	if (obj->to_a > HIGH_TO_AC) {
498 		q = ((obj->to_a - (HIGH_TO_AC - 1)) * TO_AC_POWER);
499 		p += q;
500 		log_obj(format("Add %d power for high to_ac, total is %d\n",
501 							q, p));
502 	}
503 	if (obj->to_a > VERYHIGH_TO_AC) {
504 		q = ((obj->to_a - (VERYHIGH_TO_AC -1)) * TO_AC_POWER * 2);
505 		p += q;
506 		log_obj(format("Add %d power for very high to_ac, total is %d\n",q, p));
507 	}
508 	if (obj->to_a >= INHIBIT_AC) {
509 		p += INHIBIT_POWER;
510 		log_obj("INHIBITING: AC bonus too high\n");
511 	}
512 	return p;
513 }
514 
515 /**
516  * Add base power for jewelry
517  */
jewelry_power(const struct object * obj,int p)518 static int jewelry_power(const struct object *obj, int p)
519 {
520 	if (tval_is_jewelry(obj)) {
521 		p += BASE_JEWELRY_POWER;
522 		log_obj(format("Adding %d power for jewelry, total is %d\n",
523 					   BASE_JEWELRY_POWER, p));
524 	}
525 	return p;
526 }
527 
528 /**
529  * Add power for modifiers
530  */
modifier_power(const struct object * obj,int p)531 static int modifier_power(const struct object *obj, int p)
532 {
533 	int i, k, extra_stat_bonus = 0, q;
534 
535 	for (i = 0; i < OBJ_MOD_MAX; i++) {
536 		/* Get the modifier details */
537 		struct obj_property *mod = lookup_obj_property(OBJ_PROPERTY_MOD, i);
538 		assert(mod);
539 
540 		k = obj->modifiers[i];
541 		extra_stat_bonus += (k * mod->mult);
542 
543 		if (mod->power) {
544 			q = (k * mod->power * mod->type_mult[obj->tval]);
545 			p += q;
546 			if (q) log_obj(format("Add %d power for %d %s, total is %d\n",
547 								  q, k, mod->name, p));
548 		}
549 	}
550 
551 	/* Add extra power term if there are a lot of ability bonuses */
552 	if (extra_stat_bonus > 249) {
553 		log_obj(format("Inhibiting - Total ability bonus of %d is too high\n",
554 					   extra_stat_bonus));
555 		p += INHIBIT_POWER;
556 	} else if (extra_stat_bonus > 0) {
557 		q = ability_power[extra_stat_bonus / 10];
558 		if (!q) return p;
559 		p += q;
560 		log_obj(format("Add %d power for modifier total of %d, total is %d\n",
561 					   q, extra_stat_bonus, p));
562 	}
563 	return p;
564 }
565 
566 /**
567  * Add power for non-derived flags (derived flags have flag_power 0)
568  */
flags_power(const struct object * obj,int p,int verbose,ang_file * log_file)569 static int flags_power(const struct object *obj, int p, int verbose,
570 					   ang_file *log_file)
571 {
572 	size_t i, j;
573 	int q;
574 	bitflag flags[OF_SIZE];
575 
576 	/* Extract the flags */
577 	object_flags(obj, flags);
578 
579 	/* Zero the flag counts */
580 	for (i = 0; i < N_ELEMENTS(flag_sets); i++)
581 		flag_sets[i].count = 0;
582 
583 	for (i = of_next(flags, FLAG_START); i != FLAG_END;
584 		 i = of_next(flags, i + 1)) {
585 		/* Get the flag details */
586 		struct obj_property *flag = lookup_obj_property(OBJ_PROPERTY_FLAG, i);
587 		assert(flag);
588 
589 		if (flag->power) {
590 			q = (flag->power * flag->type_mult[obj->tval]);
591 			p += q;
592 			log_obj(format("Add %d power for %s, total is %d\n",
593 						   q, flag->name, p));
594 		}
595 
596 		/* Track combinations of flag types */
597 		for (j = 0; j < N_ELEMENTS(flag_sets); j++)
598 			if (flag_sets[j].type == flag->subtype)
599 				flag_sets[j].count++;
600 	}
601 
602 	/* Add extra power for multiple flags of the same type */
603 	for (i = 0; i < N_ELEMENTS(flag_sets); i++) {
604 		if (flag_sets[i].count > 1) {
605 			q = (flag_sets[i].factor * flag_sets[i].count * flag_sets[i].count);
606 			p += q;
607 			log_obj(format("Add %d power for multiple %s, total is %d\n",
608 						   q, flag_sets[i].desc, p));
609 		}
610 
611 		/* Add bonus if item has a full set of these flags */
612 		if (flag_sets[i].count == flag_sets[i].size) {
613 			q = flag_sets[i].bonus;
614 			p += q;
615 			log_obj(format("Add %d power for full set of %s, total is %d\n",
616 						   q, flag_sets[i].desc, p));
617 		}
618 	}
619 
620 	return p;
621 }
622 
623 /**
624  * Add power for elemental properties
625  */
element_power(const struct object * obj,int p)626 static int element_power(const struct object *obj, int p)
627 {
628 	size_t i, j;
629 	int q;
630 
631 	/* Zero the set counts */
632 	for (i = 0; i < N_ELEMENTS(element_sets); i++)
633 		element_sets[i].count = 0;
634 
635 	/* Analyse each element for ignore, vulnerability, resistance or immunity */
636 	for (i = 0; i < N_ELEMENTS(el_powers); i++) {
637 		if (obj->el_info[i].flags & EL_INFO_IGNORE) {
638 			if (el_powers[i].ignore_power != 0) {
639 				q = (el_powers[i].ignore_power);
640 				p += q;
641 				log_obj(format("Add %d power for ignoring %s, total is %d\n",
642 							   q, el_powers[i].name, p));
643 			}
644 		}
645 
646 		if (obj->el_info[i].res_level == -1) {
647 			if (el_powers[i].vuln_power != 0) {
648 				q = (el_powers[i].vuln_power);
649 				p += q;
650 				log_obj(format("Add %d power for vulnerability to %s, total is %d\n", q, el_powers[i].name, p));
651 			}
652 		} else if (obj->el_info[i].res_level == 1) {
653 			if (el_powers[i].res_power != 0) {
654 				q = (el_powers[i].res_power);
655 				p += q;
656 				log_obj(format("Add %d power for resistance to %s, total is %d\n", q, el_powers[i].name, p));
657 			}
658 		} else if (obj->el_info[i].res_level == 3) {
659 			if (el_powers[i].im_power != 0) {
660 				q = (el_powers[i].im_power + el_powers[i].res_power);
661 				p += q;
662 				log_obj(format("Add %d power for immunity to %s, total is %d\n",
663 							   q, el_powers[i].name, p));
664 			}
665 		}
666 
667 		/* Track combinations of element properties */
668 		for (j = 0; j < N_ELEMENTS(element_sets); j++)
669 			if ((element_sets[j].type == el_powers[i].type) &&
670 				(element_sets[j].res_level <= obj->el_info[i].res_level))
671 				element_sets[j].count++;
672 	}
673 
674 	/* Add extra power for multiple flags of the same type */
675 	for (i = 0; i < N_ELEMENTS(element_sets); i++) {
676 		if (element_sets[i].count > 1) {
677 			q = (element_sets[i].factor * element_sets[i].count * element_sets[i].count);
678 			p += q;
679 			log_obj(format("Add %d power for multiple %s, total is %d\n",
680 						   q, element_sets[i].desc, p));
681 		}
682 
683 		/* Add bonus if item has a full set of these flags */
684 		if (element_sets[i].count == element_sets[i].size) {
685 			q = element_sets[i].bonus;
686 			p += q;
687 			log_obj(format("Add %d power for full set of %s, total is %d\n",
688 						   q, element_sets[i].desc, p));
689 		}
690 	}
691 
692 	return p;
693 }
694 
695 /**
696  * Add power for effect
697  */
effects_power(const struct object * obj,int p)698 static int effects_power(const struct object *obj, int p)
699 {
700 	int q = 0;
701 
702 	if (obj->activation) {
703 		q = obj->activation->power;
704 	} else if (obj->kind->power) {
705 		q = obj->kind->power;
706 	}
707 
708 	if (q) {
709 		p += q;
710 		log_obj(format("Add %d power for item activation, total is %d\n",
711 					   q, p));
712 	}
713 	return p;
714 }
715 
716 /**
717  * Add power for curses
718  */
curse_power(const struct object * obj,int p,int verbose,ang_file * log_file)719 static int curse_power(const struct object *obj, int p, int verbose,
720 					   ang_file *log_file)
721 {
722 	int i, q = 0;
723 
724 	if (obj->curses) {
725 		/* Get the curse object power */
726 		for (i = 1; i < z_info->curse_max; i++) {
727 			if (obj->curses[i].power) {
728 				int curse_power;
729 				log_obj(format("Calculating %s curse power...\n",
730 							   curses[i].name));
731 				curse_power = object_power(curses[i].obj, verbose, log_file);
732 				curse_power -= obj->curses[i].power / 10;
733 				log_obj(format("Adjust for strength of curse, %d for %s curse power\n", curse_power, curses[i].name));
734 				q += curse_power;
735 			}
736 		}
737 	}
738 
739 	if (q != 0) {
740 		p += q;
741 		log_obj(format("Total of %d power added for curses, total is %d\n",
742 					   q, p));
743 	}
744 	return p;
745 }
746 
747 
748 /**
749  * Evaluate the object's overall power level.
750  */
object_power(const struct object * obj,bool verbose,ang_file * log_file)751 s32b object_power(const struct object* obj, bool verbose, ang_file *log_file)
752 {
753 	s32b p = 0, dice_pwr = 0;
754 	int mult;
755 
756 	/* Set the log file */
757 	object_log = log_file;
758 
759 	/* Get all the attack power */
760 	p = to_damage_power(obj);
761 	dice_pwr = damage_dice_power(obj);
762 	p += dice_pwr;
763 	if (dice_pwr) log_obj(format("total is %d\n", p));
764 	p += ammo_damage_power(obj, p);
765 	mult = bow_multiplier(obj);
766 	p = launcher_ammo_damage_power(obj, p);
767 	p = extra_blows_power(obj, p);
768 	if (p > INHIBIT_POWER) return p;
769 	p = extra_shots_power(obj, p);
770 	if (p > INHIBIT_POWER) return p;
771 	p = extra_might_power(obj, p, mult);
772 	if (p > INHIBIT_POWER) return p;
773 	p = slay_power(obj, p, verbose, dice_pwr);
774 	p = rescale_bow_power(obj, p);
775 	p = to_hit_power(obj, p);
776 
777 	/* Armour class power */
778 	p = ac_power(obj, p);
779 	p = to_ac_power(obj, p);
780 
781 	/* Bonus for jewelry */
782 	p = jewelry_power(obj, p);
783 
784 	/* Other object properties */
785 	p = modifier_power(obj, p);
786 	p = flags_power(obj, p, verbose, object_log);
787 	p = element_power(obj, p);
788 	p = effects_power(obj, p);
789 	p = curse_power(obj, p, verbose, object_log);
790 
791 	log_obj(format("FINAL POWER IS %d\n", p));
792 
793 	return p;
794 }
795 
796 
797 /**
798  * ------------------------------------------------------------------------
799  * Object pricing
800  * ------------------------------------------------------------------------ */
801 /**
802  * Return the "value" of an "unknown" item
803  * Make a guess at the value of non-aware items
804  */
object_value_base(const struct object * obj)805 static int object_value_base(const struct object *obj)
806 {
807 	/* Use template cost for aware objects */
808 	if (object_flavor_is_aware(obj))
809 		return obj->kind->cost;
810 
811 	/* Analyze the type */
812 	switch (obj->tval)
813 	{
814 		case TV_FOOD:
815 		case TV_MUSHROOM:
816 			return 5;
817 		case TV_POTION:
818 		case TV_SCROLL:
819 			return 20;
820 		case TV_RING:
821 		case TV_AMULET:
822 			return 45;
823 		case TV_WAND:
824 			return 50;
825 		case TV_STAFF:
826 			return 70;
827 		case TV_ROD:
828 			return 90;
829 	}
830 
831 	return 0;
832 }
833 
834 
835 /**
836  * Return the real price of a known (or partly known) item.
837  *
838  * Wand and staffs get cost for each charge.
839  *
840  * Wearable items (weapons, launchers, jewelry, lights, armour) and ammo
841  * are priced according to their power rating. All ammo, and normal (non-ego)
842  * torches are scaled down by AMMO_RESCALER to reflect their impermanence.
843  */
object_value_real(const struct object * obj,int qty)844 int object_value_real(const struct object *obj, int qty)
845 {
846 	int value, total_value;
847 
848 	int power;
849 	int a = 1;
850 	int b = 5;
851 
852 	/* Wearables and ammo have prices that vary by individual item properties */
853 	if (tval_has_variable_power(obj)) {
854 #ifdef PRICE_DEBUG
855 		char buf[1024];
856 		ang_file *log_file = NULL;
857 		static file_mode pricing_mode = MODE_WRITE;
858 
859 		/* Logging */
860 		path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "pricing.log");
861 		log_file = file_open(buf, pricing_mode, FTYPE_TEXT);
862 		if (!log_file) {
863 			msg("Error - can't open pricing.log for writing.");
864 			exit(1);
865 		}
866 		pricing_mode = MODE_APPEND;
867 
868 		file_putf(log_file, "object is %s\n", obj->kind->name);
869 
870 		power = object_power(obj, true, log_file);
871 #else /* PRICE_DEBUG */
872 		power = object_power(obj, false, NULL);
873 #endif /* PRICE_DEBUG */
874 		value = SGN(power) * ((a * power * power) + (b * power));
875 
876 		/* Rescale for expendables */
877 		if ((tval_is_light(obj) && of_has(obj->flags, OF_BURNS_OUT)
878 			 && !obj->ego) || tval_is_ammo(obj)) {
879 			value = value / AMMO_RESCALER;
880 		}
881 
882 		/* Round up to make sure things like cloaks are not worthless */
883 		if (value == 0) {
884 			value = 1;
885 		}
886 
887 #ifdef PRICE_DEBUG
888 		/* More logging */
889 		file_putf(log_file, "a is %d and b is %d\n", a, b);
890 		file_putf(log_file, "value is %d\n", value);
891 
892 		if (!file_close(log_file)) {
893 			msg("Error - can't close pricing.log file.");
894 			exit(1);
895 		}
896 #endif /* PRICE_DEBUG */
897 
898 		/* Get the total value */
899 		total_value = value * qty;
900 		if (total_value < 0) total_value = 0;
901 	} else {
902 
903 		/* Worthless items */
904 		if (!obj->kind->cost) return (0L);
905 
906 		/* Base cost */
907 		value = obj->kind->cost;
908 
909 		/* Analyze the item type and quantity */
910 		if (tval_can_have_charges(obj)) {
911 			int charges;
912 
913 			total_value = value * qty;
914 
915 			/* Calculate number of charges, rounded up */
916 			charges = obj->pval * qty / obj->number;
917 			if ((obj->pval * qty) % obj->number != 0)
918 				charges++;
919 
920 			/* Pay extra for charges, depending on standard number of charges */
921 			total_value += value * charges / 20;
922 		} else {
923 			total_value = value * qty;
924 		}
925 
926 		/* No negative value */
927 		if (total_value < 0) total_value = 0;
928 	}
929 
930 	/* Return the value */
931 	return (total_value);
932 }
933 
934 
935 /**
936  * Return the price of an item including plusses (and charges).
937  *
938  * This function returns the "value" of the given item (qty one).
939  *
940  * Never notice unknown bonuses or properties, including curses,
941  * since that would give the player information they did not have.
942  */
object_value(const struct object * obj,int qty)943 int object_value(const struct object *obj, int qty)
944 {
945 	int value;
946 
947 	/* Variable power items are assessed by what is known about them */
948 	if (tval_has_variable_power(obj) && obj->known) {
949 		value = object_value_real(obj->known, qty);
950 	} else if (tval_can_have_flavor_k(obj->kind) &&
951 			   object_flavor_is_aware(obj)) {
952 		value = object_value_real(obj, qty);
953 	} else {
954 		/* Unknown constant-price items just get a base value */
955 		value = object_value_base(obj) * qty;
956 	}
957 
958 	/* Return the final value */
959 	return (value);
960 }
961