summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/init1.cc19
-rw-r--r--src/store.cc134
-rw-r--r--src/store_item.hpp47
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;
+ }
+
};