ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/treasure.C
Revision: 1.64
Committed: Sun Jul 1 05:00:18 2007 UTC (16 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.63: +11 -12 lines
Log Message:
- upgrade crossfire trt to the GPL version 3 (hopefully correctly).
- add a single file covered by the GNU Affero General Public License
  (which is not yet released, so I used the current draft, which is
  legally a bit wavy, but its likely better than nothing as it expresses
  direct intent by the authors, and we can upgrade as soon as it has been
  released).
  * this should ensure availability of source code for the server at least
    and hopefully also archetypes and maps even when modified versions
    are not being distributed, in accordance of section 13 of the agplv3.

File Contents

# Content
1 /*
2 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 *
4 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen
7 *
8 * Crossfire TRT is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 * The authors can be reached via e-mail to <crossfire@schmorp.de>
22 */
23
24 /* TREASURE_DEBUG does some checking on the treasurelists after loading.
25 * It is useful for finding bugs in the treasures file. Since it only
26 * slows the startup some (and not actual game play), it is by default
27 * left on
28 */
29 #define TREASURE_DEBUG
30
31 /* TREASURE_VERBOSE enables copious output concerning artifact generation */
32
33 //#define TREASURE_VERBOSE
34
35 #include <global.h>
36 #include <treasure.h>
37 #include <funcpoint.h>
38 #include <loader.h>
39
40 extern char *spell_mapping[];
41
42 static treasurelist *first_treasurelist;
43
44 static void change_treasure (treasure *t, object *op); /* overrule default values */
45
46 typedef std::tr1::unordered_map<
47 const char *,
48 treasurelist *,
49 str_hash,
50 str_equal,
51 slice_allocator< std::pair<const char *const, treasurelist *> >,
52 true
53 > tl_map_t;
54
55 static tl_map_t tl_map;
56
57 /*
58 * Searches for the given treasurelist
59 */
60 treasurelist *
61 treasurelist::find (const char *name)
62 {
63 if (!name)
64 return 0;
65
66 auto (i, tl_map.find (name));
67
68 if (i == tl_map.end ())
69 return 0;
70
71 return i->second;
72 }
73
74 /*
75 * Searches for the given treasurelist in the globally linked list
76 * of treasurelists which has been built by load_treasures().
77 */
78 treasurelist *
79 treasurelist::get (const char *name)
80 {
81 treasurelist *tl = find (name);
82
83 if (!tl)
84 {
85 tl = new treasurelist;
86
87 tl->name = name;
88 tl->next = first_treasurelist;
89 first_treasurelist = tl;
90
91 tl_map.insert (std::make_pair (tl->name, tl));
92 }
93
94 return tl;
95 }
96
97 //TODO: class method
98 void
99 clear (treasurelist *tl)
100 {
101 if (tl->items)
102 {
103 free_treasurestruct (tl->items);
104 tl->items = 0;
105 }
106
107 tl->total_chance = 0;
108 }
109
110 #ifdef TREASURE_DEBUG
111 /* recursived checks the linked list. Treasurelist is passed only
112 * so that the treasure name can be printed out
113 */
114 static void
115 check_treasurelist (const treasure *t, const treasurelist * tl)
116 {
117 if (t->chance >= 100 && t->next_yes && (t->next || t->next_no))
118 LOG (llevError, "Treasurelist %s has element that has 100%% generation, next_yes field as well as next or next_no\n", &tl->name);
119
120 if (t->next)
121 check_treasurelist (t->next, tl);
122
123 if (t->next_yes)
124 check_treasurelist (t->next_yes, tl);
125
126 if (t->next_no)
127 check_treasurelist (t->next_no, tl);
128 }
129 #endif
130
131 /*
132 * Reads the lib/treasure file from disk, and parses the contents
133 * into an internal treasure structure (very linked lists)
134 */
135 static treasure *
136 read_treasure (object_thawer &f)
137 {
138 treasure *t = new treasure;
139
140 f.next ();
141
142 for (;;)
143 {
144 coroapi::cede_to_tick_every (10);
145
146 switch (f.kw)
147 {
148 case KW_arch:
149 t->item = archetype::get (f.get_str ());
150 break;
151
152 case KW_list: f.get (t->name); break;
153 case KW_change_name: f.get (t->change_arch.name); break;
154 case KW_change_title: f.get (t->change_arch.title); break;
155 case KW_change_slaying: f.get (t->change_arch.slaying); break;
156 case KW_chance: f.get (t->chance); break;
157 case KW_nrof: f.get (t->nrof); break;
158 case KW_magic: f.get (t->magic); break;
159
160 case KW_yes: t->next_yes = read_treasure (f); continue;
161 case KW_no: t->next_no = read_treasure (f); continue;
162
163 case KW_end:
164 f.next ();
165 return t;
166
167 case KW_more:
168 t->next = read_treasure (f);
169 return t;
170
171 default:
172 if (!f.parse_error ("treasurelist", t->name))
173 return 0;
174
175 return t;
176 }
177
178 f.next ();
179 }
180 }
181
182 /*
183 * Each treasure is parsed with the help of load_treasure().
184 */
185 treasurelist *
186 treasurelist::read (object_thawer &f)
187 {
188 assert (f.kw == KW_treasure || f.kw == KW_treasureone);
189
190 bool one = f.kw == KW_treasureone;
191 treasurelist *tl = treasurelist::get (f.get_str ());
192 clear (tl);
193 tl->items = read_treasure (f);
194 if (!tl->items)
195 return 0;
196
197 /* This is a one of the many items on the list should be generated.
198 * Add up the chance total, and check to make sure the yes & no
199 * fields of the treasures are not being used.
200 */
201 if (one)
202 {
203 for (treasure *t = tl->items; t; t = t->next)
204 {
205 if (t->next_yes || t->next_no)
206 {
207 LOG (llevError, "Treasure %s is one item, but on treasure %s\n", &tl->name, t->item ? &t->item->archname : &t->name);
208 LOG (llevError, " the next_yes or next_no field is set\n");
209 }
210
211 tl->total_chance += t->chance;
212 }
213 }
214
215 return tl;
216 }
217
218 /*
219 * Generates the objects specified by the given treasure.
220 * It goes recursively through the rest of the linked list.
221 * If there is a certain percental chance for a treasure to be generated,
222 * this is taken into consideration.
223 * The second argument specifies for which object the treasure is
224 * being generated.
225 * If flag is GT_INVISIBLE, only invisible objects are generated (ie, only
226 * abilities. This is used by summon spells, thus no summoned monsters
227 * start with equipment, but only their abilities).
228 */
229 static void
230 put_treasure (object *op, object *creator, int flags)
231 {
232 if (flags & GT_ENVIRONMENT)
233 {
234 /* Bit of a hack - spells should never be put onto the map. The entire
235 * treasure stuff is a problem - there is no clear idea of knowing
236 * this is the original object, or if this is an object that should be created
237 * by another object.
238 */
239 //TODO: flag such as objects... as such (no drop, anybody?)
240 if (op->type == SPELL)
241 {
242 op->destroy ();
243 return;
244 }
245
246 op->expand_tail ();
247
248 if (ob_blocked (op, creator->map, creator->x, creator->y))
249 op->destroy ();
250 else
251 {
252 SET_FLAG (op, FLAG_OBJ_ORIGINAL);
253 op->insert_at (creator, creator, INS_NO_MERGE | INS_NO_WALK_ON);
254 }
255 }
256 else
257 {
258 op = creator->insert (op);
259
260 if ((flags & GT_APPLY) && QUERY_FLAG (creator, FLAG_MONSTER))
261 monster_check_apply (creator, op);
262
263 if (flags & GT_UPDATE_INV)
264 if (object *tmp = creator->in_player ())
265 esrv_send_item (tmp, op);
266 }
267 }
268
269 /* if there are change_xxx commands in the treasure, we include the changes
270 * in the generated object
271 */
272 static void
273 change_treasure (treasure *t, object *op)
274 {
275 /* CMD: change_name xxxx */
276 if (t->change_arch.name)
277 {
278 op->name = t->change_arch.name;
279 op->name_pl = t->change_arch.name;
280 }
281
282 if (t->change_arch.title)
283 op->title = t->change_arch.title;
284
285 if (t->change_arch.slaying)
286 op->slaying = t->change_arch.slaying;
287 }
288
289 static void
290 create_all_treasures (treasure *t, object *op, int flag, int difficulty, int tries)
291 {
292 if ((int) t->chance >= 100 || (rndm (100) + 1) < (int) t->chance)
293 {
294 if (t->name)
295 {
296 if (difficulty >= t->magic)
297 if (treasurelist *tl = treasurelist::find (t->name))
298 create_treasure (tl, op, flag, difficulty, tries);
299 else
300 LOG (llevError, "create_all_treasures: undefined reference to treasurelist '%s'.\n", &t->name);
301 }
302 else
303 {
304 if (t->item && (t->item->invisible != 0 || !(flag & GT_INVISIBLE)))
305 {
306 object *tmp = arch_to_object (t->item);
307
308 if (t->nrof && tmp->nrof <= 1)
309 tmp->nrof = rndm (t->nrof) + 1;
310
311 fix_generated_item (tmp, op, difficulty, t->magic, flag);
312 change_treasure (t, tmp);
313 put_treasure (tmp, op, flag);
314 }
315 }
316
317 if (t->next_yes)
318 create_all_treasures (t->next_yes, op, flag, difficulty, tries);
319 }
320 else if (t->next_no)
321 create_all_treasures (t->next_no, op, flag, difficulty, tries);
322
323 if (t->next)
324 create_all_treasures (t->next, op, flag, difficulty, tries);
325 }
326
327 static void
328 create_one_treasure (treasurelist *tl, object *op, int flag, int difficulty, int tries)
329 {
330 int value = rndm (tl->total_chance);
331 treasure *t;
332
333 if (tries++ > 100)
334 {
335 LOG (llevDebug, "create_one_treasure: tries exceeded 100, returning without making treasure\n");
336 return;
337 }
338
339 for (t = tl->items; t; t = t->next)
340 {
341 value -= t->chance;
342
343 if (value < 0)
344 break;
345 }
346
347 if (!t || value >= 0)
348 cleanup ("create_one_treasure: got null object or not able to find treasure\n", 1);
349
350 if (t->name)
351 {
352 if (difficulty >= t->magic)
353 {
354 treasurelist *tl = treasurelist::find (t->name);
355 if (tl)
356 create_treasure (tl, op, flag, difficulty, tries);
357 }
358 else if (t->nrof)
359 create_one_treasure (tl, op, flag, difficulty, tries);
360 }
361 else if (t->item && (t->item->invisible != 0 || flag != GT_INVISIBLE))
362 {
363 if (object *tmp = arch_to_object (t->item))
364 {
365 if (t->nrof && tmp->nrof <= 1)
366 tmp->nrof = rndm (t->nrof) + 1;
367
368 fix_generated_item (tmp, op, difficulty, t->magic, flag);
369 change_treasure (t, tmp);
370 put_treasure (tmp, op, flag);
371 }
372 }
373 }
374
375 void
376 object::create_treasure (treasurelist *tl, int flags)
377 {
378 ::create_treasure (tl, this, flags, map ? map->difficulty : 0);
379 }
380
381 /* This calls the appropriate treasure creation function. tries is passed
382 * to determine how many list transitions or attempts to create treasure
383 * have been made. It is really in place to prevent infinite loops with
384 * list transitions, or so that excessively good treasure will not be
385 * created on weak maps, because it will exceed the number of allowed tries
386 * to do that.
387 */
388 void
389 create_treasure (treasurelist *tl, object *op, int flag, int difficulty, int tries)
390 {
391 // empty treasurelists are legal
392 if (!tl->items)
393 return;
394
395 if (tries++ > 100)
396 {
397 LOG (llevDebug, "createtreasure: tries exceeded 100, returning without making treasure\n");
398 return;
399 }
400
401 if (op->flag [FLAG_TREASURE_ENV])
402 {
403 // do not generate items when there already is something above the object
404 if (op->flag [FLAG_IS_FLOOR] && op->above)
405 return;
406
407 flag |= GT_ENVIRONMENT;
408 }
409
410 if (tl->total_chance)
411 create_one_treasure (tl, op, flag, difficulty, tries);
412 else
413 create_all_treasures (tl->items, op, flag, difficulty, tries);
414 }
415
416 /* This is similar to the old generate treasure function. However,
417 * it instead takes a treasurelist. It is really just a wrapper around
418 * create_treasure. We create a dummy object that the treasure gets
419 * inserted into, and then return that treausre
420 */
421 object *
422 generate_treasure (treasurelist *tl, int difficulty)
423 {
424 difficulty = clamp (difficulty, 1, settings.max_level);
425
426 object *ob = object::create ();
427
428 create_treasure (tl, ob, 0, difficulty, 0);
429
430 /* Don't want to free the object we are about to return */
431 object *tmp = ob->inv;
432 if (tmp)
433 tmp->remove ();
434
435 if (ob->inv)
436 LOG (llevError, "In generate treasure, created multiple objects.\n");
437
438 ob->destroy ();
439 return tmp;
440 }
441
442 /*
443 * This is a new way of calculating the chance for an item to have
444 * a specific magical bonus.
445 * The array has two arguments, the difficulty of the level, and the
446 * magical bonus "wanted".
447 */
448
449 static int difftomagic_list[DIFFLEVELS][MAXMAGIC + 1] = {
450 // chance of magic difficulty
451 // +0 +1 +2 +3 +4
452 {95, 2, 2, 1, 0}, // 1
453 {92, 5, 2, 1, 0}, // 2
454 {85, 10, 4, 1, 0}, // 3
455 {80, 14, 4, 2, 0}, // 4
456 {75, 17, 5, 2, 1}, // 5
457 {70, 18, 8, 3, 1}, // 6
458 {65, 21, 10, 3, 1}, // 7
459 {60, 22, 12, 4, 2}, // 8
460 {55, 25, 14, 4, 2}, // 9
461 {50, 27, 16, 5, 2}, // 10
462 {45, 28, 18, 6, 3}, // 11
463 {42, 28, 20, 7, 3}, // 12
464 {40, 27, 21, 8, 4}, // 13
465 {38, 25, 22, 10, 5}, // 14
466 {36, 23, 23, 12, 6}, // 15
467 {33, 21, 24, 14, 8}, // 16
468 {31, 19, 25, 16, 9}, // 17
469 {27, 15, 30, 18, 10}, // 18
470 {20, 12, 30, 25, 13}, // 19
471 {15, 10, 28, 30, 17}, // 20
472 {13, 9, 27, 28, 23}, // 21
473 {10, 8, 25, 28, 29}, // 22
474 { 8, 7, 23, 26, 36}, // 23
475 { 6, 6, 20, 22, 46}, // 24
476 { 4, 5, 17, 18, 56}, // 25
477 { 2, 4, 12, 14, 68}, // 26
478 { 0, 3, 7, 10, 80}, // 27
479 { 0, 0, 3, 7, 90}, // 28
480 { 0, 0, 0, 3, 97}, // 29
481 { 0, 0, 0, 0, 100}, // 30
482 { 0, 0, 0, 0, 100}, // 31
483 };
484
485 /* calculate the appropriate level for wands staves and scrolls.
486 * This code presumes that op has had its spell object created (in op->inv)
487 *
488 * elmex Wed Aug 9 17:44:59 CEST 2006:
489 * Removed multiplicator, too many high-level items were generated on low-difficulty maps.
490 */
491 int
492 level_for_item (const object *op, int difficulty)
493 {
494 int olevel = 0;
495
496 if (!op->inv)
497 {
498 LOG (llevError, "level_for_item: Object %s has no inventory!\n", &op->name);
499 return 0;
500 }
501
502 olevel = (int) (op->inv->level + (double) difficulty * (1 - drand48 () * drand48 () * 2));
503
504 if (olevel <= 0)
505 olevel = rndm (1, MIN (op->inv->level, 1));
506
507 if (olevel > MAXLEVEL)
508 olevel = MAXLEVEL;
509
510 return olevel;
511 }
512
513 /*
514 * Based upon the specified difficulty and upon the difftomagic_list array,
515 * a random magical bonus is returned. This is used when determine
516 * the magical bonus created on specific maps.
517 *
518 * elmex Thu Aug 10 18:45:44 CEST 2006:
519 * Scaling difficulty by max_level, as difficulty is a level and not some
520 * weird integer between 1-31.
521 *
522 */
523 int
524 magic_from_difficulty (int difficulty)
525 {
526 int percent = 0, magic = 0;
527 int scaled_diff = (int) (((double) difficulty / settings.max_level) * DIFFLEVELS);
528
529 scaled_diff--;
530
531 if (scaled_diff < 0)
532 scaled_diff = 0;
533
534 if (scaled_diff >= DIFFLEVELS)
535 scaled_diff = DIFFLEVELS - 1;
536
537 percent = rndm (100);
538
539 for (magic = 0; magic < (MAXMAGIC + 1); magic++)
540 {
541 percent -= difftomagic_list[scaled_diff][magic];
542
543 if (percent < 0)
544 break;
545 }
546
547 if (magic == (MAXMAGIC + 1))
548 {
549 LOG (llevError, "Warning, table for difficulty (scaled %d) %d bad.\n", scaled_diff, difficulty);
550 magic = 0;
551 }
552
553 magic = (rndm (3)) ? magic : -magic;
554 /* LOG(llevDebug, "Chose magic %d for difficulty (scaled %d) %d\n", magic, scaled_diff, difficulty); */
555
556 return magic;
557 }
558
559 /*
560 * Sets magical bonus in an object, and recalculates the effect on
561 * the armour variable, and the effect on speed of armour.
562 * This function doesn't work properly, should add use of archetypes
563 * to make it truly absolute.
564 */
565
566 void
567 set_abs_magic (object *op, int magic)
568 {
569 if (!magic)
570 return;
571
572 op->magic = magic;
573 if (op->arch)
574 {
575 if (op->type == ARMOUR)
576 ARMOUR_SPEED (op) = (ARMOUR_SPEED (op->arch) * (100 + magic * 10)) / 100;
577
578 if (magic < 0 && !(rndm (3))) /* You can't just check the weight always */
579 magic = (-magic);
580 op->weight = (op->arch->weight * (100 - magic * 10)) / 100;
581 }
582 else
583 {
584 if (op->type == ARMOUR)
585 ARMOUR_SPEED (op) = (ARMOUR_SPEED (op) * (100 + magic * 10)) / 100;
586 if (magic < 0 && !(rndm (3))) /* You can't just check the weight always */
587 magic = (-magic);
588 op->weight = (op->weight * (100 - magic * 10)) / 100;
589 }
590 }
591
592 /*
593 * Sets a random magical bonus in the given object based upon
594 * the given difficulty, and the given max possible bonus.
595 */
596
597 static void
598 set_magic (int difficulty, object *op, int max_magic, int flags)
599 {
600 int i;
601
602 i = magic_from_difficulty (difficulty);
603 if ((flags & GT_ONLY_GOOD) && i < 0)
604 i = -i;
605 if (i > max_magic)
606 i = max_magic;
607 set_abs_magic (op, i);
608 if (i < 0)
609 SET_FLAG (op, FLAG_CURSED);
610 }
611
612 /*
613 * Randomly adds one magical ability to the given object.
614 * Modified for Partial Resistance in many ways:
615 * 1) Since rings can have multiple bonuses, if the same bonus
616 * is rolled again, increase it - the bonuses now stack with
617 * other bonuses previously rolled and ones the item might natively have.
618 * 2) Add code to deal with new PR method.
619 */
620 void
621 set_ring_bonus (object *op, int bonus)
622 {
623
624 int r = rndm (bonus > 0 ? 25 : 11);
625
626 if (op->type == AMULET)
627 {
628 if (!(rndm (21)))
629 r = 20 + rndm (2);
630 else
631 {
632 if (rndm (2))
633 r = 10;
634 else
635 r = 11 + rndm (9);
636 }
637 }
638
639 switch (r)
640 {
641 /* Redone by MSW 2000-11-26 to have much less code. Also,
642 * bonuses and penalties will stack and add to existing values.
643 * of the item.
644 */
645 case 0:
646 case 1:
647 case 2:
648 case 3:
649 case 4:
650 case 5:
651 case 6:
652 op->stats.stat (r) += bonus;
653 break;
654
655 case 7:
656 op->stats.dam += bonus;
657 break;
658
659 case 8:
660 op->stats.wc += bonus;
661 break;
662
663 case 9:
664 op->stats.food += bonus; /* hunger/sustenance */
665 break;
666
667 case 10:
668 op->stats.ac += bonus;
669 break;
670
671 /* Item that gives protections/vulnerabilities */
672 case 11:
673 case 12:
674 case 13:
675 case 14:
676 case 15:
677 case 16:
678 case 17:
679 case 18:
680 case 19:
681 {
682 int b = 5 + abs (bonus), val, resist = rndm (num_resist_table);
683
684 /* Roughly generate a bonus between 100 and 35 (depending on the bonus) */
685 val = 10 + rndm (b) + rndm (b) + rndm (b) + rndm (b);
686
687 /* Cursed items need to have higher negative values to equal out with
688 * positive values for how protections work out. Put another
689 * little random element in since that they don't always end up with
690 * even values.
691 */
692 if (bonus < 0)
693 val = 2 * -val - rndm (b);
694 if (val > 35)
695 val = 35; /* Upper limit */
696 b = 0;
697
698 while (op->resist[resist_table[resist]] != 0 && b < 4)
699 resist = rndm (num_resist_table);
700
701 if (b == 4)
702 return; /* Not able to find a free resistance */
703
704 op->resist[resist_table[resist]] = val;
705 /* We should probably do something more clever here to adjust value
706 * based on how good a resistance we gave.
707 */
708 break;
709 }
710 case 20:
711 if (op->type == AMULET)
712 {
713 SET_FLAG (op, FLAG_REFL_SPELL);
714 op->value *= 11;
715 }
716 else
717 {
718 op->stats.hp = 1; /* regenerate hit points */
719 op->value *= 4;
720 }
721 break;
722
723 case 21:
724 if (op->type == AMULET)
725 {
726 SET_FLAG (op, FLAG_REFL_MISSILE);
727 op->value *= 9;
728 }
729 else
730 {
731 op->stats.sp = 1; /* regenerate spell points */
732 op->value *= 3;
733 }
734 break;
735
736 case 22:
737 op->stats.exp += bonus; /* Speed! */
738 op->value = (op->value * 2) / 3;
739 break;
740 }
741
742 if (bonus > 0)
743 op->value *= 2 * bonus;
744 else
745 op->value = -(op->value * 2 * bonus) / 3;
746 }
747
748 /*
749 * get_magic(diff) will return a random number between 0 and 4.
750 * diff can be any value above 2. The higher the diff-variable, the
751 * higher is the chance of returning a low number.
752 * It is only used in fix_generated_treasure() to set bonuses on
753 * rings and amulets.
754 * Another scheme is used to calculate the magic of weapons and armours.
755 */
756 int
757 get_magic (int diff)
758 {
759 int i;
760
761 if (diff < 3)
762 diff = 3;
763
764 for (i = 0; i < 4; i++)
765 if (rndm (diff))
766 return i;
767
768 return 4;
769 }
770
771 #define DICE2 (get_magic(2)==2?2:1)
772 #define DICESPELL (rndm (3) + rndm (3) + rndm (3) + rndm (3) + rndm (3))
773
774 /*
775 * fix_generated_item(): This is called after an item is generated, in
776 * order to set it up right. This produced magical bonuses, puts spells
777 * into scrolls/books/wands, makes it unidentified, hides the value, etc.
778 */
779
780 /* 4/28/96 added creator object from which op may now inherit properties based on
781 * op->type. Right now, which stuff the creator passes on is object type
782 * dependant. I know this is a spagetti manuever, but is there a cleaner
783 * way to do this? b.t. */
784
785 /*
786 * ! (flags & GT_ENVIRONMENT):
787 * Automatically calls fix_flesh_item().
788 *
789 * flags:
790 * GT_STARTEQUIP: Sets FLAG_STARTEQIUP on item if appropriate, or clears the item's
791 * value.
792 * GT_MINIMAL: Does minimal processing on the object - just enough to make it
793 * a working object - don't change magic, value, etc, but set it material
794 * type as appropriate, for objects that need spell objects, set those, etc
795 */
796 void
797 fix_generated_item (object *op, object *creator, int difficulty, int max_magic, int flags)
798 {
799 int was_magic = op->magic, num_enchantments = 0, save_item_power = 0;
800
801 if (!creator || creator->type == op->type)
802 creator = op; /*safety & to prevent polymorphed objects giving attributes */
803
804 /* If we make an artifact, this information will be destroyed */
805 save_item_power = op->item_power;
806 op->item_power = 0;
807
808 if (op->randomitems && op->type != SPELL)
809 {
810 create_treasure (op->randomitems, op, flags & ~GT_ENVIRONMENT, difficulty, 0);
811 /* So the treasure doesn't get created again */
812 op->randomitems = 0;
813 }
814
815 if (difficulty < 1)
816 difficulty = 1;
817
818 if (INVOKE_OBJECT (ADD_BONUS, op,
819 ARG_OBJECT (creator != op ? creator : 0),
820 ARG_INT (difficulty), ARG_INT (max_magic),
821 ARG_INT (flags)))
822 return;
823
824 if (!(flags & GT_MINIMAL))
825 {
826 if (op->arch == crown_arch)
827 {
828 set_magic (difficulty, op, max_magic, flags);
829 num_enchantments = calc_item_power (op, 1);
830 generate_artifact (op, difficulty);
831 }
832 else
833 {
834 if (!op->magic && max_magic)
835 set_magic (difficulty, op, max_magic, flags);
836
837 num_enchantments = calc_item_power (op, 1);
838
839 if ((!was_magic && !rndm (CHANCE_FOR_ARTIFACT))
840 || op->type == HORN
841 || difficulty >= settings.max_level) /* high difficulties always generate an artifact,
842 * used for shop_floors or treasures */
843 generate_artifact (op, difficulty);
844 }
845
846 /* Object was made an artifact. Calculate its item_power rating.
847 * the item_power in the object is what the artfiact adds.
848 */
849 if (op->title)
850 {
851 /* if save_item_power is set, then most likely we started with an
852 * artifact and have added new abilities to it - this is rare, but
853 * but I have seen things like 'strange rings of fire'. So just figure
854 * out the power from the base power plus what this one adds. Note
855 * that since item_power is not quite linear, this actually ends up
856 * being somewhat of a bonus
857 */
858 if (save_item_power)
859 op->item_power = save_item_power + get_power_from_ench (op->item_power);
860 else
861 op->item_power = get_power_from_ench (op->item_power + num_enchantments);
862 }
863 else if (save_item_power)
864 {
865 /* restore the item_power field to the object if we haven't changed it.
866 * we don't care about num_enchantments - that will basically just
867 * have calculated some value from the base attributes of the archetype.
868 */
869 op->item_power = save_item_power;
870 }
871 else
872 {
873 /* item_power was zero. This is suspicious, as it may be because it
874 * was never previously calculated. Let's compute a value and see if
875 * it is non-zero. If it indeed is, then assign it as the new
876 * item_power value.
877 * - gros, 21th of July 2006.
878 */
879 op->item_power = calc_item_power (op, 0);
880 save_item_power = op->item_power; /* Just in case it would get used
881 * again below */
882 }
883 }
884
885 /* materialtype modifications. Note we allow this on artifacts. */
886 set_materialname (op, difficulty, NULL);
887
888 if (flags & GT_MINIMAL)
889 {
890 if (op->type == POTION)
891 /* Handle healing and magic power potions */
892 if (op->stats.sp && !op->randomitems)
893 {
894 object *tmp;
895
896 tmp = get_archetype (spell_mapping[op->stats.sp]);
897 insert_ob_in_ob (tmp, op);
898 op->stats.sp = 0;
899 }
900 }
901 else if (!op->title) /* Only modify object if not special */
902 switch (op->type)
903 {
904 case WEAPON:
905 case ARMOUR:
906 case SHIELD:
907 case HELMET:
908 case CLOAK:
909 if (QUERY_FLAG (op, FLAG_CURSED) && !(rndm (4)))
910 set_ring_bonus (op, -DICE2);
911 break;
912
913 case BRACERS:
914 if (!rndm (QUERY_FLAG (op, FLAG_CURSED) ? 5 : 20))
915 {
916 set_ring_bonus (op, QUERY_FLAG (op, FLAG_CURSED) ? -DICE2 : DICE2);
917 if (!QUERY_FLAG (op, FLAG_CURSED))
918 op->value *= 3;
919 }
920 break;
921
922 case POTION:
923 {
924 int too_many_tries = 0, is_special = 0;
925
926 /* Handle healing and magic power potions */
927 if (op->stats.sp && !op->randomitems)
928 {
929 object *tmp;
930
931 tmp = get_archetype (spell_mapping[op->stats.sp]);
932 insert_ob_in_ob (tmp, op);
933 op->stats.sp = 0;
934 }
935
936 while (!(is_special = special_potion (op)) && !op->inv)
937 {
938 generate_artifact (op, difficulty);
939 if (too_many_tries++ > 10)
940 break;
941 }
942
943 /* don't want to change value for healing/magic power potions,
944 * since the value set on those is already correct.
945 */
946 if (op->inv && op->randomitems)
947 {
948 /* value multiplier is same as for scrolls */
949 op->value = (op->value * op->inv->value);
950 op->level = op->inv->level / 2 + rndm (difficulty) + rndm (difficulty);
951 }
952 else
953 {
954 op->name = "potion";
955 op->name_pl = "potions";
956 }
957
958 if (!(flags & GT_ONLY_GOOD) && rndm (2))
959 SET_FLAG (op, FLAG_CURSED);
960 break;
961 }
962
963 case AMULET:
964 if (op->arch == amulet_arch)
965 op->value *= 5; /* Since it's not just decoration */
966
967 case RING:
968 if (op->arch == NULL)
969 {
970 op->destroy ();
971 op = 0;
972 break;
973 }
974
975 if (op->arch != ring_arch && op->arch != amulet_arch) /* It's a special artifact! */
976 break;
977
978 if (!(flags & GT_ONLY_GOOD) && !(rndm (3)))
979 SET_FLAG (op, FLAG_CURSED);
980
981 set_ring_bonus (op, QUERY_FLAG (op, FLAG_CURSED) ? -DICE2 : DICE2);
982
983 if (op->type != RING) /* Amulets have only one ability */
984 break;
985
986 if (!(rndm (4)))
987 {
988 int d = (rndm (2) || QUERY_FLAG (op, FLAG_CURSED)) ? -DICE2 : DICE2;
989
990 if (d > 0)
991 op->value *= 3;
992
993 set_ring_bonus (op, d);
994
995 if (!(rndm (4)))
996 {
997 int d = (rndm (3) || QUERY_FLAG (op, FLAG_CURSED)) ? -DICE2 : DICE2;
998
999 if (d > 0)
1000 op->value *= 5;
1001 set_ring_bonus (op, d);
1002 }
1003 }
1004
1005 if (GET_ANIM_ID (op))
1006 SET_ANIMATION (op, rndm (NUM_ANIMATIONS (op)));
1007
1008 break;
1009
1010 case BOOK:
1011 /* Is it an empty book?, if yes lets make a special·
1012 * msg for it, and tailor its properties based on the·
1013 * creator and/or map level we found it on.
1014 */
1015 if (!op->msg && rndm (10))
1016 {
1017 /* set the book level properly */
1018 if (creator->level == 0 || QUERY_FLAG (creator, FLAG_ALIVE))
1019 {
1020 if (op->map && op->map->difficulty)
1021 op->level = rndm (op->map->difficulty) + rndm (10) + 1;
1022 else
1023 op->level = rndm (20) + 1;
1024 }
1025 else
1026 op->level = rndm (creator->level);
1027
1028 tailor_readable_ob (op, (creator && creator->stats.sp) ? creator->stats.sp : -1);
1029 /* books w/ info are worth more! */
1030 op->value *= ((op->level > 10 ? op->level : (op->level + 1) / 2) * ((strlen (op->msg) / 250) + 1));
1031 /* creator related stuff */
1032
1033 /* for library, chained books. Note that some monsters have no_pick
1034 * set - we don't want to set no pick in that case.
1035 */
1036 if (QUERY_FLAG (creator, FLAG_NO_PICK) && !QUERY_FLAG (creator, FLAG_MONSTER))
1037 SET_FLAG (op, FLAG_NO_PICK);
1038 if (creator->slaying && !op->slaying) /* for check_inv floors */
1039 op->slaying = creator->slaying;
1040
1041 /* add exp so reading it gives xp (once) */
1042 op->stats.exp = op->value > 10000 ? op->value / 5 : op->value / 10;
1043 }
1044 break;
1045
1046 case SPELLBOOK:
1047 op->value = op->value * op->inv->value;
1048 /* add exp so learning gives xp */
1049 op->level = op->inv->level;
1050 op->stats.exp = op->value;
1051 break;
1052
1053 case WAND:
1054 /* nrof in the treasure list is number of charges,
1055 * not number of wands. So copy that into food (charges),
1056 * and reset nrof.
1057 */
1058 op->stats.food = op->inv->nrof;
1059 op->nrof = 1;
1060 /* If the spell changes by level, choose a random level
1061 * for it, and adjust price. If the spell doesn't
1062 * change by level, just set the wand to the level of
1063 * the spell, and value calculation is simpler.
1064 */
1065 if (op->inv->duration_modifier || op->inv->dam_modifier || op->inv->range_modifier)
1066 {
1067 op->level = level_for_item (op, difficulty);
1068 op->value = op->value * op->inv->value * (op->level + 50) / (op->inv->level + 50);
1069 }
1070 else
1071 {
1072 op->level = op->inv->level;
1073 op->value = op->value * op->inv->value;
1074 }
1075 break;
1076
1077 case ROD:
1078 op->level = level_for_item (op, difficulty);
1079 /* Add 50 to both level an divisor to keep prices a little more
1080 * reasonable. Otherwise, a high level version of a low level
1081 * spell can be worth tons a money (eg, level 20 rod, level 2 spell =
1082 * 10 time multiplier). This way, the value are a bit more reasonable.
1083 */
1084 op->value = op->value * op->inv->value * (op->level + 50) / (op->inv->level + 50);
1085 /* maxhp is used to denote how many 'charges' the rod holds before */
1086 if (op->stats.maxhp)
1087 op->stats.maxhp *= MAX (op->inv->stats.sp, op->inv->stats.grace);
1088 else
1089 op->stats.maxhp = 2 * MAX (op->inv->stats.sp, op->inv->stats.grace);
1090
1091 op->stats.hp = op->stats.maxhp;
1092 break;
1093
1094 case SCROLL:
1095 op->level = level_for_item (op, difficulty);
1096 op->value = op->value * op->inv->value * (op->level + 50) / (op->inv->level + 50);
1097
1098 /* add exp so reading them properly gives xp */
1099 op->stats.exp = op->value / 5;
1100 op->nrof = op->inv->nrof;
1101 break;
1102
1103 case RUNE:
1104 trap_adjust (op, difficulty);
1105 break;
1106
1107 case TRAP:
1108 trap_adjust (op, difficulty);
1109 break;
1110 } /* switch type */
1111
1112 if (flags & GT_STARTEQUIP)
1113 {
1114 if (op->nrof < 2 && op->type != CONTAINER && op->type != MONEY && !QUERY_FLAG (op, FLAG_IS_THROWN))
1115 SET_FLAG (op, FLAG_STARTEQUIP);
1116 else if (op->type != MONEY)
1117 op->value = 0;
1118 }
1119
1120 if (!(flags & GT_ENVIRONMENT))
1121 fix_flesh_item (op, creator);
1122 }
1123
1124 /*
1125 *
1126 *
1127 * CODE DEALING WITH ARTIFACTS STARTS HERE
1128 *
1129 *
1130 */
1131
1132 /*
1133 * Allocate and return the pointer to an empty artifactlist structure.
1134 */
1135 static artifactlist *
1136 get_empty_artifactlist (void)
1137 {
1138 return salloc0 <artifactlist> ();
1139 }
1140
1141 /*
1142 * Allocate and return the pointer to an empty artifact structure.
1143 */
1144 static artifact *
1145 get_empty_artifact (void)
1146 {
1147 return salloc0 <artifact> ();
1148 }
1149
1150 /*
1151 * Searches the artifact lists and returns one that has the same type
1152 * of objects on it.
1153 */
1154 artifactlist *
1155 find_artifactlist (int type)
1156 {
1157 for (artifactlist *al = first_artifactlist; al; al = al->next)
1158 if (al->type == type)
1159 return al;
1160
1161 return 0;
1162 }
1163
1164 /*
1165 * For debugging purposes. Dumps all tables.
1166 */
1167 void
1168 dump_artifacts (void)
1169 {
1170 artifactlist *al;
1171 artifact *art;
1172 linked_char *next;
1173
1174 fprintf (logfile, "\n");
1175 for (al = first_artifactlist; al != NULL; al = al->next)
1176 {
1177 fprintf (logfile, "Artifact has type %d, total_chance=%d\n", al->type, al->total_chance);
1178 for (art = al->items; art != NULL; art = art->next)
1179 {
1180 fprintf (logfile, "Artifact %-30s Difficulty %3d Chance %5d\n", &art->item->name, art->difficulty, art->chance);
1181 if (art->allowed != NULL)
1182 {
1183 fprintf (logfile, "\tallowed combinations:");
1184 for (next = art->allowed; next != NULL; next = next->next)
1185 fprintf (logfile, "%s,", &next->name);
1186 fprintf (logfile, "\n");
1187 }
1188 }
1189 }
1190 fprintf (logfile, "\n");
1191 }
1192
1193 /*
1194 * For debugging purposes. Dumps all treasures recursively (see below).
1195 */
1196 void
1197 dump_monster_treasure_rec (const char *name, treasure *t, int depth)
1198 {
1199 treasurelist *tl;
1200 int i;
1201
1202 if (depth > 100)
1203 return;
1204
1205 while (t)
1206 {
1207 if (t->name)
1208 {
1209 for (i = 0; i < depth; i++)
1210 fprintf (logfile, " ");
1211
1212 fprintf (logfile, "{ (list: %s)\n", &t->name);
1213
1214 tl = treasurelist::find (t->name);
1215 if (tl)
1216 dump_monster_treasure_rec (name, tl->items, depth + 2);
1217
1218 for (i = 0; i < depth; i++)
1219 fprintf (logfile, " ");
1220
1221 fprintf (logfile, "} (end of list: %s)\n", &t->name);
1222 }
1223 else
1224 {
1225 for (i = 0; i < depth; i++)
1226 fprintf (logfile, " ");
1227
1228 if (t->item && t->item->type == FLESH)
1229 fprintf (logfile, "%s's %s\n", name, &t->item->object::name);
1230 else
1231 fprintf (logfile, "%s\n", &t->item->object::name);
1232 }
1233
1234 if (t->next_yes)
1235 {
1236 for (i = 0; i < depth; i++)
1237 fprintf (logfile, " ");
1238
1239 fprintf (logfile, " (if yes)\n");
1240 dump_monster_treasure_rec (name, t->next_yes, depth + 1);
1241 }
1242
1243 if (t->next_no)
1244 {
1245 for (i = 0; i < depth; i++)
1246 fprintf (logfile, " ");
1247
1248 fprintf (logfile, " (if no)\n");
1249 dump_monster_treasure_rec (name, t->next_no, depth + 1);
1250 }
1251
1252 t = t->next;
1253 }
1254 }
1255
1256 /*
1257 * For debugging purposes. Dumps all treasures for a given monster.
1258 * Created originally by Raphael Quinet for debugging the alchemy code.
1259 */
1260 void
1261 dump_monster_treasure (const char *name)
1262 {
1263 archetype *at;
1264 int found;
1265
1266 found = 0;
1267 fprintf (logfile, "\n");
1268
1269 for_all_archetypes (at)
1270 if (!strcasecmp (at->object::name, name) && at->title == NULL)
1271 {
1272 fprintf (logfile, "treasures for %s (arch: %s)\n", &at->object::name, &at->archname);
1273 if (at->randomitems != NULL)
1274 dump_monster_treasure_rec (at->object::name, at->randomitems->items, 1);
1275 else
1276 fprintf (logfile, "(nothing)\n");
1277
1278 fprintf (logfile, "\n");
1279 found++;
1280 }
1281
1282 if (found == 0)
1283 fprintf (logfile, "No objects have the name %s!\n\n", name);
1284 }
1285
1286 /*
1287 * Builds up the lists of artifacts from the file in the libdir.
1288 */
1289 void
1290 init_artifacts (void)
1291 {
1292 static int has_been_inited = 0;
1293 char filename[MAX_BUF];
1294 artifact *art = NULL;
1295 artifactlist *al;
1296
1297 if (has_been_inited)
1298 return;
1299 else
1300 has_been_inited = 1;
1301
1302 sprintf (filename, "%s/artifacts", settings.datadir);
1303 object_thawer f (filename);
1304
1305 if (!f)
1306 return;
1307
1308 f.next ();
1309
1310 for (;;)
1311 {
1312 switch (f.kw)
1313 {
1314 case KW_allowed:
1315 if (!art)
1316 art = get_empty_artifact ();
1317
1318 {
1319 if (!strcmp (f.get_str (), "all"))
1320 break;
1321
1322 char *next, *cp = f.get_str ();
1323
1324 do
1325 {
1326 if ((next = strchr (cp, ',')))
1327 *next++ = '\0';
1328
1329 linked_char *tmp = new linked_char;
1330
1331 tmp->name = cp;
1332 tmp->next = art->allowed;
1333 art->allowed = tmp;
1334 }
1335 while ((cp = next));
1336 }
1337 break;
1338
1339 case KW_chance:
1340 f.get (art->chance);
1341 break;
1342
1343 case KW_difficulty:
1344 f.get (art->difficulty);
1345 break;
1346
1347 case KW_object:
1348 {
1349 art->item = object::create ();
1350 f.get (art->item->name);
1351 f.next ();
1352
1353 if (!art->item->parse_kv (f))
1354 LOG (llevError, "Init_Artifacts: Could not load object.\n");
1355
1356 al = find_artifactlist (art->item->type);
1357
1358 if (!al)
1359 {
1360 al = get_empty_artifactlist ();
1361 al->type = art->item->type;
1362 al->next = first_artifactlist;
1363 first_artifactlist = al;
1364 }
1365
1366 art->next = al->items;
1367 al->items = art;
1368 art = 0;
1369 }
1370 continue;
1371
1372 case KW_EOF:
1373 goto done;
1374
1375 default:
1376 if (!f.parse_error ("artifacts file"))
1377 cleanup ("artifacts file required");
1378 break;
1379 }
1380
1381 f.next ();
1382 }
1383
1384 done:
1385 for (al = first_artifactlist; al; al = al->next)
1386 {
1387 al->total_chance = 0;
1388
1389 for (art = al->items; art; art = art->next)
1390 {
1391 if (!art->chance)
1392 LOG (llevError, "Warning: artifact with no chance: %s\n", &art->item->name);
1393 else
1394 al->total_chance += art->chance;
1395 }
1396 #if 0
1397 LOG (llevDebug, "Artifact list type %d has %d total chance\n", al->type, al->total_chance);
1398 #endif
1399 }
1400
1401 LOG (llevDebug, "done.\n");
1402 }
1403
1404 /*
1405 * Used in artifact generation. The bonuses of the first object
1406 * is modified by the bonuses of the second object.
1407 */
1408 void
1409 add_abilities (object *op, object *change)
1410 {
1411 int i, tmp;
1412
1413 if (change->face != blank_face)
1414 {
1415 #ifdef TREASURE_VERBOSE
1416 LOG (llevDebug, "add_abilities change face: %d\n", change->face);
1417 #endif
1418 op->face = change->face;
1419 }
1420
1421 for (i = 0; i < NUM_STATS; i++)
1422 change_attr_value (&(op->stats), i, change->stats.stat (i));
1423
1424 op->attacktype |= change->attacktype;
1425 op->path_attuned |= change->path_attuned;
1426 op->path_repelled |= change->path_repelled;
1427 op->path_denied |= change->path_denied;
1428 op->move_type |= change->move_type;
1429 op->stats.luck += change->stats.luck;
1430
1431 if (QUERY_FLAG (change, FLAG_CURSED))
1432 SET_FLAG (op, FLAG_CURSED);
1433 if (QUERY_FLAG (change, FLAG_DAMNED))
1434 SET_FLAG (op, FLAG_DAMNED);
1435 if ((QUERY_FLAG (change, FLAG_CURSED) || QUERY_FLAG (change, FLAG_DAMNED)) && op->magic > 0)
1436 set_abs_magic (op, -op->magic);
1437
1438 if (QUERY_FLAG (change, FLAG_LIFESAVE))
1439 SET_FLAG (op, FLAG_LIFESAVE);
1440 if (QUERY_FLAG (change, FLAG_REFL_SPELL))
1441 SET_FLAG (op, FLAG_REFL_SPELL);
1442 if (QUERY_FLAG (change, FLAG_STEALTH))
1443 SET_FLAG (op, FLAG_STEALTH);
1444 if (QUERY_FLAG (change, FLAG_XRAYS))
1445 SET_FLAG (op, FLAG_XRAYS);
1446 if (QUERY_FLAG (change, FLAG_BLIND))
1447 SET_FLAG (op, FLAG_BLIND);
1448 if (QUERY_FLAG (change, FLAG_SEE_IN_DARK))
1449 SET_FLAG (op, FLAG_SEE_IN_DARK);
1450 if (QUERY_FLAG (change, FLAG_REFL_MISSILE))
1451 SET_FLAG (op, FLAG_REFL_MISSILE);
1452 if (QUERY_FLAG (change, FLAG_MAKE_INVIS))
1453 SET_FLAG (op, FLAG_MAKE_INVIS);
1454
1455 if (QUERY_FLAG (change, FLAG_STAND_STILL))
1456 {
1457 CLEAR_FLAG (op, FLAG_ANIMATE);
1458 /* so artifacts will join */
1459 if (!QUERY_FLAG (op, FLAG_ALIVE))
1460 op->speed = 0.0;
1461
1462 op->set_speed (op->speed);
1463 }
1464
1465 if (change->nrof)
1466 op->nrof = rndm (change->nrof) + 1;
1467
1468 op->stats.exp += change->stats.exp; /* Speed modifier */
1469 op->stats.wc += change->stats.wc;
1470 op->stats.ac += change->stats.ac;
1471
1472 if (change->other_arch)
1473 {
1474 /* Basically, for horns & potions, the other_arch field is the spell
1475 * to cast. So convert that to into a spell and put it into
1476 * this object.
1477 */
1478 if (op->type == HORN || op->type == POTION)
1479 {
1480 object *tmp_obj;
1481
1482 /* Remove any spells this object currently has in it */
1483 while (op->inv)
1484 op->inv->destroy ();
1485
1486 tmp_obj = arch_to_object (change->other_arch);
1487 insert_ob_in_ob (tmp_obj, op);
1488 }
1489 /* No harm setting this for potions/horns */
1490 op->other_arch = change->other_arch;
1491 }
1492
1493 if (change->stats.hp < 0)
1494 op->stats.hp = -change->stats.hp;
1495 else
1496 op->stats.hp += change->stats.hp;
1497
1498 if (change->stats.maxhp < 0)
1499 op->stats.maxhp = -change->stats.maxhp;
1500 else
1501 op->stats.maxhp += change->stats.maxhp;
1502
1503 if (change->stats.sp < 0)
1504 op->stats.sp = -change->stats.sp;
1505 else
1506 op->stats.sp += change->stats.sp;
1507
1508 if (change->stats.maxsp < 0)
1509 op->stats.maxsp = -change->stats.maxsp;
1510 else
1511 op->stats.maxsp += change->stats.maxsp;
1512
1513 if (change->stats.food < 0)
1514 op->stats.food = -(change->stats.food);
1515 else
1516 op->stats.food += change->stats.food;
1517
1518 if (change->level < 0)
1519 op->level = -(change->level);
1520 else
1521 op->level += change->level;
1522
1523 if (change->gen_sp_armour < 0)
1524 op->gen_sp_armour = -(change->gen_sp_armour);
1525 else
1526 op->gen_sp_armour = (op->gen_sp_armour * (change->gen_sp_armour)) / 100;
1527
1528 op->item_power = change->item_power;
1529
1530 for (i = 0; i < NROFATTACKS; i++)
1531 if (change->resist[i])
1532 op->resist[i] += change->resist[i];
1533
1534 if (change->stats.dam)
1535 {
1536 if (change->stats.dam < 0)
1537 op->stats.dam = (-change->stats.dam);
1538 else if (op->stats.dam)
1539 {
1540 tmp = (signed char) (((int) op->stats.dam * (int) change->stats.dam) / 10);
1541 if (tmp == op->stats.dam)
1542 {
1543 if (change->stats.dam < 10)
1544 op->stats.dam--;
1545 else
1546 op->stats.dam++;
1547 }
1548 else
1549 op->stats.dam = tmp;
1550 }
1551 }
1552
1553 if (change->weight)
1554 {
1555 if (change->weight < 0)
1556 op->weight = (-change->weight);
1557 else
1558 op->weight = (op->weight * (change->weight)) / 100;
1559 }
1560
1561 if (change->last_sp)
1562 {
1563 if (change->last_sp < 0)
1564 op->last_sp = (-change->last_sp);
1565 else
1566 op->last_sp = (signed char) (((int) op->last_sp * (int) change->last_sp) / (int) 100);
1567 }
1568
1569 if (change->gen_sp_armour)
1570 {
1571 if (change->gen_sp_armour < 0)
1572 op->gen_sp_armour = (-change->gen_sp_armour);
1573 else
1574 op->gen_sp_armour = (signed char) (((int) op->gen_sp_armour * ((int) change->gen_sp_armour)) / (int) 100);
1575 }
1576
1577 op->value *= change->value;
1578
1579 if (change->materials)
1580 op->materials = change->materials;
1581
1582 if (change->materialname)
1583 op->materialname = change->materialname;
1584
1585 if (change->slaying)
1586 op->slaying = change->slaying;
1587
1588 if (change->race)
1589 op->race = change->race;
1590
1591 if (change->msg)
1592 op->msg = change->msg;
1593 }
1594
1595 static int
1596 legal_artifact_combination (object *op, artifact *art)
1597 {
1598 int neg, success = 0;
1599 linked_char *tmp;
1600 const char *name;
1601
1602 if (!art->allowed)
1603 return 1; /* Ie, "all" */
1604
1605 for (tmp = art->allowed; tmp; tmp = tmp->next)
1606 {
1607 #ifdef TREASURE_VERBOSE
1608 LOG (llevDebug, "legal_art: %s\n", &tmp->name);
1609 #endif
1610 if (*tmp->name == '!')
1611 name = tmp->name + 1, neg = 1;
1612 else
1613 name = tmp->name, neg = 0;
1614
1615 /* If we match name, then return the opposite of 'neg' */
1616 if (!strcmp (name, op->name) || (op->arch && !strcmp (name, op->arch->archname)))
1617 return !neg;
1618
1619 /* Set success as true, since if the match was an inverse, it means
1620 * everything is allowed except what we match
1621 */
1622 else if (neg)
1623 success = 1;
1624 }
1625
1626 return success;
1627 }
1628
1629 /*
1630 * Fixes the given object, giving it the abilities and titles
1631 * it should have due to the second artifact-template.
1632 */
1633
1634 void
1635 give_artifact_abilities (object *op, object *artifct)
1636 {
1637 char new_name[MAX_BUF];
1638
1639 sprintf (new_name, "of %s", &artifct->name);
1640 op->title = new_name;
1641 add_abilities (op, artifct); /* Give out the bonuses */
1642
1643 #if 0 /* Bit verbose, but keep it here until next time I need it... */
1644 {
1645 char identified = QUERY_FLAG (op, FLAG_IDENTIFIED);
1646
1647 SET_FLAG (op, FLAG_IDENTIFIED);
1648 LOG (llevDebug, "Generated artifact %s %s [%s]\n", op->name, op->title, describe_item (op, NULL));
1649 if (!identified)
1650 CLEAR_FLAG (op, FLAG_IDENTIFIED);
1651 }
1652 #endif
1653 return;
1654 }
1655
1656 /*
1657 * Decides randomly which artifact the object should be
1658 * turned into. Makes sure that the item can become that
1659 * artifact (means magic, difficulty, and Allowed fields properly).
1660 * Then calls give_artifact_abilities in order to actually create
1661 * the artifact.
1662 */
1663
1664 /* Give 1 re-roll attempt per artifact */
1665 #define ARTIFACT_TRIES 2
1666
1667 void
1668 generate_artifact (object *op, int difficulty)
1669 {
1670 artifactlist *al;
1671 artifact *art;
1672 int i;
1673
1674 al = find_artifactlist (op->type);
1675
1676 if (al == NULL)
1677 {
1678 #if 0 /* This is too verbose, usually */
1679 LOG (llevDebug, "Couldn't change %s into artifact - no table.\n", op->name);
1680 #endif
1681 return;
1682 }
1683
1684 for (i = 0; i < ARTIFACT_TRIES; i++)
1685 {
1686 int roll = rndm (al->total_chance);
1687
1688 for (art = al->items; art; art = art->next)
1689 {
1690 roll -= art->chance;
1691 if (roll < 0)
1692 break;
1693 }
1694
1695 if (art == NULL || roll >= 0)
1696 {
1697 #if 1
1698 LOG (llevError, "Got null entry and non zero roll in generate_artifact, type %d\n", op->type);
1699 #endif
1700 return;
1701 }
1702 if (!strcmp (art->item->name, "NONE"))
1703 return;
1704 if (FABS (op->magic) < art->item->magic)
1705 continue; /* Not magic enough to be this item */
1706
1707 /* Map difficulty not high enough */
1708 if (difficulty < art->difficulty)
1709 continue;
1710
1711 if (!legal_artifact_combination (op, art))
1712 {
1713 #ifdef TREASURE_VERBOSE
1714 LOG (llevDebug, "%s of %s was not a legal combination.\n", &op->name, &art->item->name);
1715 #endif
1716 continue;
1717 }
1718
1719 give_artifact_abilities (op, art->item);
1720 return;
1721 }
1722 }
1723
1724 /* fix_flesh_item() - objects of type FLESH are similar to type
1725 * FOOD, except they inherit properties (name, food value, etc).
1726 * based on the original owner (or 'donor' if you like). -b.t.
1727 */
1728
1729 void
1730 fix_flesh_item (object *item, object *donor)
1731 {
1732 char tmpbuf[MAX_BUF];
1733 int i;
1734
1735 if (item->type == FLESH && donor)
1736 {
1737 /* change the name */
1738 sprintf (tmpbuf, "%s's %s", &donor->name, &item->name);
1739 item->name = tmpbuf;
1740 sprintf (tmpbuf, "%s's %s", &donor->name, &item->name_pl);
1741 item->name_pl = tmpbuf;
1742
1743 /* weight is FLESH weight/100 * donor */
1744 if ((item->weight = (signed long) (((double) item->weight / (double) 100.0) * (double) donor->weight)) == 0)
1745 item->weight = 1;
1746
1747 /* value is multiplied by level of donor */
1748 item->value *= isqrt (donor->level * 2);
1749
1750 /* food value */
1751 item->stats.food += (donor->stats.hp / 100) + donor->stats.Con;
1752
1753 /* flesh items inherit some abilities of donor, but not
1754 * full effect.
1755 */
1756 for (i = 0; i < NROFATTACKS; i++)
1757 item->resist[i] = donor->resist[i] / 2;
1758
1759 /* item inherits donor's level (important for quezals) */
1760 item->level = donor->level;
1761
1762 /* if donor has some attacktypes, the flesh is poisonous */
1763 if (donor->attacktype & AT_POISON)
1764 item->type = POISON;
1765 if (donor->attacktype & AT_ACID)
1766 item->stats.hp = -1 * item->stats.food;
1767 SET_FLAG (item, FLAG_NO_STEAL);
1768 }
1769 }
1770
1771 /* special_potion() - so that old potion code is still done right. */
1772 int
1773 special_potion (object *op)
1774 {
1775 if (op->attacktype)
1776 return 1;
1777
1778 if (op->stats.Str || op->stats.Dex || op->stats.Con || op->stats.Pow || op->stats.Wis || op->stats.Int || op->stats.Cha)
1779 return 1;
1780
1781 for (int i = 0; i < NROFATTACKS; i++)
1782 if (op->resist[i])
1783 return 1;
1784
1785 return 0;
1786 }
1787
1788 void
1789 free_treasurestruct (treasure *t)
1790 {
1791 if (t->next) free_treasurestruct (t->next);
1792 if (t->next_yes) free_treasurestruct (t->next_yes);
1793 if (t->next_no) free_treasurestruct (t->next_no);
1794
1795 delete t;
1796 }
1797
1798 void
1799 free_charlinks (linked_char *lc)
1800 {
1801 if (lc->next)
1802 free_charlinks (lc->next);
1803
1804 delete lc;
1805 }
1806
1807 void
1808 free_artifact (artifact *at)
1809 {
1810 if (at->next) free_artifact (at->next);
1811 if (at->allowed) free_charlinks (at->allowed);
1812
1813 at->item->destroy (1);
1814
1815 sfree (at);
1816 }
1817
1818 void
1819 free_artifactlist (artifactlist *al)
1820 {
1821 artifactlist *nextal;
1822
1823 for (al = first_artifactlist; al; al = nextal)
1824 {
1825 nextal = al->next;
1826
1827 if (al->items)
1828 free_artifact (al->items);
1829
1830 sfree (al);
1831 }
1832 }
1833
1834 void
1835 free_all_treasures (void)
1836 {
1837 treasurelist *tl, *next;
1838
1839 for (tl = first_treasurelist; tl; tl = next)
1840 {
1841 clear (tl);
1842
1843 next = tl->next;
1844 delete tl;
1845 }
1846
1847 free_artifactlist (first_artifactlist);
1848 }