Crossfire Server, Branch 1.12  R12190
treasure.c
Go to the documentation of this file.
00001 
00002 /*
00003  * static char *rcs_treasure_c =
00004  *   "$Id: treasure.c 13896 2010-09-26 13:57:17Z ryo_saeba $";
00005  */
00006 
00007 /*
00008     CrossFire, A Multiplayer game for X-windows
00009 
00010     Copyright (C) 2002-2006 Mark Wedel & Crossfire Development Team
00011     Copyright (C) 1992 Frank Tore Johansen
00012 
00013     This program is free software; you can redistribute it and/or modify
00014     it under the terms of the GNU General Public License as published by
00015     the Free Software Foundation; either version 2 of the License, or
00016     (at your option) any later version.
00017 
00018     This program is distributed in the hope that it will be useful,
00019     but WITHOUT ANY WARRANTY; without even the implied warranty of
00020     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021     GNU General Public License for more details.
00022 
00023     You should have received a copy of the GNU General Public License
00024     along with this program; if not, write to the Free Software
00025     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00026 
00027     The authors can be reached via e-mail at crossfire-devel@real-time.com
00028 */
00029 
00036 #define ALLOWED_COMBINATION
00037 
00044 #define TREASURE_DEBUG
00045 
00046 /* TREASURE_VERBOSE enables copious output concerning artifact generation */
00047 /* #define TREASURE_VERBOSE */
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); /* overrule default values */
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)) /* Skip blanks */
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     /* find_treasurelist will print out its own error message */
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             /* This is a one of the many items on the list should be generated.
00253              * Add up the chance total, and check to make sure the yes & no
00254              * fields of the treasures are not being used.
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     /* Perform some checks on how valid the treasure data actually is.
00274      * verify that list transitions work (ie, the list that it is supposed
00275      * to transition to exists).  Also, verify that at least the name
00276      * or archetype is set for each treasure element.
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     /* Special cases - randomitems of none is to override default.  If
00300      * first_treasurelist is null, it means we are on the first pass of
00301      * of loading archetyps, so for now, just return - second pass will
00302      * init these values.
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     /* Bit of a hack - spells should never be put onto the map.  The entire
00328      * treasure stuff is a problem - there is no clear idea of knowing
00329      * this is the original object, or if this is an object that should be created
00330      * by another object.
00331      */
00332     if (flags&GT_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&GT_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     /* CMD: change_name xxxx */
00356     if (t->change_arch.name) {
00357         FREE_AND_COPY(op->name, t->change_arch.name);
00358         /* not great, but better than something that is completely wrong */
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&GT_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&GT_ONLY_GOOD)) { /* Generate only good items, damnit !*/
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     /* Don't want to free the object we are about to return */
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     /* Basically, we set mult to the lowest spell increase attribute that is
00565      * not zero - zero's mean no modification is done, so we don't want those.
00566      * given we want non zero results, we can't just use a few MIN's here.
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 /*chance of magic    difficulty*/
00596 /* +0  +1 +2 +3 +4 */
00597     { 94, 3, 2, 1, 0 }, /*1*/
00598     { 94, 3, 2, 1, 0 }, /*2*/
00599     { 94, 3, 2, 1, 0 }, /*3*/
00600     { 94, 3, 2, 1, 0 }, /*4*/
00601     { 94, 3, 2, 1, 0 }, /*5*/
00602     { 90, 4, 3, 2, 1 }, /*6*/
00603     { 90, 4, 3, 2, 1 }, /*7*/
00604     { 90, 4, 3, 2, 1 }, /*8*/
00605     { 90, 4, 3, 2, 1 }, /*9*/
00606     { 90, 4, 3, 2, 1 }, /*10*/
00607     { 85, 6, 4, 3, 2 }, /*11*/
00608     { 85, 6, 4, 3, 2 }, /*12*/
00609     { 85, 6, 4, 3, 2 }, /*13*/
00610     { 85, 6, 4, 3, 2 }, /*14*/
00611     { 85, 6, 4, 3, 2 }, /*15*/
00612     { 81, 8, 5, 4, 3 }, /*16*/
00613     { 81, 8, 5, 4, 3 }, /*17*/
00614     { 81, 8, 5, 4, 3 }, /*18*/
00615     { 81, 8, 5, 4, 3 }, /*19*/
00616     { 81, 8, 5, 4, 3 }, /*20*/
00617     { 75, 10, 6, 5, 4 }, /*21*/
00618     { 75, 10, 6, 5, 4 }, /*22*/
00619     { 75, 10, 6, 5, 4 }, /*23*/
00620     { 75, 10, 6, 5, 4 }, /*24*/
00621     { 75, 10, 6, 5, 4 }, /*25*/
00622     { 70, 12, 7, 6, 5 }, /*26*/
00623     { 70, 12, 7, 6, 5 }, /*27*/
00624     { 70, 12, 7, 6, 5 }, /*28*/
00625     { 70, 12, 7, 6, 5 }, /*29*/
00626     { 70, 12, 7, 6, 5 }, /*30*/
00627     { 70, 9, 8, 7, 6 }, /*31*/
00628     { 70, 9, 8, 7, 6 }, /*32*/
00629     { 70, 9, 8, 7, 6 }, /*33*/
00630     { 70, 9, 8, 7, 6 }, /*34*/
00631     { 70, 9, 8, 7, 6 }, /*35*/
00632     { 70, 6, 9, 8, 7 }, /*36*/
00633     { 70, 6, 9, 8, 7 }, /*37*/
00634     { 70, 6, 9, 8, 7 }, /*38*/
00635     { 70, 6, 9, 8, 7 }, /*39*/
00636     { 70, 6, 9, 8, 7 }, /*40*/
00637     { 70, 3, 10, 9, 8 }, /*41*/
00638     { 70, 3, 10, 9, 8 }, /*42*/
00639     { 70, 3, 10, 9, 8 }, /*43*/
00640     { 70, 3, 10, 9, 8 }, /*44*/
00641     { 70, 3, 10, 9, 8 }, /*45*/
00642     { 70, 2, 9, 10, 9 }, /*46*/
00643     { 70, 2, 9, 10, 9 }, /*47*/
00644     { 70, 2, 9, 10, 9 }, /*48*/
00645     { 70, 2, 9, 10, 9 }, /*49*/
00646     { 70, 2, 9, 10, 9 }, /*50*/
00647     { 70, 2, 7, 11, 10 }, /*51*/
00648     { 70, 2, 7, 11, 10 }, /*52*/
00649     { 70, 2, 7, 11, 10 }, /*53*/
00650     { 70, 2, 7, 11, 10 }, /*54*/
00651     { 70, 2, 7, 11, 10 }, /*55*/
00652     { 70, 2, 5, 12, 11 }, /*56*/
00653     { 70, 2, 5, 12, 11 }, /*57*/
00654     { 70, 2, 5, 12, 11 }, /*58*/
00655     { 70, 2, 5, 12, 11 }, /*59*/
00656     { 70, 2, 5, 12, 11 }, /*60*/
00657     { 70, 2, 3, 13, 12 }, /*61*/
00658     { 70, 2, 3, 13, 12 }, /*62*/
00659     { 70, 2, 3, 13, 12 }, /*63*/
00660     { 70, 2, 3, 13, 12 }, /*64*/
00661     { 70, 2, 3, 13, 12 }, /*65*/
00662     { 70, 2, 3, 12, 13 }, /*66*/
00663     { 70, 2, 3, 12, 13 }, /*67*/
00664     { 70, 2, 3, 12, 13 }, /*68*/
00665     { 70, 2, 3, 12, 13 }, /*69*/
00666     { 70, 2, 3, 12, 13 }, /*70*/
00667     { 70, 2, 3, 11, 14 }, /*71*/
00668     { 70, 2, 3, 11, 14 }, /*72*/
00669     { 70, 2, 3, 11, 14 }, /*73*/
00670     { 70, 2, 3, 11, 14 }, /*74*/
00671     { 70, 2, 3, 11, 14 }, /*75*/
00672     { 70, 2, 3, 10, 15 }, /*76*/
00673     { 70, 2, 3, 10, 15 }, /*77*/
00674     { 70, 2, 3, 10, 15 }, /*78*/
00675     { 70, 2, 3, 10, 15 }, /*79*/
00676     { 70, 2, 3, 10, 15 }, /*80*/
00677     { 70, 2, 3, 9, 16  }, /*81*/
00678     { 70, 2, 3, 9, 16  }, /*82*/
00679     { 70, 2, 3, 9, 16  }, /*83*/
00680     { 70, 2, 3, 9, 16  }, /*84*/
00681     { 70, 2, 3, 9, 16  }, /*85*/
00682     { 70, 2, 3, 8, 17  }, /*86*/
00683     { 70, 2, 3, 8, 17  }, /*87*/
00684     { 70, 2, 3, 8, 17  }, /*88*/
00685     { 70, 2, 3, 8, 17  }, /*89*/
00686     { 70, 2, 3, 8, 17  }, /*90*/
00687     { 70, 2, 3, 7, 18  }, /*91*/
00688     { 70, 2, 3, 7, 18  }, /*92*/
00689     { 70, 2, 3, 7, 18  }, /*93*/
00690     { 70, 2, 3, 7, 18  }, /*94*/
00691     { 70, 2, 3, 7, 18  }, /*95*/
00692     { 70, 2, 3, 6, 19  }, /*96*/
00693     { 70, 2, 3, 6, 19  }, /*97*/
00694     { 70, 2, 3, 6, 19  }, /*98*/
00695     { 70, 2, 3, 6, 19  }, /*99*/
00696     { 70, 2, 3, 6, 19  }, /*100*/
00697     { 70, 2, 3, 6, 19  }, /*101*/
00698     { 70, 2, 3, 6, 19  }, /*101*/
00699     { 70, 2, 3, 6, 19  }, /*102*/
00700     { 70, 2, 3, 6, 19  }, /*103*/
00701     { 70, 2, 3, 6, 19  }, /*104*/
00702     { 70, 2, 3, 6, 19  }, /*105*/
00703     { 70, 2, 3, 6, 19  }, /*106*/
00704     { 70, 2, 3, 6, 19  }, /*107*/
00705     { 70, 2, 3, 6, 19  }, /*108*/
00706     { 70, 2, 3, 6, 19  }, /*109*/
00707     { 70, 2, 3, 6, 19  }, /*110*/
00708     { 70, 2, 3, 6, 19  }, /*111*/
00709     { 70, 2, 3, 6, 19  }, /*112*/
00710     { 70, 2, 3, 6, 19  }, /*113*/
00711     { 70, 2, 3, 6, 19  }, /*114*/
00712     { 70, 2, 3, 6, 19  }, /*115*/
00713     { 70, 2, 3, 6, 19  }, /*116*/
00714     { 70, 2, 3, 6, 19  }, /*117*/
00715     { 70, 2, 3, 6, 19  }, /*118*/
00716     { 70, 2, 3, 6, 19  }, /*119*/
00717     { 70, 2, 3, 6, 19  }, /*120*/
00718     { 70, 2, 3, 6, 19  }, /*121*/
00719     { 70, 2, 3, 6, 19  }, /*122*/
00720     { 70, 2, 3, 6, 19  }, /*123*/
00721     { 70, 2, 3, 6, 19  }, /*124*/
00722     { 70, 2, 3, 6, 19  }, /*125*/
00723     { 70, 2, 3, 6, 19  }, /*126*/
00724     { 70, 2, 3, 6, 19  }, /*127*/
00725     { 70, 2, 3, 6, 19  }, /*128*/
00726     { 70, 2, 3, 6, 19  }, /*129*/
00727     { 70, 2, 3, 6, 19  }, /*130*/
00728     { 70, 2, 3, 6, 19  }, /*131*/
00729     { 70, 2, 3, 6, 19  }, /*132*/
00730     { 70, 2, 3, 6, 19  }, /*133*/
00731     { 70, 2, 3, 6, 19  }, /*134*/
00732     { 70, 2, 3, 6, 19  }, /*135*/
00733     { 70, 2, 3, 6, 19  }, /*136*/
00734     { 70, 2, 3, 6, 19  }, /*137*/
00735     { 70, 2, 3, 6, 19  }, /*138*/
00736     { 70, 2, 3, 6, 19  }, /*139*/
00737     { 70, 2, 3, 6, 19  }, /*140*/
00738     { 70, 2, 3, 6, 19  }, /*141*/
00739     { 70, 2, 3, 6, 19  }, /*142*/
00740     { 70, 2, 3, 6, 19  }, /*143*/
00741     { 70, 2, 3, 6, 19  }, /*144*/
00742     { 70, 2, 3, 6, 19  }, /*145*/
00743     { 70, 2, 3, 6, 19  }, /*146*/
00744     { 70, 2, 3, 6, 19  }, /*147*/
00745     { 70, 2, 3, 6, 19  }, /*148*/
00746     { 70, 2, 3, 6, 19  }, /*149*/
00747     { 70, 2, 3, 6, 19  }, /*150*/
00748     { 70, 2, 3, 6, 19  }, /*151*/
00749     { 70, 2, 3, 6, 19  }, /*152*/
00750     { 70, 2, 3, 6, 19  }, /*153*/
00751     { 70, 2, 3, 6, 19  }, /*154*/
00752     { 70, 2, 3, 6, 19  }, /*155*/
00753     { 70, 2, 3, 6, 19  }, /*156*/
00754     { 70, 2, 3, 6, 19  }, /*157*/
00755     { 70, 2, 3, 6, 19  }, /*158*/
00756     { 70, 2, 3, 6, 19  }, /*159*/
00757     { 70, 2, 3, 6, 19  }, /*160*/
00758     { 70, 2, 3, 6, 19  }, /*161*/
00759     { 70, 2, 3, 6, 19  }, /*162*/
00760     { 70, 2, 3, 6, 19  }, /*163*/
00761     { 70, 2, 3, 6, 19  }, /*164*/
00762     { 70, 2, 3, 6, 19  }, /*165*/
00763     { 70, 2, 3, 6, 19  }, /*166*/
00764     { 70, 2, 3, 6, 19  }, /*167*/
00765     { 70, 2, 3, 6, 19  }, /*168*/
00766     { 70, 2, 3, 6, 19  }, /*169*/
00767     { 70, 2, 3, 6, 19  }, /*170*/
00768     { 70, 2, 3, 6, 19  }, /*171*/
00769     { 70, 2, 3, 6, 19  }, /*172*/
00770     { 70, 2, 3, 6, 19  }, /*173*/
00771     { 70, 2, 3, 6, 19  }, /*174*/
00772     { 70, 2, 3, 6, 19  }, /*175*/
00773     { 70, 2, 3, 6, 19  }, /*176*/
00774     { 70, 2, 3, 6, 19  }, /*177*/
00775     { 70, 2, 3, 6, 19  }, /*178*/
00776     { 70, 2, 3, 6, 19  }, /*179*/
00777     { 70, 2, 3, 6, 19  }, /*180*/
00778     { 70, 2, 3, 6, 19  }, /*181*/
00779     { 70, 2, 3, 6, 19  }, /*182*/
00780     { 70, 2, 3, 6, 19  }, /*183*/
00781     { 70, 2, 3, 6, 19  }, /*184*/
00782     { 70, 2, 3, 6, 19  }, /*185*/
00783     { 70, 2, 3, 6, 19  }, /*186*/
00784     { 70, 2, 3, 6, 19  }, /*187*/
00785     { 70, 2, 3, 6, 19  }, /*188*/
00786     { 70, 2, 3, 6, 19  }, /*189*/
00787     { 70, 2, 3, 6, 19  }, /*190*/
00788     { 70, 2, 3, 6, 19  }, /*191*/
00789     { 70, 2, 3, 6, 19  }, /*192*/
00790     { 70, 2, 3, 6, 19  }, /*193*/
00791     { 70, 2, 3, 6, 19  }, /*194*/
00792     { 70, 2, 3, 6, 19  }, /*195*/
00793     { 70, 2, 3, 6, 19  }, /*196*/
00794     { 70, 2, 3, 6, 19  }, /*197*/
00795     { 70, 2, 3, 6, 19  }, /*198*/
00796     { 70, 2, 3, 6, 19  }, /*199*/
00797     { 70, 2, 3, 6, 19  }, /*200*/
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     /*  LOG(llevDebug, "Chose magic %d for difficulty %d\n", loop, difficulty);*/
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)) /* You can't just check the weight always */
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)) /* You can't just check the weight always */
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&GT_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         /* Redone by MSW 2000-11-26 to have much less code.  Also,
00925          * bonuses and penalties will stack and add to existing values.
00926          * of the item.
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; /* hunger/sustenance */
00948         break;
00949 
00950     case 10:
00951         op->stats.ac += bonus;
00952         break;
00953 
00954         /* Item that gives protections/vulnerabilities */
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             /* Roughly generate a bonus between 100 and 35 (depending on the bonus) */
00967             val = 10+RANDOM()%b+RANDOM()%b+RANDOM()%b+RANDOM()%b;
00968 
00969             /* Cursed items need to have higher negative values to equal out with
00970              * positive values for how protections work out.  Put another
00971              * little random element in since that they don't always end up with
00972              * even values.
00973              */
00974             if (bonus < 0)
00975                 val = 2*-val-RANDOM()%b;
00976             if (val > 35)
00977                 val = 35; /* Upper limit */
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; /* Not able to find a free resistance */
00984             op->resist[resist_table[resist]] = val;
00985             /* We should probably do something more clever here to adjust value
00986              * based on how good a resistance we gave.
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; /* regenerate hit points */
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; /* regenerate spell points */
01007             op->value *= 3;
01008         }
01009         break;
01010 
01011     case 22:
01012         op->stats.exp += bonus; /* Speed! */
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; /* safety & to prevent polymorphed objects giving attributes */
01075 
01076     /* If we make an artifact, this information will be destroyed */
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         /* So the treasure doesn't get created again */
01085         op->randomitems = NULL;
01086     }
01087 
01088     if (difficulty < 1)
01089         difficulty = 1;
01090     if (!(flags&GT_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         /* Object was made an artifact.  Calculate its item_power rating.
01106          * the item_power in the object is what the artifact adds.
01107          */
01108         if (op->title) {
01109             /* if save_item_power is set, then most likely we started with an
01110              * artifact and have added new abilities to it - this is rare, but
01111              * but I have seen things like 'strange rings of fire'.  So just
01112              * figure out the power from the base power plus what this one adds.
01113              * Note that since item_power is not quite linear, this actually
01114              * ends up being somewhat of a bonus.
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             /* restore the item_power field to the object if we haven't changed
01122              * it. we don't care about num_enchantments - that will basically
01123              * just have calculated some value from the base attributes of the
01124              * archetype.
01125              */
01126             op->item_power = save_item_power;
01127         } else {
01128             /* item_power was zero. This is suspicious, as it may be because it
01129              * was never previously calculated. Let's compute a value and see if
01130              * it is non-zero. If it indeed is, then assign it as the new
01131              * item_power value.
01132              * - gros, 21th of July 2006.
01133              */
01134             op->item_power = calc_item_power(op, 0);
01135             save_item_power = op->item_power; /* Just in case it would get used
01136                                                * again below */
01137         }
01138     } else {
01139         /* If flag is GT_MINIMAL, we want to restore item power */
01140         op->item_power = save_item_power;
01141     }
01142 
01143     /* materialtype modifications.  Note we allow this on artifacts. */
01144 
01145     set_materialname(op, difficulty, NULL);
01146 
01147     if (flags&GT_MINIMAL) {
01148         if (op->type == POTION)
01149             /* Handle healing and magic power potions */
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) { /* Only modify object if not special */
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                 /* Handle healing and magic power potions */
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                 /* don't want to change value for healing/magic power potions,
01194                  * since the value set on those is already correct.
01195                  */
01196                 if (op->inv && op->randomitems) {
01197                     /* value multiplier is same as for scrolls */
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&GT_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; /* Since it's not just decoration */
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                 /* It's a special artifact!*/
01221                 break;
01222 
01223             if (!(flags&GT_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) /* Amulets have only one ability */
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             /* Is it an empty book?, if yes lets make a special
01246              * msg for it, and tailor its properties based on the
01247              * creator and/or map level we found it on.
01248              */
01249             if (!op->msg && RANDOM()%10) {
01250                 /* set the book level properly */
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                 /* books w/ info are worth more! */
01261                 op->value *= ((op->level > 10 ? op->level : (op->level+1)/2)*((strlen(op->msg)/250)+1));
01262                 /* creator related stuff */
01263 
01264                 /* for library, chained books.  Note that some monsters have
01265                  * no_pick set - we don't want to set no pick in that case.
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) /* for check_inv floors */
01271                         op->slaying = add_string(creator->slaying);
01272 
01273                 /* add exp so reading it gives xp (once)*/
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             /* add exp so learning gives xp */
01281             op->level = op->inv->level;
01282             op->stats.exp = op->value;
01283             /* some more fun */
01284             if (!(flags&GT_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             /* nrof in the treasure list is number of charges,
01296              * not number of wands.  So copy that into food (charges),
01297              * and reset nrof.
01298              */
01299             op->stats.food = op->inv->nrof;
01300             op->nrof = 1;
01301             /* If the spell changes by level, choose a random level
01302              * for it, and adjust price.  If the spell doesn't
01303              * change by level, just set the wand to the level of
01304              * the spell, and value calculation is simpler.
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             /* Add 50 to both level an divisor to keep prices a little
01320              * more reasonable.  Otherwise, a high level version of a
01321              * low level spell can be worth tons a money (eg, level 20
01322              * rod, level 2 spell = 10 time multiplier).  This way, the
01323              * value are a bit more reasonable.
01324              */
01325             op->value = op->value*op->inv->value*(op->level+50)/(op->inv->level+50);
01326             /* maxhp is used to denote how many 'charges' the rod holds
01327              * before */
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             /* add exp so reading them properly gives xp */
01340             op->stats.exp = op->value/5;
01341             op->nrof = op->inv->nrof;
01342             /* some more fun */
01343             if (!(flags&GT_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         } /* switch type */
01361     }
01362     if (flags&GT_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&GT_ENVIRONMENT))
01373         fix_flesh_item(op, creator);
01374 }
01375 
01376 /*
01377  *
01378  *
01379  * CODE DEALING WITH ARTIFACTS STARTS HERE
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 == ' ') /* Skip blanks */
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         /* so artifacts will join */
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; /* Speed modifier */
01713     op->stats.wc += change->stats.wc;
01714     op->stats.ac += change->stats.ac;
01715 
01716     if (change->other_arch) {
01717         /* Basically, for horns & potions, the other_arch field is the spell
01718          * to cast.  So convert that to into a spell and put it into
01719          * this object.
01720          */
01721         if (op->type == HORN || op->type == POTION) {
01722             object *tmp_obj;
01723 
01724             /* Remove any spells this object currently has in it */
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         /* No harm setting this for potions/horns */
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 = (int)(((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; /* Ie, "all" */
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         /* If we match name, then return the opposite of 'neg' */
01868         if (!strcmp(name, op->name) || (op->arch && !strcmp(name, op->arch->name)))
01869             return !neg;
01870 
01871         /* Set success as true, since if the match was an inverse, it means
01872          * everything is allowed except what we match
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); /* Give out the bonuses */
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; /* Not magic enough to be this item */
01934 
01935         /* Map difficulty not high enough */
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         /* change the name */
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         /* store original arch in other_arch */
01967         if (!item->other_arch) {
01968             if (!donor->arch->reference_count) {
01969                 item->other_arch = donor->arch;
01970             } else {
01971                 /* If dealing with custom monsters, other_arch still needs to
01972                  * point back to the original.  Otherwise what happens
01973                  * is that other_arch points at the custom archetype, but
01974                  * that can be freed.  Reference count doesn't work because
01975                  * the loader will not be able to resolve the other_arch at
01976                  * load time (server may has restarted, etc.)
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         /* weight is FLESH weight/100 * donor */
01990         if ((item->weight = (signed long)(((double)item->weight/(double)100.0)*(double)donor->weight)) == 0)
01991             item->weight = 1;
01992 
01993         /* value is multiplied by level of donor */
01994         item->value *= isqrt(donor->level*2);
01995 
01996         /* food value */
01997         item->stats.food += (donor->stats.hp/100)+donor->stats.Con;
01998 
01999         /* flesh items inherit some abilities of donor, but not full effect. */
02000         for (i = 0; i < NROFATTACKS; i++)
02001             item->resist[i] = donor->resist[i]/2;
02002 
02003         /* item inherits donor's level and exp (important for dragons) */
02004         item->level = donor->level;
02005         item->stats.exp = donor->stats.exp;
02006 
02007         /* if donor has some attacktypes, the flesh is poisonous */
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 }