ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/treasure.C
Revision: 1.30
Committed: Wed Jan 3 02:30:51 2007 UTC (17 years, 4 months ago) by elmex
Content type: text/plain
Branch: MAIN
Changes since 1.29: +33 -38 lines
Log Message:
implemented proper support for empty treasures, which
sadly occur in empty treasure lists. fixing treasurelists
to have no entries at all would be even more complicated,
but even when this is fixed, the current changes only make the
server more crash robust to bad treasures.
Also removed the 'NONE' specialcase for treasure lists. Developers
should use 'none' instead now.

File Contents

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