diff options
-rw-r--r-- | src/init1.cc | 19 | ||||
-rw-r--r-- | src/store.cc | 134 | ||||
-rw-r--r-- | src/store_item.hpp | 47 |
3 files changed, 144 insertions, 56 deletions
diff --git a/src/init1.cc b/src/init1.cc index 98c16cc5..2224bc25 100644 --- a/src/init1.cc +++ b/src/init1.cc @@ -5352,10 +5352,12 @@ errr init_st_info_txt(FILE *fp) if (!*s) return (1); /* Add to items array */ - store_item item; - item.chance = atoi(buf + 2); - item.kind = test_item_name(s); - st_ptr->items.emplace_back(item); + auto chance = atoi(buf + 2); + int k_idx = test_item_name(s); + assert(k_idx >= 0); + + st_ptr->items.emplace_back( + store_item::k_idx(k_idx, chance)); /* Next... */ continue; @@ -5371,11 +5373,10 @@ errr init_st_info_txt(FILE *fp) &rar1, &tv1, &sv1)) return (1); /* Add to the items array */ - store_item item; - item.chance = rar1; - item.kind = (sv1 < 256) - ? lookup_kind(tv1, sv1) - : tv1 + 10000; /* An SVAL of 256 means all possible items. */ + store_item item = (sv1 < 256) + ? store_item::k_idx(lookup_kind(tv1, sv1), rar1) + : store_item::tval(tv1, rar1); /* An SVAL of 256 means all possible items. */ + st_ptr->items.emplace_back(item); /* Next... */ diff --git a/src/store.cc b/src/store.cc index a11a3ea8..1c593c7e 100644 --- a/src/store.cc +++ b/src/store.cc @@ -1177,6 +1177,75 @@ static bool_ kind_is_storeok(int k_idx) return (TRUE); } +namespace { // anonymous + +struct is_artifact_p : public boost::static_visitor<bool> { + + bool operator ()(store_item_filter_by_k_idx f) const + { + auto const &k_info = game->edit_data.k_info; + return bool(k_info[f.k_idx].flags & TR_NORM_ART); + } + + bool operator ()(store_item_filter_by_tval) const + { + return false; + } +}; + +class choose_k_idx : public boost::static_visitor<int> { + + int m_level; + +public: + + explicit choose_k_idx(int level) + : m_level(level) + { + } + + int operator ()(store_item_filter_by_k_idx f) const + { + return f.k_idx; + } + + int operator ()(store_item_filter_by_tval f) const + { + auto const &st_info = game->edit_data.st_info; + auto &alloc = game->alloc; + + /* No themes */ + init_match_theme(obj_theme::no_theme()); + + /* Activate restriction */ + get_obj_num_hook = kind_is_storeok; + store_tval = f.tval; + + /* Do we forbid too shallow items ? */ + if (st_info[st_ptr->st_idx].flags & STF_FORCE_LEVEL) + { + store_level = m_level; + } + else + { + store_level = 0; + } + + /* Prepare allocation table */ + get_obj_num_prep(); + + /* Get it! */ + auto k_idx = get_obj_num(m_level); + + /* Invalidate the cached allocation table */ + alloc.kind_table_valid = false; + + return k_idx; + } +}; + +} // namespace (anonymous) + /* * Creates a random item and gives it to a store * This algorithm needs to be rethought. A lot. @@ -1193,22 +1262,21 @@ static void store_create() auto const &k_info = game->edit_data.k_info; auto &alloc = game->alloc; - int i = 0, tries, level = 0; + int k_idx = -1; + int level = 0; object_type forge; object_type *q_ptr = NULL; bool_ obj_all_done = FALSE; - /* Paranoia -- no room left */ if (st_ptr->stock.size() >= st_ptr->stock_size) { return; } - /* Hack -- consider up to four items */ - for (tries = 0; tries < 4; tries++) + for (int tries = 0; tries < 4; tries++) { obj_all_done = FALSE; @@ -1262,28 +1330,31 @@ static void store_create() /* Pick a level for object/magic */ level = return_level(); - /* Random item (usually of given level) */ - i = get_obj_num(level); + /* Choose a k_info index */ + k_idx = get_obj_num(level); + if (k_idx <= 0) + { + continue; + } /* Invalidate the cached allocation table */ alloc.kind_table_valid = false; - /* Handle failure */ - if (!i) continue; - } /* Normal Store */ else { /* Hack -- Pick an item to sell */ - auto const &item = st_info[st_ptr->st_idx].items[rand_int(st_info[st_ptr->st_idx].items.size())]; - i = item.kind; + auto const &item = *uniform_element(st_info[st_ptr->st_idx].items); + auto filter = item.filter; auto chance = item.chance; /* Don't allow k_info artifacts */ - if ((i <= 10000) && (k_info[i].flags & TR_NORM_ART)) + if (boost::apply_visitor(is_artifact_p(), filter)) + { continue; + } /* Does it passes the rarity check ? */ if (!magik(chance)) continue; @@ -1291,55 +1362,30 @@ static void store_create() /* Hack -- fake level for apply_magic() */ level = return_level(); - /* Hack -- i > 10000 means it's a tval and all svals are allowed */ - if (i > 10000) + /* Choose the k_info index */ + k_idx = boost::apply_visitor(choose_k_idx(level), filter); + if (k_idx <= 0) { - /* No themes */ - init_match_theme(obj_theme::no_theme()); - - /* Activate restriction */ - get_obj_num_hook = kind_is_storeok; - store_tval = i - 10000; - - /* Do we forbid too shallow items ? */ - if (st_info[st_ptr->st_idx].flags & STF_FORCE_LEVEL) - { - store_level = level; - } - else - { - store_level = 0; - } - - /* Prepare allocation table */ - get_obj_num_prep(); - - /* Get it ! */ - i = get_obj_num(level); - - /* Invalidate the cached allocation table */ - alloc.kind_table_valid = false; + continue; } - - if (!i) continue; } /* Only if not already done */ if (!obj_all_done) { /* Don't allow k_info artifacts */ - if (k_info[i].flags & TR_NORM_ART) + if (k_info[k_idx].flags & TR_NORM_ART) continue; /* Don't allow artifacts */ - if (k_info[i].flags & TR_INSTA_ART) + if (k_info[k_idx].flags & TR_INSTA_ART) continue; /* Get local object */ q_ptr = &forge; /* Create a new object of the chosen kind */ - object_prep(q_ptr, i); + object_prep(q_ptr, k_idx); /* Apply some "low-level" magic (no artifacts) */ apply_magic(q_ptr, level, FALSE, FALSE, FALSE); diff --git a/src/store_item.hpp b/src/store_item.hpp index 62d3f2a9..1f00802a 100644 --- a/src/store_item.hpp +++ b/src/store_item.hpp @@ -2,17 +2,58 @@ #include "h-basic.h" +#include <boost/variant.hpp> + +struct store_item_filter_by_k_idx +{ + s16b k_idx = -1; +}; + +struct store_item_filter_by_tval +{ + s16b tval = -1; +}; + +using store_item_filter_t = boost::variant<store_item_filter_by_k_idx, store_item_filter_by_tval>; + struct store_item { /** - * Legal item kinds; if > 10000, designates (TVAL - 10000) and any SVAL. - * Otherwise designates an entry in k_info.txt. + * Filter for the store items. */ - s16b kind = 0; + store_item_filter_t filter; /** * Percentage chance of generation if the entry is chosen. */ s16b chance = 0; + /** + * Create a store item based on k_info index. + */ + static store_item k_idx(s16b idx, s16b chance) + { + store_item_filter_by_k_idx k; + k.k_idx = idx; + + store_item i; + i.chance = chance; + i.filter = k; + return i; + } + + /** + * Create a store item based on TVAL. + */ + static store_item tval(s16b tval, s16b chance) + { + store_item_filter_by_tval k; + k.tval = tval; + + store_item i; + i.chance = chance; + i.filter = k; + return i; + } + }; |