00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00036 #define ALLOWED_COMBINATION
00037
00044 #define TREASURE_DEBUG
00045
00046
00047
00048
00049 #include <stdlib.h>
00050 #include <global.h>
00051 #include <treasure.h>
00052 #include <loader.h>
00053 #include <sproto.h>
00054
00055
00056 static void change_treasure(treasure *t, object *op);
00057 static int special_potion(object *op);
00058 static void fix_flesh_item(object *item, object *donor);
00059
00060 extern const char *const spell_mapping[];
00061 int artifact_init;
00066 void init_archetype_pointers(void) {
00067 int prev_warn = warn_archetypes;
00068
00069 warn_archetypes = 1;
00070 if (ring_arch == NULL)
00071 ring_arch = find_archetype("ring");
00072 if (amulet_arch == NULL)
00073 amulet_arch = find_archetype("amulet");
00074 if (staff_arch == NULL)
00075 staff_arch = find_archetype("staff");
00076 if (crown_arch == NULL)
00077 crown_arch = find_archetype("crown");
00078 warn_archetypes = prev_warn;
00079 }
00080
00091 static treasurelist *get_empty_treasurelist(void) {
00092 treasurelist *tl = (treasurelist *)malloc(sizeof(treasurelist));
00093 if (tl == NULL)
00094 fatal(OUT_OF_MEMORY);
00095 memset(tl, 0, sizeof(treasurelist));
00096 return tl;
00097 }
00098
00109 static treasure *get_empty_treasure(void) {
00110 treasure *t = (treasure *)calloc(1, sizeof(treasure));
00111 if (t == NULL)
00112 fatal(OUT_OF_MEMORY);
00113 t->item = NULL;
00114 t->name = NULL;
00115 t->next = NULL;
00116 t->next_yes = NULL;
00117 t->next_no = NULL;
00118 t->chance = 100;
00119 t->magic = 0;
00120 t->nrof = 0;
00121 return t;
00122 }
00123
00138 static treasure *load_treasure(FILE *fp, int *line) {
00139 char buf[MAX_BUF], *cp, variable[MAX_BUF];
00140 treasure *t = get_empty_treasure();
00141 int value;
00142
00143 nroftreasures++;
00144 while (fgets(buf, MAX_BUF, fp) != NULL) {
00145 (*line)++;
00146
00147 if (*buf == '#')
00148 continue;
00149 if ((cp = strchr(buf, '\n')) != NULL)
00150 *cp = '\0';
00151 cp = buf;
00152 while (isspace(*cp))
00153 cp++;
00154
00155 if (sscanf(cp, "arch %s", variable)) {
00156 if ((t->item = find_archetype(variable)) == NULL)
00157 LOG(llevError, "Treasure lacks archetype: %s\n", variable);
00158 } else if (sscanf(cp, "list %s", variable))
00159 t->name = add_string(variable);
00160 else if (sscanf(cp, "change_name %s", variable))
00161 t->change_arch.name = add_string(variable);
00162 else if (sscanf(cp, "change_title %s", variable))
00163 t->change_arch.title = add_string(variable);
00164 else if (sscanf(cp, "change_slaying %s", variable))
00165 t->change_arch.slaying = add_string(variable);
00166 else if (sscanf(cp, "chance %d", &value))
00167 t->chance = (uint8)value;
00168 else if (sscanf(cp, "nrof %d", &value))
00169 t->nrof = (uint16)value;
00170 else if (sscanf(cp, "magic %d", &value))
00171 t->magic = (uint8)value;
00172 else if (!strcmp(cp, "yes"))
00173 t->next_yes = load_treasure(fp, line);
00174 else if (!strcmp(cp, "no"))
00175 t->next_no = load_treasure(fp, line);
00176 else if (!strcmp(cp, "end"))
00177 return t;
00178 else if (!strcmp(cp, "more")) {
00179 t->next = load_treasure(fp, line);
00180 return t;
00181 } else
00182 LOG(llevError, "Unknown treasure-command: '%s', last entry %s, line %d\n", cp, t->name ? t->name : "null", *line);
00183 }
00184 LOG(llevError, "treasure lacks 'end'.\n");
00185 return t;
00186 }
00187
00188 #ifdef TREASURE_DEBUG
00189
00200 static void check_treasurelist(const treasure *t, const treasurelist *tl) {
00201 if (t->item == NULL && t->name == NULL)
00202 LOG(llevError, "Treasurelist %s has element with no name or archetype\n", tl->name);
00203 if (t->chance >= 100 && t->next_yes && (t->next || t->next_no))
00204 LOG(llevError, "Treasurelist %s has element that has 100%% generation, next_yes field as well as next or next_no\n", tl->name);
00205
00206 if (t->name && strcmp(t->name, "NONE"))
00207 find_treasurelist(t->name);
00208 if (t->next)
00209 check_treasurelist(t->next, tl);
00210 if (t->next_yes)
00211 check_treasurelist(t->next_yes, tl);
00212 if (t->next_no)
00213 check_treasurelist(t->next_no, tl);
00214 }
00215 #endif
00216
00224 void load_treasures(void) {
00225 FILE *fp;
00226 char filename[MAX_BUF], buf[MAX_BUF], name[MAX_BUF];
00227 treasurelist *previous = NULL;
00228 treasure *t;
00229 int comp, line = 0;
00230
00231 snprintf(filename, sizeof(filename), "%s/%s", settings.datadir, settings.treasures);
00232 if ((fp = open_and_uncompress(filename, 0, &comp)) == NULL) {
00233 LOG(llevError, "Can't open treasure file.\n");
00234 return;
00235 }
00236 while (fgets(buf, MAX_BUF, fp) != NULL) {
00237 line++;
00238 if (*buf == '#')
00239 continue;
00240
00241 if (sscanf(buf, "treasureone %s\n", name) || sscanf(buf, "treasure %s\n", name)) {
00242 treasurelist *tl = get_empty_treasurelist();
00243
00244 tl->name = add_string(name);
00245 if (previous == NULL)
00246 first_treasurelist = tl;
00247 else
00248 previous->next = tl;
00249 previous = tl;
00250 tl->items = load_treasure(fp, &line);
00251
00252
00253
00254
00255
00256 if (!strncmp(buf, "treasureone", 11)) {
00257 for (t = tl->items; t != NULL; t = t->next) {
00258 #ifdef TREASURE_DEBUG
00259 if (t->next_yes || t->next_no) {
00260 LOG(llevError, "Treasure %s is one item, but on treasure %s\n", tl->name, t->item ? t->item->name : t->name);
00261 LOG(llevError, " the next_yes or next_no field is set\n");
00262 }
00263 #endif
00264 tl->total_chance += t->chance;
00265 }
00266 }
00267 } else
00268 LOG(llevError, "Treasure-list didn't understand: %s, line %d\n", buf, line);
00269 }
00270 close_and_delete(fp, comp);
00271
00272 #ifdef TREASURE_DEBUG
00273
00274
00275
00276
00277
00278 for (previous = first_treasurelist; previous != NULL; previous = previous->next)
00279 check_treasurelist(previous->items, previous);
00280 #endif
00281 }
00282
00295 treasurelist *find_treasurelist(const char *name) {
00296 const char *tmp = find_string(name);
00297 treasurelist *tl;
00298
00299
00300
00301
00302
00303
00304 if (!strcmp(name, "none") || (!first_treasurelist))
00305 return NULL;
00306 if (tmp != NULL)
00307 for (tl = first_treasurelist; tl != NULL; tl = tl->next)
00308 if (tmp == tl->name)
00309 return tl;
00310 LOG(llevError, "Couldn't find treasurelist %s\n", name);
00311 return NULL;
00312 }
00313
00314
00326 static void put_treasure(object *op, object *creator, int flags) {
00327
00328
00329
00330
00331
00332 if (flags>_ENVIRONMENT && op->type != SPELL) {
00333 op->x = creator->x;
00334 op->y = creator->y;
00335 SET_FLAG(op, FLAG_OBJ_ORIGINAL);
00336 insert_ob_in_map(op, creator->map, op, INS_NO_MERGE|INS_NO_WALK_ON);
00337 } else {
00338 op = insert_ob_in_ob(op, creator);
00339 if ((flags>_APPLY) && QUERY_FLAG(creator, FLAG_MONSTER))
00340 monster_check_apply(creator, op);
00341 }
00342 }
00343
00354 static void change_treasure(treasure *t, object *op) {
00355
00356 if (t->change_arch.name) {
00357 FREE_AND_COPY(op->name, t->change_arch.name);
00358
00359 FREE_AND_COPY(op->name_pl, t->change_arch.name);
00360 }
00361
00362 if (t->change_arch.title) {
00363 if (op->title)
00364 free_string(op->title);
00365 op->title = add_string(t->change_arch.title);
00366 }
00367
00368 if (t->change_arch.slaying) {
00369 if (op->slaying)
00370 free_string(op->slaying);
00371 op->slaying = add_string(t->change_arch.slaying);
00372 }
00373 }
00374
00390 static void create_all_treasures(treasure *t, object *op, int flag, int difficulty, int tries) {
00391 object *tmp;
00392
00393
00394 if ((int)t->chance >= 100 || (RANDOM()%100+1) < (int)t->chance) {
00395 if (t->name) {
00396 if (strcmp(t->name, "NONE") && difficulty >= t->magic)
00397 create_treasure(find_treasurelist(t->name), op, flag, difficulty, tries);
00398 } else {
00399 if (t->item->clone.invisible != 0 || !(flag>_INVISIBLE)) {
00400 tmp = arch_to_object(t->item);
00401 if (t->nrof && tmp->nrof <= 1)
00402 tmp->nrof = RANDOM()%((int)t->nrof)+1;
00403 fix_generated_item(tmp, op, difficulty, t->magic, flag);
00404 change_treasure(t, tmp);
00405 put_treasure(tmp, op, flag);
00406 }
00407 }
00408 if (t->next_yes != NULL)
00409 create_all_treasures(t->next_yes, op, flag, difficulty, tries);
00410 } else
00411 if (t->next_no != NULL)
00412 create_all_treasures(t->next_no, op, flag, difficulty, tries);
00413 if (t->next != NULL)
00414 create_all_treasures(t->next, op, flag, difficulty, tries);
00415 }
00416
00435 static void create_one_treasure(treasurelist *tl, object *op, int flag, int difficulty, int tries) {
00436 int value = RANDOM()%tl->total_chance;
00437 treasure *t;
00438
00439 if (tries++ > 100) {
00440 LOG(llevDebug, "create_one_treasure: tries exceeded 100, returning without making treasure\n");
00441 return;
00442 }
00443
00444 for (t = tl->items; t != NULL; t = t->next) {
00445 value -= t->chance;
00446 if (value < 0)
00447 break;
00448 }
00449
00450 if (!t || value >= 0) {
00451 LOG(llevError, "create_one_treasure: got null object or not able to find treasure\n");
00452 abort();
00453 return;
00454 }
00455 if (t->name) {
00456 if (!strcmp(t->name, "NONE"))
00457 return;
00458 if (difficulty >= t->magic)
00459 create_treasure(find_treasurelist(t->name), op, flag, difficulty, tries);
00460 else if (t->nrof)
00461 create_one_treasure(tl, op, flag, difficulty, tries);
00462 return;
00463 }
00464 if ((t->item) && (flag>_ONLY_GOOD)) {
00465 if (QUERY_FLAG(&(t->item->clone), FLAG_CURSED)
00466 || QUERY_FLAG(&(t->item->clone), FLAG_DAMNED)) {
00467 create_one_treasure(tl, op, flag, difficulty, tries+1);
00468 return;
00469 }
00470 }
00471 if ((t->item && t->item->clone.invisible != 0) || flag != GT_INVISIBLE) {
00472 object *tmp = arch_to_object(t->item);
00473
00474 if (!tmp)
00475 return;
00476 if (t->nrof && tmp->nrof <= 1)
00477 tmp->nrof = RANDOM()%((int)t->nrof)+1;
00478 fix_generated_item(tmp, op, difficulty, t->magic, flag);
00479 change_treasure(t, tmp);
00480 put_treasure(tmp, op, flag);
00481 }
00482 }
00483
00499 void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries) {
00500 if (tries++ > 100) {
00501 LOG(llevDebug, "createtreasure: tries exceeded 100, returning without making treasure\n");
00502 return;
00503 }
00504 if (t->total_chance)
00505 create_one_treasure(t, op, flag, difficulty, tries);
00506 else
00507 create_all_treasures(t->items, op, flag, difficulty, tries);
00508 }
00509
00524 object *generate_treasure(treasurelist *t, int difficulty) {
00525 object *ob = get_object(), *tmp;
00526
00527 create_treasure(t, ob, 0, difficulty, 0);
00528
00529
00530 tmp = ob->inv;
00531 if (tmp != NULL)
00532 remove_ob(tmp);
00533 if (ob->inv) {
00534 LOG(llevError, "In generate treasure, created multiple objects.\n");
00535 }
00536 free_object(ob);
00537 return tmp;
00538 }
00539
00554 static int level_for_item(const object *op, int difficulty, int retmult) {
00555 int level, mult, olevel;
00556
00557 mult = 0;
00558 if (!op->inv) {
00559 LOG(llevError, "level_for_item: Object %s has no inventory!\n", op->name);
00560 return 0;
00561 }
00562 level = op->inv->level;
00563
00564
00565
00566
00567
00568 mult = op->inv->dam_modifier;
00569 if (op->inv->range_modifier && (op->inv->range_modifier < mult || mult == 0))
00570 mult = op->inv->range_modifier;
00571 if (op->inv->duration_modifier && (op->inv->duration_modifier < mult || mult == 0))
00572 mult = op->inv->duration_modifier;
00573
00574 if (mult == 0)
00575 mult = 5;
00576
00577 if (retmult)
00578 return mult;
00579
00580 olevel = mult*rndm(0, difficulty)+level;
00581 if (olevel > MAX_SPELLITEM_LEVEL)
00582 olevel = MAX_SPELLITEM_LEVEL;
00583
00584 return olevel;
00585 }
00586
00594 static const int difftomagic_list[DIFFLEVELS][MAXMAGIC+1] = {
00595
00596
00597 { 94, 3, 2, 1, 0 },
00598 { 94, 3, 2, 1, 0 },
00599 { 94, 3, 2, 1, 0 },
00600 { 94, 3, 2, 1, 0 },
00601 { 94, 3, 2, 1, 0 },
00602 { 90, 4, 3, 2, 1 },
00603 { 90, 4, 3, 2, 1 },
00604 { 90, 4, 3, 2, 1 },
00605 { 90, 4, 3, 2, 1 },
00606 { 90, 4, 3, 2, 1 },
00607 { 85, 6, 4, 3, 2 },
00608 { 85, 6, 4, 3, 2 },
00609 { 85, 6, 4, 3, 2 },
00610 { 85, 6, 4, 3, 2 },
00611 { 85, 6, 4, 3, 2 },
00612 { 81, 8, 5, 4, 3 },
00613 { 81, 8, 5, 4, 3 },
00614 { 81, 8, 5, 4, 3 },
00615 { 81, 8, 5, 4, 3 },
00616 { 81, 8, 5, 4, 3 },
00617 { 75, 10, 6, 5, 4 },
00618 { 75, 10, 6, 5, 4 },
00619 { 75, 10, 6, 5, 4 },
00620 { 75, 10, 6, 5, 4 },
00621 { 75, 10, 6, 5, 4 },
00622 { 70, 12, 7, 6, 5 },
00623 { 70, 12, 7, 6, 5 },
00624 { 70, 12, 7, 6, 5 },
00625 { 70, 12, 7, 6, 5 },
00626 { 70, 12, 7, 6, 5 },
00627 { 70, 9, 8, 7, 6 },
00628 { 70, 9, 8, 7, 6 },
00629 { 70, 9, 8, 7, 6 },
00630 { 70, 9, 8, 7, 6 },
00631 { 70, 9, 8, 7, 6 },
00632 { 70, 6, 9, 8, 7 },
00633 { 70, 6, 9, 8, 7 },
00634 { 70, 6, 9, 8, 7 },
00635 { 70, 6, 9, 8, 7 },
00636 { 70, 6, 9, 8, 7 },
00637 { 70, 3, 10, 9, 8 },
00638 { 70, 3, 10, 9, 8 },
00639 { 70, 3, 10, 9, 8 },
00640 { 70, 3, 10, 9, 8 },
00641 { 70, 3, 10, 9, 8 },
00642 { 70, 2, 9, 10, 9 },
00643 { 70, 2, 9, 10, 9 },
00644 { 70, 2, 9, 10, 9 },
00645 { 70, 2, 9, 10, 9 },
00646 { 70, 2, 9, 10, 9 },
00647 { 70, 2, 7, 11, 10 },
00648 { 70, 2, 7, 11, 10 },
00649 { 70, 2, 7, 11, 10 },
00650 { 70, 2, 7, 11, 10 },
00651 { 70, 2, 7, 11, 10 },
00652 { 70, 2, 5, 12, 11 },
00653 { 70, 2, 5, 12, 11 },
00654 { 70, 2, 5, 12, 11 },
00655 { 70, 2, 5, 12, 11 },
00656 { 70, 2, 5, 12, 11 },
00657 { 70, 2, 3, 13, 12 },
00658 { 70, 2, 3, 13, 12 },
00659 { 70, 2, 3, 13, 12 },
00660 { 70, 2, 3, 13, 12 },
00661 { 70, 2, 3, 13, 12 },
00662 { 70, 2, 3, 12, 13 },
00663 { 70, 2, 3, 12, 13 },
00664 { 70, 2, 3, 12, 13 },
00665 { 70, 2, 3, 12, 13 },
00666 { 70, 2, 3, 12, 13 },
00667 { 70, 2, 3, 11, 14 },
00668 { 70, 2, 3, 11, 14 },
00669 { 70, 2, 3, 11, 14 },
00670 { 70, 2, 3, 11, 14 },
00671 { 70, 2, 3, 11, 14 },
00672 { 70, 2, 3, 10, 15 },
00673 { 70, 2, 3, 10, 15 },
00674 { 70, 2, 3, 10, 15 },
00675 { 70, 2, 3, 10, 15 },
00676 { 70, 2, 3, 10, 15 },
00677 { 70, 2, 3, 9, 16 },
00678 { 70, 2, 3, 9, 16 },
00679 { 70, 2, 3, 9, 16 },
00680 { 70, 2, 3, 9, 16 },
00681 { 70, 2, 3, 9, 16 },
00682 { 70, 2, 3, 8, 17 },
00683 { 70, 2, 3, 8, 17 },
00684 { 70, 2, 3, 8, 17 },
00685 { 70, 2, 3, 8, 17 },
00686 { 70, 2, 3, 8, 17 },
00687 { 70, 2, 3, 7, 18 },
00688 { 70, 2, 3, 7, 18 },
00689 { 70, 2, 3, 7, 18 },
00690 { 70, 2, 3, 7, 18 },
00691 { 70, 2, 3, 7, 18 },
00692 { 70, 2, 3, 6, 19 },
00693 { 70, 2, 3, 6, 19 },
00694 { 70, 2, 3, 6, 19 },
00695 { 70, 2, 3, 6, 19 },
00696 { 70, 2, 3, 6, 19 },
00697 { 70, 2, 3, 6, 19 },
00698 { 70, 2, 3, 6, 19 },
00699 { 70, 2, 3, 6, 19 },
00700 { 70, 2, 3, 6, 19 },
00701 { 70, 2, 3, 6, 19 },
00702 { 70, 2, 3, 6, 19 },
00703 { 70, 2, 3, 6, 19 },
00704 { 70, 2, 3, 6, 19 },
00705 { 70, 2, 3, 6, 19 },
00706 { 70, 2, 3, 6, 19 },
00707 { 70, 2, 3, 6, 19 },
00708 { 70, 2, 3, 6, 19 },
00709 { 70, 2, 3, 6, 19 },
00710 { 70, 2, 3, 6, 19 },
00711 { 70, 2, 3, 6, 19 },
00712 { 70, 2, 3, 6, 19 },
00713 { 70, 2, 3, 6, 19 },
00714 { 70, 2, 3, 6, 19 },
00715 { 70, 2, 3, 6, 19 },
00716 { 70, 2, 3, 6, 19 },
00717 { 70, 2, 3, 6, 19 },
00718 { 70, 2, 3, 6, 19 },
00719 { 70, 2, 3, 6, 19 },
00720 { 70, 2, 3, 6, 19 },
00721 { 70, 2, 3, 6, 19 },
00722 { 70, 2, 3, 6, 19 },
00723 { 70, 2, 3, 6, 19 },
00724 { 70, 2, 3, 6, 19 },
00725 { 70, 2, 3, 6, 19 },
00726 { 70, 2, 3, 6, 19 },
00727 { 70, 2, 3, 6, 19 },
00728 { 70, 2, 3, 6, 19 },
00729 { 70, 2, 3, 6, 19 },
00730 { 70, 2, 3, 6, 19 },
00731 { 70, 2, 3, 6, 19 },
00732 { 70, 2, 3, 6, 19 },
00733 { 70, 2, 3, 6, 19 },
00734 { 70, 2, 3, 6, 19 },
00735 { 70, 2, 3, 6, 19 },
00736 { 70, 2, 3, 6, 19 },
00737 { 70, 2, 3, 6, 19 },
00738 { 70, 2, 3, 6, 19 },
00739 { 70, 2, 3, 6, 19 },
00740 { 70, 2, 3, 6, 19 },
00741 { 70, 2, 3, 6, 19 },
00742 { 70, 2, 3, 6, 19 },
00743 { 70, 2, 3, 6, 19 },
00744 { 70, 2, 3, 6, 19 },
00745 { 70, 2, 3, 6, 19 },
00746 { 70, 2, 3, 6, 19 },
00747 { 70, 2, 3, 6, 19 },
00748 { 70, 2, 3, 6, 19 },
00749 { 70, 2, 3, 6, 19 },
00750 { 70, 2, 3, 6, 19 },
00751 { 70, 2, 3, 6, 19 },
00752 { 70, 2, 3, 6, 19 },
00753 { 70, 2, 3, 6, 19 },
00754 { 70, 2, 3, 6, 19 },
00755 { 70, 2, 3, 6, 19 },
00756 { 70, 2, 3, 6, 19 },
00757 { 70, 2, 3, 6, 19 },
00758 { 70, 2, 3, 6, 19 },
00759 { 70, 2, 3, 6, 19 },
00760 { 70, 2, 3, 6, 19 },
00761 { 70, 2, 3, 6, 19 },
00762 { 70, 2, 3, 6, 19 },
00763 { 70, 2, 3, 6, 19 },
00764 { 70, 2, 3, 6, 19 },
00765 { 70, 2, 3, 6, 19 },
00766 { 70, 2, 3, 6, 19 },
00767 { 70, 2, 3, 6, 19 },
00768 { 70, 2, 3, 6, 19 },
00769 { 70, 2, 3, 6, 19 },
00770 { 70, 2, 3, 6, 19 },
00771 { 70, 2, 3, 6, 19 },
00772 { 70, 2, 3, 6, 19 },
00773 { 70, 2, 3, 6, 19 },
00774 { 70, 2, 3, 6, 19 },
00775 { 70, 2, 3, 6, 19 },
00776 { 70, 2, 3, 6, 19 },
00777 { 70, 2, 3, 6, 19 },
00778 { 70, 2, 3, 6, 19 },
00779 { 70, 2, 3, 6, 19 },
00780 { 70, 2, 3, 6, 19 },
00781 { 70, 2, 3, 6, 19 },
00782 { 70, 2, 3, 6, 19 },
00783 { 70, 2, 3, 6, 19 },
00784 { 70, 2, 3, 6, 19 },
00785 { 70, 2, 3, 6, 19 },
00786 { 70, 2, 3, 6, 19 },
00787 { 70, 2, 3, 6, 19 },
00788 { 70, 2, 3, 6, 19 },
00789 { 70, 2, 3, 6, 19 },
00790 { 70, 2, 3, 6, 19 },
00791 { 70, 2, 3, 6, 19 },
00792 { 70, 2, 3, 6, 19 },
00793 { 70, 2, 3, 6, 19 },
00794 { 70, 2, 3, 6, 19 },
00795 { 70, 2, 3, 6, 19 },
00796 { 70, 2, 3, 6, 19 },
00797 { 70, 2, 3, 6, 19 },
00798
00799 };
00800
00808 static int magic_from_difficulty(int difficulty) {
00809 int percent, loop;
00810
00811 difficulty--;
00812 if (difficulty < 0)
00813 difficulty = 0;
00814
00815 if (difficulty >= DIFFLEVELS)
00816 difficulty = DIFFLEVELS-1;
00817
00818 percent = RANDOM()%100;
00819
00820 for (loop = 0; loop < (MAXMAGIC+1); ++loop) {
00821 percent -= difftomagic_list[difficulty][loop];
00822 if (percent < 0)
00823 break;
00824 }
00825 if (loop == (MAXMAGIC+1)) {
00826 LOG(llevError, "Warning, table for difficulty %d bad.\n", difficulty);
00827 loop = 0;
00828 }
00829
00830 return (RANDOM()%3) ? loop : -loop;
00831 }
00832
00844 void set_abs_magic(object *op, int magic) {
00845 if (!magic)
00846 return;
00847
00848 op->magic = magic;
00849 if (op->arch) {
00850 if (op->type == ARMOUR)
00851 ARMOUR_SPEED(op) = (ARMOUR_SPEED(&op->arch->clone)*(100+magic*10))/100;
00852
00853 if (magic < 0 && !(RANDOM()%3))
00854 magic = (-magic);
00855 op->weight = (op->arch->clone.weight*(100-magic*10))/100;
00856 } else {
00857 if (op->type == ARMOUR)
00858 ARMOUR_SPEED(op) = (ARMOUR_SPEED(op)*(100+magic*10))/100;
00859 if (magic < 0 && !(RANDOM()%3))
00860 magic = (-magic);
00861 op->weight = (op->weight*(100-magic*10))/100;
00862 }
00863 }
00864
00880 static void set_magic(int difficulty, object *op, int max_magic, int flags) {
00881 int i;
00882
00883 i = magic_from_difficulty(difficulty);
00884 if ((flags>_ONLY_GOOD) && i < 0)
00885 i = -i;
00886 if (i > max_magic)
00887 i = max_magic;
00888 set_abs_magic(op, i);
00889 if (i < 0)
00890 SET_FLAG(op, FLAG_CURSED);
00891 }
00892
00909 static void set_ring_bonus(object *op, int bonus) {
00910 int r = RANDOM()%(bonus > 0 ? 25 : 11);
00911
00912 if (op->type == AMULET) {
00913 if (!(RANDOM()%21))
00914 r = 20+RANDOM()%2;
00915 else {
00916 if (RANDOM()&2)
00917 r = 10;
00918 else
00919 r = 11+RANDOM()%9;
00920 }
00921 }
00922
00923 switch (r) {
00924
00925
00926
00927
00928 case 0:
00929 case 1:
00930 case 2:
00931 case 3:
00932 case 4:
00933 case 5:
00934 case 6:
00935 set_attr_value(&op->stats, r, (signed char)(bonus+get_attr_value(&op->stats, r)));
00936 break;
00937
00938 case 7:
00939 op->stats.dam += bonus;
00940 break;
00941
00942 case 8:
00943 op->stats.wc += bonus;
00944 break;
00945
00946 case 9:
00947 op->stats.food += bonus;
00948 break;
00949
00950 case 10:
00951 op->stats.ac += bonus;
00952 break;
00953
00954
00955 case 11:
00956 case 12:
00957 case 13:
00958 case 14:
00959 case 15:
00960 case 16:
00961 case 17:
00962 case 18:
00963 case 19: {
00964 int b = 5+FABS(bonus), val, resist = RANDOM()%num_resist_table;
00965
00966
00967 val = 10+RANDOM()%b+RANDOM()%b+RANDOM()%b+RANDOM()%b;
00968
00969
00970
00971
00972
00973
00974 if (bonus < 0)
00975 val = 2*-val-RANDOM()%b;
00976 if (val > 35)
00977 val = 35;
00978 b = 0;
00979 while (op->resist[resist_table[resist]] != 0 && b < 4) {
00980 resist = RANDOM()%num_resist_table;
00981 }
00982 if (b == 4)
00983 return;
00984 op->resist[resist_table[resist]] = val;
00985
00986
00987
00988 break;
00989 }
00990
00991 case 20:
00992 if (op->type == AMULET) {
00993 SET_FLAG(op, FLAG_REFL_SPELL);
00994 op->value *= 11;
00995 } else {
00996 op->stats.hp = 1;
00997 op->value *= 4;
00998 }
00999 break;
01000
01001 case 21:
01002 if (op->type == AMULET) {
01003 SET_FLAG(op, FLAG_REFL_MISSILE);
01004 op->value *= 9;
01005 } else {
01006 op->stats.sp = 1;
01007 op->value *= 3;
01008 }
01009 break;
01010
01011 case 22:
01012 op->stats.exp += bonus;
01013 op->value = (op->value*2)/3;
01014 break;
01015 }
01016 if (bonus > 0)
01017 op->value *= 2*bonus;
01018 else
01019 op->value = -(op->value*2*bonus)/3;
01020 }
01021
01030 static int get_magic(int diff) {
01031 int i;
01032
01033 if (diff < 3)
01034 diff = 3;
01035 for (i = 0; i < 4; i++)
01036 if (RANDOM()%diff)
01037 return i;
01038 return 4;
01039 }
01040
01041 #define DICE2 (get_magic(2) == 2 ? 2 : 1)
01042 #define DICESPELL (RANDOM()%3+RANDOM()%3+RANDOM()%3+RANDOM()%3+RANDOM()%3)
01043
01070 void fix_generated_item(object *op, object *creator, int difficulty, int max_magic, int flags) {
01071 int was_magic = op->magic, num_enchantments = 0, save_item_power;
01072
01073 if (!creator || creator->type == op->type)
01074 creator = op;
01075
01076
01077 save_item_power = op->item_power;
01078 op->item_power = 0;
01079
01080 if (op->randomitems && op->type != SPELL) {
01081 create_treasure(op->randomitems, op, flags, difficulty, 0);
01082 if (!op->inv)
01083 LOG(llevDebug, "fix_generated_item: Unable to generate treasure for %s\n", op->name);
01084
01085 op->randomitems = NULL;
01086 }
01087
01088 if (difficulty < 1)
01089 difficulty = 1;
01090 if (!(flags>_MINIMAL)) {
01091 if (op->arch == crown_arch) {
01092 set_magic(difficulty > 25 ? 30 : difficulty+5, op, max_magic, flags);
01093 num_enchantments = calc_item_power(op, 1);
01094 generate_artifact(op, difficulty);
01095 } else {
01096 if (!op->magic && max_magic)
01097 set_magic(difficulty, op, max_magic, flags);
01098 num_enchantments = calc_item_power(op, 1);
01099 if ((!was_magic && !(RANDOM()%CHANCE_FOR_ARTIFACT))
01100 || op->type == HORN
01101 || difficulty >= 999)
01102 generate_artifact(op, difficulty);
01103 }
01104
01105
01106
01107
01108 if (op->title) {
01109
01110
01111
01112
01113
01114
01115
01116 if (save_item_power)
01117 op->item_power = save_item_power+get_power_from_ench(op->item_power);
01118 else
01119 op->item_power += get_power_from_ench(num_enchantments);
01120 } else if (save_item_power) {
01121
01122
01123
01124
01125
01126 op->item_power = save_item_power;
01127 } else {
01128
01129
01130
01131
01132
01133
01134 op->item_power = calc_item_power(op, 0);
01135 save_item_power = op->item_power;
01136
01137 }
01138 } else {
01139
01140 op->item_power = save_item_power;
01141 }
01142
01143
01144
01145 set_materialname(op, difficulty, NULL);
01146
01147 if (flags>_MINIMAL) {
01148 if (op->type == POTION)
01149
01150 if (op->stats.sp && !op->randomitems) {
01151 object *tmp;
01152
01153 tmp = create_archetype(spell_mapping[op->stats.sp]);
01154 insert_ob_in_ob(tmp, op);
01155 op->stats.sp = 0;
01156 }
01157 } else if (!op->title) {
01158 switch (op->type) {
01159 case WEAPON:
01160 case ARMOUR:
01161 case SHIELD:
01162 case HELMET:
01163 case CLOAK:
01164 if (QUERY_FLAG(op, FLAG_CURSED) && !(RANDOM()%4))
01165 set_ring_bonus(op, -DICE2);
01166 break;
01167
01168 case BRACERS:
01169 if (!(RANDOM()%(QUERY_FLAG(op, FLAG_CURSED) ? 5 : 20))) {
01170 set_ring_bonus(op, QUERY_FLAG(op, FLAG_CURSED) ? -DICE2 : DICE2);
01171 if (!QUERY_FLAG(op, FLAG_CURSED))
01172 op->value *= 3;
01173 }
01174 break;
01175
01176 case POTION: {
01177 int too_many_tries = 0, is_special = 0;
01178
01179
01180 if (op->stats.sp && !op->randomitems) {
01181 object *tmp;
01182
01183 tmp = create_archetype(spell_mapping[op->stats.sp]);
01184 insert_ob_in_ob(tmp, op);
01185 op->stats.sp = 0;
01186 }
01187
01188 while (!(is_special = special_potion(op)) && !op->inv) {
01189 generate_artifact(op, difficulty);
01190 if (too_many_tries++ > 10)
01191 break;
01192 }
01193
01194
01195
01196 if (op->inv && op->randomitems) {
01197
01198 op->value = (op->value*op->inv->value);
01199 op->level = op->inv->level/2+RANDOM()%difficulty+RANDOM()%difficulty;
01200 } else {
01201 FREE_AND_COPY(op->name, "potion");
01202 FREE_AND_COPY(op->name_pl, "potions");
01203 }
01204 if (!(flags>_ONLY_GOOD) && RANDOM()%2)
01205 SET_FLAG(op, FLAG_CURSED);
01206 break;
01207 }
01208
01209 case AMULET:
01210 if (op->arch == amulet_arch)
01211 op->value *= 5;
01212 case RING:
01213 if (op->arch == NULL) {
01214 remove_ob(op);
01215 free_object(op);
01216 op = NULL;
01217 break;
01218 }
01219 if (op->arch != ring_arch && op->arch != amulet_arch)
01220
01221 break;
01222
01223 if (!(flags>_ONLY_GOOD) && !(RANDOM()%3))
01224 SET_FLAG(op, FLAG_CURSED);
01225 set_ring_bonus(op, QUERY_FLAG(op, FLAG_CURSED) ? -DICE2 : DICE2);
01226 if (op->type != RING)
01227 break;
01228 if (!(RANDOM()%4)) {
01229 int d = (RANDOM()%2 || QUERY_FLAG(op, FLAG_CURSED)) ? -DICE2 : DICE2;
01230 if (d > 0)
01231 op->value *= 3;
01232 set_ring_bonus(op, d);
01233 if (!(RANDOM()%4)) {
01234 int d = (RANDOM()%3 || QUERY_FLAG(op, FLAG_CURSED)) ? -DICE2 : DICE2;
01235 if (d > 0)
01236 op->value *= 5;
01237 set_ring_bonus(op, d);
01238 }
01239 }
01240 if (GET_ANIM_ID(op))
01241 SET_ANIMATION(op, RANDOM()%((int)NUM_ANIMATIONS(op)));
01242 break;
01243
01244 case BOOK:
01245
01246
01247
01248
01249 if (!op->msg && RANDOM()%10) {
01250
01251 if (creator->level == 0 || QUERY_FLAG(creator, FLAG_ALIVE)) {
01252 if (op->map && op->map->difficulty)
01253 op->level = RANDOM()%(op->map->difficulty)+RANDOM()%10+1;
01254 else
01255 op->level = RANDOM()%20+1;
01256 } else
01257 op->level = RANDOM()%creator->level;
01258
01259 tailor_readable_ob(op, -1);
01260
01261 op->value *= ((op->level > 10 ? op->level : (op->level+1)/2)*((strlen(op->msg)/250)+1));
01262
01263
01264
01265
01266
01267 if (QUERY_FLAG(creator, FLAG_NO_PICK)
01268 && !QUERY_FLAG(creator, FLAG_MONSTER))
01269 SET_FLAG(op, FLAG_NO_PICK);
01270 if (creator->slaying && !op->slaying)
01271 op->slaying = add_string(creator->slaying);
01272
01273
01274 op->stats.exp = op->value > 10000 ? op->value/5 : op->value/10;
01275 }
01276 break;
01277
01278 case SPELLBOOK:
01279 op->value = op->value*op->inv->value;
01280
01281 op->level = op->inv->level;
01282 op->stats.exp = op->value;
01283
01284 if (!(flags>_ONLY_GOOD) && rndm(1, 100) <= 5) {
01285 if (rndm(1, 6) <= 1)
01286 SET_FLAG(op, FLAG_DAMNED);
01287 else
01288 SET_FLAG(op, FLAG_CURSED);
01289 } else if (rndm(1, 100) <= 1) {
01290 SET_FLAG(op, FLAG_BLESSED);
01291 }
01292 break;
01293
01294 case WAND:
01295
01296
01297
01298
01299 op->stats.food = op->inv->nrof;
01300 op->nrof = 1;
01301
01302
01303
01304
01305
01306 if (op->inv->duration_modifier
01307 || op->inv->dam_modifier
01308 || op->inv->range_modifier) {
01309 op->level = level_for_item(op, difficulty, 0);
01310 op->value = op->value*op->inv->value*(op->level+50)/(op->inv->level+50);
01311 } else {
01312 op->level = op->inv->level;
01313 op->value = op->value*op->inv->value;
01314 }
01315 break;
01316
01317 case ROD:
01318 op->level = level_for_item(op, difficulty, 0);
01319
01320
01321
01322
01323
01324
01325 op->value = op->value*op->inv->value*(op->level+50)/(op->inv->level+50);
01326
01327
01328 if (op->stats.maxhp)
01329 op->stats.maxhp *= MAX(op->inv->stats.sp, op->inv->stats.grace);
01330 else
01331 op->stats.maxhp = 2*MAX(op->inv->stats.sp, op->inv->stats.grace);
01332
01333 op->stats.hp = op->stats.maxhp;
01334 break;
01335
01336 case SCROLL:
01337 op->level = level_for_item(op, difficulty, 0);
01338 op->value = op->value*op->inv->value*(op->level+50)/(op->inv->level+50);
01339
01340 op->stats.exp = op->value/5;
01341 op->nrof = op->inv->nrof;
01342
01343 if (!(flags>_ONLY_GOOD) && rndm(1, 100) <= 20) {
01344 if (rndm(1, 6) <= 1)
01345 SET_FLAG(op, FLAG_DAMNED);
01346 else
01347 SET_FLAG(op, FLAG_CURSED);
01348 } else if (rndm(1, 100) <= 2) {
01349 SET_FLAG(op, FLAG_BLESSED);
01350 }
01351 break;
01352
01353 case RUNE:
01354 trap_adjust(op, difficulty);
01355 break;
01356
01357 case TRAP:
01358 trap_adjust(op, difficulty);
01359 break;
01360 }
01361 }
01362 if (flags>_STARTEQUIP) {
01363 if (op->nrof < 2
01364 && op->type != CONTAINER
01365 && op->type != MONEY
01366 && !QUERY_FLAG(op, FLAG_IS_THROWN))
01367 SET_FLAG(op, FLAG_STARTEQUIP);
01368 else if (op->type != MONEY)
01369 op->value = 0;
01370 }
01371
01372 if (!(flags>_ENVIRONMENT))
01373 fix_flesh_item(op, creator);
01374 }
01375
01376
01377
01378
01379
01380
01381
01382
01383
01393 static artifactlist *get_empty_artifactlist(void) {
01394 artifactlist *tl = (artifactlist *)malloc(sizeof(artifactlist));
01395 if (tl == NULL)
01396 fatal(OUT_OF_MEMORY);
01397 tl->next = NULL;
01398 tl->items = NULL;
01399 tl->total_chance = 0;
01400 return tl;
01401 }
01402
01412 static artifact *get_empty_artifact(void) {
01413 artifact *t = (artifact *)malloc(sizeof(artifact));
01414 if (t == NULL)
01415 fatal(OUT_OF_MEMORY);
01416 t->item = NULL;
01417 t->next = NULL;
01418 t->chance = 0;
01419 t->difficulty = 0;
01420 t->allowed = NULL;
01421 return t;
01422 }
01423
01431 artifactlist *find_artifactlist(int type) {
01432 artifactlist *al;
01433
01434 for (al = first_artifactlist; al != NULL; al = al->next)
01435 if (al->type == type)
01436 return al;
01437 return NULL;
01438 }
01439
01446 void dump_artifacts(void) {
01447 artifactlist *al;
01448 artifact *art;
01449 linked_char *next;
01450
01451 fprintf(logfile, "\n");
01452 for (al = first_artifactlist; al != NULL; al = al->next) {
01453 fprintf(logfile, "Artifact has type %d, total_chance=%d\n", al->type, al->total_chance);
01454 for (art = al->items; art != NULL; art = art->next) {
01455 fprintf(logfile, "Artifact %-30s Difficulty %3d Chance %5d\n", art->item->name, art->difficulty, art->chance);
01456 if (art->allowed != NULL) {
01457 fprintf(logfile, "\tAllowed combinations:");
01458 for (next = art->allowed; next != NULL; next = next->next)
01459 fprintf(logfile, "%s,", next->name);
01460 fprintf(logfile, "\n");
01461 }
01462 }
01463 }
01464 fprintf(logfile, "\n");
01465 }
01466
01470 static void dump_monster_treasure_rec(const char *name, treasure *t, int depth) {
01471 treasurelist *tl;
01472 int i;
01473
01474 if (depth > 100)
01475 return;
01476
01477 while (t != NULL) {
01478 if (t->name != NULL) {
01479 for (i = 0; i < depth; i++)
01480 fprintf(logfile, " ");
01481 fprintf(logfile, "{ (list: %s)\n", t->name);
01482 tl = find_treasurelist(t->name);
01483 dump_monster_treasure_rec(name, tl->items, depth+2);
01484 for (i = 0; i < depth; i++)
01485 fprintf(logfile, " ");
01486 fprintf(logfile, "} (end of list: %s)\n", t->name);
01487 } else {
01488 for (i = 0; i < depth; i++)
01489 fprintf(logfile, " ");
01490 if (t->item->clone.type == FLESH)
01491 fprintf(logfile, "%s's %s\n", name, t->item->clone.name);
01492 else
01493 fprintf(logfile, "%s\n", t->item->clone.name);
01494 }
01495 if (t->next_yes != NULL) {
01496 for (i = 0; i < depth; i++)
01497 fprintf(logfile, " ");
01498 fprintf(logfile, " (if yes)\n");
01499 dump_monster_treasure_rec(name, t->next_yes, depth+1);
01500 }
01501 if (t->next_no != NULL) {
01502 for (i = 0; i < depth; i++)
01503 fprintf(logfile, " ");
01504 fprintf(logfile, " (if no)\n");
01505 dump_monster_treasure_rec(name, t->next_no, depth+1);
01506 }
01507 t = t->next;
01508 }
01509 }
01510
01515 void dump_monster_treasure(const char *name) {
01516 archetype *at;
01517 int found;
01518
01519 found = 0;
01520 fprintf(logfile, "\n");
01521 for (at = first_archetype; at != NULL; at = at->next)
01522 if (!strcasecmp(at->clone.name, name) && at->clone.title == NULL) {
01523 fprintf(logfile, "treasures for %s (arch: %s)\n", at->clone.name, at->name);
01524 if (at->clone.randomitems != NULL)
01525 dump_monster_treasure_rec(at->clone.name, at->clone.randomitems->items, 1);
01526 else
01527 fprintf(logfile, "(nothing)\n");
01528 fprintf(logfile, "\n");
01529 found++;
01530 }
01531 if (found == 0)
01532 fprintf(logfile, "No objects have the name %s!\n\n", name);
01533 }
01534
01539 void init_artifacts(void) {
01540 static int has_been_inited = 0;
01541 FILE *fp;
01542 char filename[MAX_BUF], buf[HUGE_BUF], *cp, *next;
01543 artifact *art = NULL;
01544 linked_char *tmp;
01545 int value, comp;
01546 artifactlist *al;
01547 archetype dummy_archetype;
01548
01549 memset(&dummy_archetype, 0, sizeof(archetype));
01550
01551 if (has_been_inited)
01552 return;
01553 else
01554 has_been_inited = 1;
01555
01556 artifact_init = 1;
01557
01558 snprintf(filename, sizeof(filename), "%s/artifacts", settings.datadir);
01559 LOG(llevDebug, "Reading artifacts from %s...\n", filename);
01560 if ((fp = open_and_uncompress(filename, 0, &comp)) == NULL) {
01561 LOG(llevError, "Can't open %s.\n", filename);
01562 return;
01563 }
01564
01565 while (fgets(buf, HUGE_BUF, fp) != NULL) {
01566 if (*buf == '#')
01567 continue;
01568 if ((cp = strchr(buf, '\n')) != NULL)
01569 *cp = '\0';
01570 cp = buf;
01571 while (*cp == ' ')
01572 cp++;
01573 if (*cp == '\0')
01574 continue;
01575
01576 if (!strncmp(cp, "Allowed", 7)) {
01577 if (art == NULL) {
01578 art = get_empty_artifact();
01579 nrofartifacts++;
01580 }
01581
01582 cp = strchr(cp, ' ')+1;
01583 while (*(cp+strlen(cp)-1) == ' ')
01584 cp[strlen(cp)-1] = '\0';
01585
01586 if (!strcmp(cp, "all"))
01587 continue;
01588
01589 do {
01590 while (*cp == ' ')
01591 cp++;
01592 nrofallowedstr++;
01593 if ((next = strchr(cp, ',')) != NULL)
01594 *(next++) = '\0';
01595 tmp = (linked_char *)malloc(sizeof(linked_char));
01596 tmp->name = add_string(cp);
01597 tmp->next = art->allowed;
01598 art->allowed = tmp;
01599 } while ((cp = next) != NULL);
01600 } else if (sscanf(cp, "chance %d", &value))
01601 art->chance = (uint16)value;
01602 else if (sscanf(cp, "difficulty %d", &value))
01603 art->difficulty = (uint8)value;
01604 else if (!strncmp(cp, "Object", 6)) {
01605 art->item = (object *)calloc(1, sizeof(object));
01606 if (art->item == NULL) {
01607 LOG(llevError, "init_artifacts: memory allocation failure.\n");
01608 abort();
01609 }
01610 reset_object(art->item);
01611 art->item->arch = &dummy_archetype;
01612 if (!load_object(fp, art->item, LO_LINEMODE, 0))
01613 LOG(llevError, "Init_Artifacts: Could not load object.\n");
01614 art->item->arch = NULL;
01615 art->item->name = add_string((strchr(cp, ' ')+1));
01616 al = find_artifactlist(art->item->type);
01617 if (al == NULL) {
01618 al = get_empty_artifactlist();
01619 al->type = art->item->type;
01620 al->next = first_artifactlist;
01621 first_artifactlist = al;
01622 }
01623 art->next = al->items;
01624 al->items = art;
01625 art = NULL;
01626 } else
01627 LOG(llevError, "Unknown input in artifact file: %s\n", buf);
01628 }
01629
01630 close_and_delete(fp, comp);
01631
01632 for (al = first_artifactlist; al != NULL; al = al->next) {
01633 for (art = al->items; art != NULL; art = art->next) {
01634 if (!art->chance)
01635 LOG(llevError, "Warning: artifact with no chance: %s\n", art->item->name);
01636 else
01637 al->total_chance += art->chance;
01638 }
01639 #if 0
01640 LOG(llevDebug, "Artifact list type %d has %d total chance\n", al->type, al->total_chance);
01641 #endif
01642 }
01643
01644 LOG(llevDebug, "done artifacts.\n");
01645 artifact_init = 0;
01646 }
01647
01648
01653 void add_abilities(object *op, object *change) {
01654 int i, tmp;
01655
01656 if (change->face != blank_face) {
01657 #ifdef TREASURE_VERBOSE
01658 LOG(llevDebug, "FACE: %d\n", change->face->number);
01659 #endif
01660 op->face = change->face;
01661 }
01662 if (change->animation_id != 0) {
01663 op->animation_id = change->animation_id;
01664 SET_FLAG(op, FLAG_ANIMATE);
01665 animate_object(op, op->facing);
01666 }
01667
01668 for (i = 0; i < NUM_STATS; i++)
01669 change_attr_value(&(op->stats), i, get_attr_value(&(change->stats), i));
01670
01671 op->attacktype |= change->attacktype;
01672 op->path_attuned |= change->path_attuned;
01673 op->path_repelled |= change->path_repelled;
01674 op->path_denied |= change->path_denied;
01675 op->move_type |= change->move_type;
01676 op->stats.luck += change->stats.luck;
01677
01678 if (QUERY_FLAG(change, FLAG_CURSED))
01679 SET_FLAG(op, FLAG_CURSED);
01680 if (QUERY_FLAG(change, FLAG_DAMNED))
01681 SET_FLAG(op, FLAG_DAMNED);
01682 if ((QUERY_FLAG(change, FLAG_CURSED) || QUERY_FLAG(change, FLAG_DAMNED))
01683 && op->magic > 0)
01684 set_abs_magic(op, -op->magic);
01685
01686 if (QUERY_FLAG(change, FLAG_LIFESAVE))
01687 SET_FLAG(op, FLAG_LIFESAVE);
01688 if (QUERY_FLAG(change, FLAG_REFL_SPELL))
01689 SET_FLAG(op, FLAG_REFL_SPELL);
01690 if (QUERY_FLAG(change, FLAG_STEALTH))
01691 SET_FLAG(op, FLAG_STEALTH);
01692 if (QUERY_FLAG(change, FLAG_XRAYS))
01693 SET_FLAG(op, FLAG_XRAYS);
01694 if (QUERY_FLAG(change, FLAG_BLIND))
01695 SET_FLAG(op, FLAG_BLIND);
01696 if (QUERY_FLAG(change, FLAG_SEE_IN_DARK))
01697 SET_FLAG(op, FLAG_SEE_IN_DARK);
01698 if (QUERY_FLAG(change, FLAG_REFL_MISSILE))
01699 SET_FLAG(op, FLAG_REFL_MISSILE);
01700 if (QUERY_FLAG(change, FLAG_MAKE_INVIS))
01701 SET_FLAG(op, FLAG_MAKE_INVIS);
01702
01703 if (QUERY_FLAG(change, FLAG_STAND_STILL)) {
01704 CLEAR_FLAG(op, FLAG_ANIMATE);
01705
01706 if (!QUERY_FLAG(op, FLAG_ALIVE))
01707 op->speed = 0.0;
01708 update_ob_speed(op);
01709 }
01710 if (change->nrof)
01711 op->nrof = RANDOM()%((int)change->nrof)+1;
01712 op->stats.exp += change->stats.exp;
01713 op->stats.wc += change->stats.wc;
01714 op->stats.ac += change->stats.ac;
01715
01716 if (change->other_arch) {
01717
01718
01719
01720
01721 if (op->type == HORN || op->type == POTION) {
01722 object *tmp_obj;
01723
01724
01725 while (op->inv) {
01726 tmp_obj = op->inv;
01727 remove_ob(tmp_obj);
01728 free_object(tmp_obj);
01729 }
01730 tmp_obj = arch_to_object(change->other_arch);
01731 insert_ob_in_ob(tmp_obj, op);
01732 }
01733
01734 op->other_arch = change->other_arch;
01735 }
01736
01737 if (change->stats.hp < 0)
01738 op->stats.hp = -change->stats.hp;
01739 else
01740 op->stats.hp += change->stats.hp;
01741 if (change->stats.maxhp < 0)
01742 op->stats.maxhp = -change->stats.maxhp;
01743 else
01744 op->stats.maxhp += change->stats.maxhp;
01745 if (change->stats.sp < 0)
01746 op->stats.sp = -change->stats.sp;
01747 else
01748 op->stats.sp += change->stats.sp;
01749 if (change->stats.maxsp < 0)
01750 op->stats.maxsp = -change->stats.maxsp;
01751 else
01752 op->stats.maxsp += change->stats.maxsp;
01753 if (change->stats.food < 0)
01754 op->stats.food = -(change->stats.food);
01755 else
01756 op->stats.food += change->stats.food;
01757 if (change->level < 0)
01758 op->level = -(change->level);
01759 else
01760 op->level += change->level;
01761
01762 if (change->gen_sp_armour < 0)
01763 op->gen_sp_armour = -(change->gen_sp_armour);
01764 else
01765 op->gen_sp_armour = (op->gen_sp_armour*(change->gen_sp_armour))/100;
01766
01767 op->item_power = change->item_power;
01768
01769 for (i = 0; i < NROFATTACKS; i++) {
01770 if (change->resist[i]) {
01771 op->resist[i] += change->resist[i];
01772 }
01773 }
01774 if (change->stats.dam) {
01775 if (change->stats.dam < 0)
01776 op->stats.dam = (-change->stats.dam);
01777 else if (op->stats.dam) {
01778 tmp = (signed char)(((int)op->stats.dam*(int)change->stats.dam)/10);
01779 if (tmp == op->stats.dam) {
01780 if (change->stats.dam < 10)
01781 op->stats.dam--;
01782 else
01783 op->stats.dam++;
01784 } else
01785 op->stats.dam = tmp;
01786 }
01787 }
01788 if (change->weight) {
01789 if (change->weight < 0)
01790 op->weight = (-change->weight);
01791 else
01792 op->weight = (op->weight*(change->weight))/100;
01793 }
01794 if (change->last_sp) {
01795 if (change->last_sp < 0)
01796 op->last_sp = (-change->last_sp);
01797 else
01798 op->last_sp = (signed char)(((int)op->last_sp*(int)change->last_sp)/(int)100);
01799 }
01800 if (change->gen_sp_armour) {
01801 if (change->gen_sp_armour < 0)
01802 op->gen_sp_armour = (-change->gen_sp_armour);
01803 else
01804 op->gen_sp_armour = (signed char)(((int)op->gen_sp_armour*((int)change->gen_sp_armour))/(int)100);
01805 }
01806 op->value *= change->value;
01807
01808 if (change->material)
01809 op->material = change->material;
01810
01811 if (change->materialname) {
01812 if (op->materialname)
01813 free_string(op->materialname);
01814 op->materialname = add_refcount(change->materialname);
01815 }
01816
01817 if (change->slaying) {
01818 if (op->slaying)
01819 free_string(op->slaying);
01820 op->slaying = add_refcount(change->slaying);
01821 }
01822 if (change->race) {
01823 if (op->race)
01824 free_string(op->race);
01825 op->race = add_refcount(change->race);
01826 }
01827 if (change->msg) {
01828 if (op->msg)
01829 free_string(op->msg);
01830 op->msg = add_refcount(change->msg);
01831 }
01832
01833 if (change->inv) {
01834 object *inv = change->inv;
01835 object *copy;
01836
01837 while (inv) {
01838 copy = get_object();
01839 copy_object(inv, copy);
01840 insert_ob_in_ob(copy, op);
01841 inv = inv->below;
01842 }
01843 }
01844 }
01845
01849 int legal_artifact_combination(object *op, artifact *art) {
01850 int neg, success = 0;
01851 linked_char *tmp;
01852 const char *name;
01853
01854 if (art->allowed == (linked_char *)NULL)
01855 return 1;
01856 for (tmp = art->allowed; tmp; tmp = tmp->next) {
01857 #ifdef TREASURE_VERBOSE
01858 LOG(llevDebug, "legal_art: %s\n", tmp->name);
01859 #endif
01860 if (*tmp->name == '!')
01861 name = tmp->name+1,
01862 neg = 1;
01863 else
01864 name = tmp->name,
01865 neg = 0;
01866
01867
01868 if (!strcmp(name, op->name) || (op->arch && !strcmp(name, op->arch->name)))
01869 return !neg;
01870
01871
01872
01873
01874 else if (neg)
01875 success = 1;
01876 }
01877 return success;
01878 }
01879
01884 void give_artifact_abilities(object *op, object *artifact) {
01885 char new_name[MAX_BUF];
01886
01887 snprintf(new_name, sizeof(new_name), "of %s", artifact->name);
01888 if (op->title)
01889 free_string(op->title);
01890 op->title = add_string(new_name);
01891 add_abilities(op, artifact);
01892
01893 return;
01894 }
01895
01897 #define ARTIFACT_TRIES 2
01898
01906 void generate_artifact(object *op, int difficulty) {
01907 artifactlist *al;
01908 artifact *art;
01909 int i;
01910
01911 al = find_artifactlist(op->type);
01912
01913 if (al == NULL) {
01914 return;
01915 }
01916
01917 for (i = 0; i < ARTIFACT_TRIES; i++) {
01918 int roll = RANDOM()%al->total_chance;
01919
01920 for (art = al->items; art != NULL; art = art->next) {
01921 roll -= art->chance;
01922 if (roll < 0)
01923 break;
01924 }
01925
01926 if (art == NULL || roll >= 0) {
01927 LOG(llevError, "Got null entry and non zero roll in generate_artifact, type %d\n", op->type);
01928 return;
01929 }
01930 if (!strcmp(art->item->name, "NONE"))
01931 return;
01932 if (FABS(op->magic) < art->item->magic)
01933 continue;
01934
01935
01936 if (difficulty < art->difficulty)
01937 continue;
01938
01939 if (!legal_artifact_combination(op, art)) {
01940 #ifdef TREASURE_VERBOSE
01941 LOG(llevDebug, "%s of %s was not a legal combination.\n", op->name, art->item->name);
01942 #endif
01943 continue;
01944 }
01945 give_artifact_abilities(op, art->item);
01946 return;
01947 }
01948 }
01949
01955 static void fix_flesh_item(object *item, object *donor) {
01956 char tmpbuf[MAX_BUF];
01957 int i;
01958
01959 if (item->type == FLESH && donor && QUERY_FLAG(donor, FLAG_MONSTER)) {
01960
01961 snprintf(tmpbuf, sizeof(tmpbuf), "%s's %s", donor->name, item->name);
01962 FREE_AND_COPY(item->name, tmpbuf);
01963 snprintf(tmpbuf, sizeof(tmpbuf), "%s's %s", donor->name, item->name_pl);
01964 FREE_AND_COPY(item->name_pl, tmpbuf);
01965
01966
01967 if (!item->other_arch) {
01968 if (!donor->arch->reference_count) {
01969 item->other_arch = donor->arch;
01970 } else {
01971
01972
01973
01974
01975
01976
01977
01978 archetype *original = find_archetype(donor->arch->name);
01979
01980 if (original)
01981 item->other_arch = original;
01982 else {
01983 LOG(llevError, "could not find original archetype %s for custom monster!\n", donor->arch->name);
01984 abort();
01985 }
01986 }
01987 }
01988
01989
01990 if ((item->weight = (signed long)(((double)item->weight/(double)100.0)*(double)donor->weight)) == 0)
01991 item->weight = 1;
01992
01993
01994 item->value *= isqrt(donor->level*2);
01995
01996
01997 item->stats.food += (donor->stats.hp/100)+donor->stats.Con;
01998
01999
02000 for (i = 0; i < NROFATTACKS; i++)
02001 item->resist[i] = donor->resist[i]/2;
02002
02003
02004 item->level = donor->level;
02005 item->stats.exp = donor->stats.exp;
02006
02007
02008 if (donor->attacktype&AT_POISON)
02009 item->type = POISON;
02010 if (donor->attacktype&AT_ACID)
02011 item->stats.hp = -1*item->stats.food;
02012 SET_FLAG(item, FLAG_NO_STEAL);
02013 }
02014 }
02015
02024 static int special_potion(object *op) {
02025 int i;
02026
02027 if (op->attacktype)
02028 return 1;
02029
02030 if (op->stats.Str
02031 || op->stats.Dex
02032 || op->stats.Con
02033 || op->stats.Pow
02034 || op->stats.Wis
02035 || op->stats.Int
02036 || op->stats.Cha)
02037 return 1;
02038
02039 for (i = 0; i < NROFATTACKS; i++)
02040 if (op->resist[i])
02041 return 1;
02042
02043 return 0;
02044 }
02045
02052 static void free_treasurestruct(treasure *t) {
02053 if (t->next)
02054 free_treasurestruct(t->next);
02055 if (t->next_yes)
02056 free_treasurestruct(t->next_yes);
02057 if (t->next_no)
02058 free_treasurestruct(t->next_no);
02059 free(t);
02060 }
02061
02068 static void free_charlinks(linked_char *lc) {
02069 if (lc->next)
02070 free_charlinks(lc->next);
02071 free(lc);
02072 }
02073
02086 static void free_artifact(artifact *at) {
02087 object *next;
02088
02089 if (at->next)
02090 free_artifact(at->next);
02091 if (at->allowed)
02092 free_charlinks(at->allowed);
02093 while (at->item) {
02094 next = at->item->next;
02095 if (at->item->name)
02096 free_string(at->item->name);
02097 if (at->item->name_pl)
02098 free_string(at->item->name_pl);
02099 if (at->item->msg)
02100 free_string(at->item->msg);
02101 if (at->item->title)
02102 free_string(at->item->title);
02103 free_key_values(at->item);
02104 free(at->item);
02105 at->item = next;
02106 }
02107 free(at);
02108 }
02109
02116 static void free_artifactlist(artifactlist *al) {
02117 artifactlist *nextal;
02118
02119 for (; al != NULL; al = nextal) {
02120 nextal = al->next;
02121 if (al->items) {
02122 free_artifact(al->items);
02123 }
02124 free(al);
02125 }
02126 }
02127
02131 void free_all_treasures(void) {
02132 treasurelist *tl, *next;
02133
02134 for (tl = first_treasurelist; tl != NULL; tl = next) {
02135 next = tl->next;
02136 if (tl->name)
02137 free_string(tl->name);
02138 if (tl->items)
02139 free_treasurestruct(tl->items);
02140 free(tl);
02141 }
02142 free_artifactlist(first_artifactlist);
02143 first_artifactlist = NULL;
02144 }