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