--- deliantra/server/common/treasure.C 2007/03/14 00:04:58 1.40 +++ deliantra/server/common/treasure.C 2007/04/16 06:23:40 1.41 @@ -40,20 +40,33 @@ #include #include +extern char *spell_mapping[]; + +static treasurelist *first_treasurelist; static void change_treasure (treasure *t, object *op); /* overrule default values */ -extern char *spell_mapping[]; + +typedef std::tr1::unordered_map< + const char *, + treasurelist *, + str_hash, + str_equal, + slice_allocator< std::pair >, + true +> tl_map_t; + +static tl_map_t tl_map; /* * Initialize global archtype pointers: */ - void init_archetype_pointers () { int prev_warn = warn_archetypes; warn_archetypes = 1; + if (ring_arch == NULL) ring_arch = archetype::find ("ring"); if (amulet_arch == NULL) @@ -62,31 +75,60 @@ staff_arch = archetype::find ("staff"); if (crown_arch == NULL) crown_arch = archetype::find ("crown"); + warn_archetypes = prev_warn; } /* - * Allocate and return the pointer to an empty treasurelist structure. + * Searches for the given treasurelist in the globally linked list + * of treasurelists which has been built by load_treasures(). */ - -static treasurelist * -get_empty_treasurelist (void) +treasurelist * +treasurelist::find (const char *name) { - return new treasurelist; + if (!name) + return 0; + + AUTODECL (i, tl_map.find (name)); + + if (i == tl_map.end ()) + return 0; + + return i->second; } /* - * Allocate and return the pointer to an empty treasure structure. + * Searches for the given treasurelist in the globally linked list + * of treasurelists which has been built by load_treasures(). */ -//TODO: make this a constructor -static treasure * -get_empty_treasure (void) +treasurelist * +treasurelist::get (const char *name) { - treasure *t = new treasure; + treasurelist *tl = find (name); - t->chance = 100; + if (!tl) + { + tl = new treasurelist; - return t; + tl->name = name; + tl->next = first_treasurelist; + first_treasurelist = tl; + + tl_map.insert (std::make_pair (tl->name, tl)); + } + + return tl; +} + +//TODO: class method +void +clear (treasurelist *tl) +{ + if (tl->items) + { + free_treasurestruct (tl->items); + tl->items = 0; + } } /* @@ -98,7 +140,7 @@ load_treasure (FILE * fp, int *line) { char buf[MAX_BUF], *cp, variable[MAX_BUF]; - treasure *t = get_empty_treasure (); + treasure *t = new treasure; int value; nroftreasures++; @@ -161,13 +203,13 @@ { if (t->chance >= 100 && t->next_yes && (t->next || t->next_no)) LOG (llevError, "Treasurelist %s has element that has 100%% generation, next_yes field as well as next or next_no\n", &tl->name); - /* find_treasurelist will print out its own error message */ - if (t->name && *t->name) - find_treasurelist (t->name); + if (t->next) check_treasurelist (t->next, tl); + if (t->next_yes) check_treasurelist (t->next_yes, tl); + if (t->next_no) check_treasurelist (t->next_no, tl); } @@ -183,7 +225,6 @@ { FILE *fp; char filename[MAX_BUF], buf[MAX_BUF], name[MAX_BUF]; - treasurelist *previous = NULL; treasure *t; int comp, line = 0; @@ -200,15 +241,9 @@ ; // ignore else if (sscanf (buf, "treasureone %s\n", name) || sscanf (buf, "treasure %s\n", name)) { - treasurelist *tl = get_empty_treasurelist (); + treasurelist *tl = treasurelist::get (name); - tl->name = name; - if (previous == NULL) - first_treasurelist = tl; - else - previous->next = tl; - - previous = tl; + clear (tl); tl->items = load_treasure (fp, &line); /* This is a one of the many items on the list should be generated. @@ -217,7 +252,7 @@ */ if (!strncmp (buf, "treasureone", 11)) { - for (t = tl->items; t != NULL; t = t->next) + for (t = tl->items; t; t = t->next) { #ifdef TREASURE_DEBUG if (t->next_yes || t->next_no) @@ -233,6 +268,7 @@ else LOG (llevError, "Treasure-list %s didn't understand: %s, line %d\n", filename, buf, line); } + close_and_delete (fp, comp); #ifdef TREASURE_DEBUG @@ -241,36 +277,12 @@ * to transition to exists). Also, verify that at least the name * or archetype is set for each treasure element. */ - for (previous = first_treasurelist; previous != NULL; previous = previous->next) - check_treasurelist (previous->items, previous); + for (treasurelist *tl = first_treasurelist; tl; tl = tl->next) + check_treasurelist (tl->items, tl); #endif } /* - * Searches for the given treasurelist in the globally linked list - * of treasurelists which has been built by load_treasures(). - */ - -treasurelist * -find_treasurelist (const char *name) -{ - shstr_cmp name_ (name); - - if (!name_) - return 0; - - for (treasurelist *tl = first_treasurelist; tl != 0; tl = tl->next) - if (name_ == tl->name) - return tl; - - if (first_treasurelist) - LOG (llevError, "Couldn't find treasurelist %s\n", name); - - return 0; -} - - -/* * Generates the objects specified by the given treasure. * It goes recursively through the rest of the linked list. * If there is a certain percental chance for a treasure to be generated, @@ -328,27 +340,22 @@ op->slaying = t->change_arch.slaying; } -void +static void create_all_treasures (treasure *t, object *op, int flag, int difficulty, int tries) { - object *tmp; - if ((int) t->chance >= 100 || (rndm (100) + 1) < (int) t->chance) { if (t->name) { if (difficulty >= t->magic) - { - treasurelist *tl = find_treasurelist (t->name); - if (tl) - create_treasure (tl, op, flag, difficulty, tries); - } + create_treasure (treasurelist::find (t->name), op, flag, difficulty, tries); } else { if (t->item && (t->item->clone.invisible != 0 || !(flag & GT_INVISIBLE))) { - tmp = arch_to_object (t->item); + object *tmp = arch_to_object (t->item); + if (t->nrof && tmp->nrof <= 1) tmp->nrof = rndm (t->nrof) + 1; @@ -358,17 +365,17 @@ } } - if (t->next_yes != NULL) + if (t->next_yes) create_all_treasures (t->next_yes, op, flag, difficulty, tries); } - else if (t->next_no != NULL) + else if (t->next_no) create_all_treasures (t->next_no, op, flag, difficulty, tries); - if (t->next != NULL) + if (t->next) create_all_treasures (t->next, op, flag, difficulty, tries); } -void +static void create_one_treasure (treasurelist *tl, object *op, int flag, int difficulty, int tries) { int value = rndm (tl->total_chance); @@ -380,7 +387,7 @@ return; } - for (t = tl->items; t != NULL; t = t->next) + for (t = tl->items; t; t = t->next) { value -= t->chance; @@ -389,39 +396,30 @@ } if (!t || value >= 0) - { - LOG (llevError, "create_one_treasure: got null object or not able to find treasure\n"); - abort (); - return; - } + cleanup ("create_one_treasure: got null object or not able to find treasure\n", 1); if (t->name) { if (difficulty >= t->magic) { - treasurelist *tl = find_treasurelist (t->name); + treasurelist *tl = treasurelist::find (t->name); if (tl) create_treasure (tl, op, flag, difficulty, tries); } else if (t->nrof) create_one_treasure (tl, op, flag, difficulty, tries); - - return; } - - if (t->item && (t->item->clone.invisible != 0 || flag != GT_INVISIBLE)) + else if (t->item && (t->item->clone.invisible != 0 || flag != GT_INVISIBLE)) { - object *tmp = arch_to_object (t->item); - - if (!tmp) - return; - - if (t->nrof && tmp->nrof <= 1) - tmp->nrof = rndm (t->nrof) + 1; + if (object *tmp = arch_to_object (t->item)) + { + if (t->nrof && tmp->nrof <= 1) + tmp->nrof = rndm (t->nrof) + 1; - fix_generated_item (tmp, op, difficulty, t->magic, flag); - change_treasure (t, tmp); - put_treasure (tmp, op, flag); + fix_generated_item (tmp, op, difficulty, t->magic, flag); + change_treasure (t, tmp); + put_treasure (tmp, op, flag); + } } } @@ -435,6 +433,10 @@ void create_treasure (treasurelist *tl, object *op, int flag, int difficulty, int tries) { + // empty treasurelists are legal + if (!tl->items) + return; + if (tries++ > 100) { LOG (llevDebug, "createtreasure: tries exceeded 100, returning without making treasure\n"); @@ -558,7 +560,6 @@ * weird integer between 1-31. * */ - int magic_from_difficulty (int difficulty) { @@ -656,7 +657,6 @@ * other bonuses previously rolled and ones the item might natively have. * 2) Add code to deal with new PR method. */ - void set_ring_bonus (object *op, int bonus) { @@ -1178,14 +1178,7 @@ static artifactlist * get_empty_artifactlist (void) { - artifactlist *al = (artifactlist *) malloc (sizeof (artifactlist)); - - if (al == NULL) - fatal (OUT_OF_MEMORY); - al->next = NULL; - al->items = NULL; - al->total_chance = 0; - return al; + return salloc0 (); } /* @@ -1194,17 +1187,7 @@ static artifact * get_empty_artifact (void) { - artifact *a = (artifact *) malloc (sizeof (artifact)); - - if (a == NULL) - fatal (OUT_OF_MEMORY); - - a->item = NULL; - a->next = NULL; - a->chance = 0; - a->difficulty = 0; - a->allowed = NULL; - return a; + return salloc0 (); } /* @@ -1214,9 +1197,7 @@ artifactlist * find_artifactlist (int type) { - artifactlist *al; - - for (al = first_artifactlist; al; al = al->next) + for (artifactlist *al = first_artifactlist; al; al = al->next) if (al->type == type) return al; @@ -1263,24 +1244,30 @@ if (depth > 100) return; + while (t) { if (t->name) { for (i = 0; i < depth; i++) fprintf (logfile, " "); + fprintf (logfile, "{ (list: %s)\n", &t->name); - tl = find_treasurelist (t->name); + + tl = treasurelist::find (t->name); if (tl) dump_monster_treasure_rec (name, tl->items, depth + 2); + for (i = 0; i < depth; i++) fprintf (logfile, " "); + fprintf (logfile, "} (end of list: %s)\n", &t->name); } else { for (i = 0; i < depth; i++) fprintf (logfile, " "); + if (t->item && t->item->clone.type == FLESH) fprintf (logfile, "%s's %s\n", name, &t->item->clone.name); else @@ -1291,6 +1278,7 @@ { for (i = 0; i < depth; i++) fprintf (logfile, " "); + fprintf (logfile, " (if yes)\n"); dump_monster_treasure_rec (name, t->next_yes, depth + 1); } @@ -1299,6 +1287,7 @@ { for (i = 0; i < depth; i++) fprintf (logfile, " "); + fprintf (logfile, " (if no)\n"); dump_monster_treasure_rec (name, t->next_no, depth + 1); } @@ -1311,7 +1300,6 @@ * For debugging purposes. Dumps all treasures for a given monster. * Created originally by Raphael Quinet for debugging the alchemy code. */ - void dump_monster_treasure (const char *name) { @@ -1844,12 +1832,9 @@ void free_treasurestruct (treasure *t) { - if (t->next) - free_treasurestruct (t->next); - if (t->next_yes) - free_treasurestruct (t->next_yes); - if (t->next_no) - free_treasurestruct (t->next_no); + if (t->next) free_treasurestruct (t->next); + if (t->next_yes) free_treasurestruct (t->next_yes); + if (t->next_no) free_treasurestruct (t->next_no); delete t; } @@ -1864,21 +1849,18 @@ } void -free_artifact (artifact * at) +free_artifact (artifact *at) { - if (at->next) - free_artifact (at->next); - - if (at->allowed) - free_charlinks (at->allowed); + if (at->next) free_artifact (at->next); + if (at->allowed) free_charlinks (at->allowed); at->item->destroy (1); - delete at; + sfree (at); } void -free_artifactlist (artifactlist * al) +free_artifactlist (artifactlist *al) { artifactlist *nextal; @@ -1889,7 +1871,7 @@ if (al->items) free_artifact (al->items); - free (al); + sfree (al); } } @@ -1898,13 +1880,13 @@ { treasurelist *tl, *next; - - for (tl = first_treasurelist; tl != NULL; tl = next) + for (tl = first_treasurelist; tl; tl = next) { + clear (tl); + next = tl->next; - if (tl->items) - free_treasurestruct (tl->items); delete tl; } + free_artifactlist (first_artifactlist); }