OSDN Git Service

[Refactor] #40233 Somefunctions moved from store.c/h to store-util.c/h and separated...
authorHourier <hourier@users.sourceforge.jp>
Sun, 22 Mar 2020 12:58:35 +0000 (21:58 +0900)
committerHourier <hourier@users.sourceforge.jp>
Sun, 22 Mar 2020 12:58:35 +0000 (21:58 +0900)
19 files changed:
Hengband_vcs2017/Hengband/Hengband.vcxproj
Hengband_vcs2017/Hengband/Hengband.vcxproj.filters
src/Makefile.am
src/character-dump.c
src/cmd/cmd-dump.c
src/core.c
src/init.c
src/load.c
src/market/black-market.c [new file with mode: 0644]
src/market/black-market.h [new file with mode: 0644]
src/market/say-comments.c
src/market/say-comments.h
src/market/store-util.c
src/market/store-util.h
src/player/process-death.c
src/save.c
src/store.c
src/store.h
src/wizard1.c

index 0fad116..7b4a4cb 100644 (file)
     <ClCompile Include="..\..\src\io\tokenizer.c" />\r
     <ClCompile Include="..\..\src\io\write-diary.c" />\r
     <ClCompile Include="..\..\src\market\articles-on-sale.c" />\r
+    <ClCompile Include="..\..\src\market\black-market.c" />\r
     <ClCompile Include="..\..\src\market\gold-magnification-table.c" />\r
     <ClCompile Include="..\..\src\market\poker.c" />\r
     <ClCompile Include="..\..\src\market\say-comments.c" />\r
     <ClInclude Include="..\..\src\io\tokenizer.h" />\r
     <ClInclude Include="..\..\src\io\write-diary.h" />\r
     <ClInclude Include="..\..\src\market\articles-on-sale.h" />\r
+    <ClInclude Include="..\..\src\market\black-market.h" />\r
     <ClInclude Include="..\..\src\market\gold-magnification-table.h" />\r
     <ClInclude Include="..\..\src\market\poker.h" />\r
     <ClInclude Include="..\..\src\market\say-comments.h" />\r
index d8060c0..f2c60fc 100644 (file)
     <ClCompile Include="..\..\src\market\gold-magnification-table.c">
       <Filter>market</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\market\black-market.c">
+      <Filter>market</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\src\gamevalue.h" />
     <ClInclude Include="..\..\src\market\gold-magnification-table.h">
       <Filter>market</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\src\market\black-market.h">
+      <Filter>market</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="..\..\src\wall.bmp" />
index bfd676c..5ac6412 100644 (file)
@@ -14,6 +14,7 @@ hengband_SOURCES = \
        market/poker.c market/poker.h market/store-owners.c market/store-owners.h \
        market/store-owner-comments.c market/store-owner-comments.h \
        market/articles-on-sale.c market/articles-on-sale.h \
+       market/black-market.c market/black-market.h \
        market/say-comments.c market/say-comments.h \
        market/store-util.c market/store-util.h \
        market/gold-magnification-table.c market/gold-magnification-table.h \
index af1de28..2c1b71f 100644 (file)
@@ -498,38 +498,38 @@ static void dump_aux_equipment_inventory(player_type *creature_ptr, FILE *fff)
  */
 static void dump_aux_home_museum(player_type *creature_ptr, FILE *fff)
 {
-       store_type  *st_ptr;
-       st_ptr = &town_info[1].store[STORE_HOME];
+       store_type  *store_ptr;
+       store_ptr = &town_info[1].store[STORE_HOME];
 
        GAME_TEXT o_name[MAX_NLEN];
-       if (st_ptr->stock_num)
+       if (store_ptr->stock_num)
        {
                fprintf(fff, _("  [我が家のアイテム]\n", "  [Home Inventory]\n"));
 
                TERM_LEN x = 1;
-               for (int i = 0; i < st_ptr->stock_num; i++)
+               for (int i = 0; i < store_ptr->stock_num; i++)
                {
                        if ((i % 12) == 0)
                                fprintf(fff, _("\n ( %d ページ )\n", "\n ( page %d )\n"), x++);
-                       object_desc(creature_ptr, o_name, &st_ptr->stock[i], 0);
+                       object_desc(creature_ptr, o_name, &store_ptr->stock[i], 0);
                        fprintf(fff, "%c) %s\n", I2A(i % 12), o_name);
                }
 
                fprintf(fff, "\n\n");
        }
 
-       st_ptr = &town_info[1].store[STORE_MUSEUM];
+       store_ptr = &town_info[1].store[STORE_MUSEUM];
 
-       if (st_ptr->stock_num == 0) return;
+       if (store_ptr->stock_num == 0) return;
 
        fprintf(fff, _("  [博物館のアイテム]\n", "  [Museum]\n"));
 
        TERM_LEN x = 1;
-       for (int i = 0; i < st_ptr->stock_num; i++)
+       for (int i = 0; i < store_ptr->stock_num; i++)
        {
 #ifdef JP
                if ((i % 12) == 0) fprintf(fff, "\n ( %d ページ )\n", x++);
-               object_desc(creature_ptr, o_name, &st_ptr->stock[i], 0);
+               object_desc(creature_ptr, o_name, &store_ptr->stock[i], 0);
                fprintf(fff, "%c) %s\n", I2A(i % 12), o_name);
 #else
                if ((i % 12) == 0) fprintf(fff, "\n ( page %d )\n", x++);
index a88780e..51fa85e 100644 (file)
@@ -641,7 +641,7 @@ static void do_cmd_knowledge_inven(player_type *creature_ptr)
 {
        FILE *fff;
        GAME_TEXT file_name[1024];
-       store_type  *st_ptr;
+       store_type *store_ptr;
        OBJECT_TYPE_VALUE tval;
        int j = 0;
 
@@ -676,11 +676,11 @@ static void do_cmd_knowledge_inven(player_type *creature_ptr)
                        do_cmd_knowledge_inven_aux(creature_ptr, fff, &creature_ptr->inventory_list[i], &j, tval, where);
                }
 
-               st_ptr = &town_info[1].store[STORE_HOME];
+               store_ptr = &town_info[1].store[STORE_HOME];
                strcpy(where, _("家", "H "));
-               for (int i = 0; i < st_ptr->stock_num; i++)
+               for (int i = 0; i < store_ptr->stock_num; i++)
                {
-                       do_cmd_knowledge_inven_aux(creature_ptr, fff, &st_ptr->stock[i], &j, tval, where);
+                       do_cmd_knowledge_inven_aux(creature_ptr, fff, &store_ptr->stock[i], &j, tval, where);
                }
        }
 
@@ -3155,10 +3155,10 @@ static void do_cmd_knowledge_home(player_type *player_ptr)
                return;
        }
 
-       store_type *st_ptr;
-       st_ptr = &town_info[1].store[STORE_HOME];
+       store_type *store_ptr;
+       store_ptr = &town_info[1].store[STORE_HOME];
 
-       if (st_ptr->stock_num)
+       if (store_ptr->stock_num)
        {
 #ifdef JP
                TERM_LEN x = 1;
@@ -3166,11 +3166,11 @@ static void do_cmd_knowledge_home(player_type *player_ptr)
                fprintf(fff, _("  [ 我が家のアイテム ]\n", "  [Home Inventory]\n"));
                concptr paren = ")";
                GAME_TEXT o_name[MAX_NLEN];
-               for (int i = 0; i < st_ptr->stock_num; i++)
+               for (int i = 0; i < store_ptr->stock_num; i++)
                {
 #ifdef JP
                        if ((i % 12) == 0) fprintf(fff, "\n ( %d ページ )\n", x++);
-                       object_desc(player_ptr, o_name, &st_ptr->stock[i], 0);
+                       object_desc(player_ptr, o_name, &store_ptr->stock[i], 0);
                        if (strlen(o_name) <= 80 - 3)
                        {
                                fprintf(fff, "%c%s %s\n", I2A(i % 12), paren, o_name);
@@ -3187,7 +3187,7 @@ static void do_cmd_knowledge_home(player_type *player_ptr)
                                fprintf(fff, "   %.77s\n", o_name + n);
                        }
 #else
-                       object_desc(player_ptr, o_name, &st_ptr->stock[i], 0);
+                       object_desc(player_ptr, o_name, &store_ptr->stock[i], 0);
                        fprintf(fff, "%c%s %s\n", I2A(i % 12), paren, o_name);
 #endif
                }
index 1286dfc..1f7321f 100644 (file)
@@ -4629,18 +4629,18 @@ void prevent_turn_overflow(player_type *player_ptr)
        {
                for (int j = 0; j < MAX_STORES; j++)
                {
-                       store_type *st_ptr = &town_info[i].store[j];
+                       store_type *store_ptr = &town_info[i].store[j];
 
-                       if (st_ptr->last_visit > -10L * TURNS_PER_TICK * STORE_TICKS)
+                       if (store_ptr->last_visit > -10L * TURNS_PER_TICK * STORE_TICKS)
                        {
-                               st_ptr->last_visit -= rollback_turns;
-                               if (st_ptr->last_visit < -10L * TURNS_PER_TICK * STORE_TICKS) st_ptr->last_visit = -10L * TURNS_PER_TICK * STORE_TICKS;
+                               store_ptr->last_visit -= rollback_turns;
+                               if (store_ptr->last_visit < -10L * TURNS_PER_TICK * STORE_TICKS) store_ptr->last_visit = -10L * TURNS_PER_TICK * STORE_TICKS;
                        }
 
-                       if (st_ptr->store_open)
+                       if (store_ptr->store_open)
                        {
-                               st_ptr->store_open -= rollback_turns;
-                               if (st_ptr->store_open < 1) st_ptr->store_open = 1;
+                               store_ptr->store_open -= rollback_turns;
+                               if (store_ptr->store_open < 1) store_ptr->store_open = 1;
                        }
                }
        }
index 87f9304..0e27a8d 100644 (file)
@@ -764,7 +764,7 @@ static errr init_towns(void)
                for (int j = 0; j < MAX_STORES; j++)
                {
                        /* Access the store */
-                       store_type *st_ptr = &town_info[i].store[j];
+                       store_type *store_ptr = &town_info[i].store[j];
 
                        if ((i > 1) && (j == STORE_MUSEUM || j == STORE_HOME)) continue;
 
@@ -776,28 +776,28 @@ static errr init_towns(void)
                         */
                        if (j == STORE_HOME)
                        {
-                               st_ptr->stock_size = (STORE_INVEN_MAX * 10);
+                               store_ptr->stock_size = (STORE_INVEN_MAX * 10);
                        }
                        else if (j == STORE_MUSEUM)
                        {
-                               st_ptr->stock_size = (STORE_INVEN_MAX * 50);
+                               store_ptr->stock_size = (STORE_INVEN_MAX * 50);
                        }
                        else
                        {
-                               st_ptr->stock_size = STORE_INVEN_MAX;
+                               store_ptr->stock_size = STORE_INVEN_MAX;
                        }
 
                        /* Allocate the stock */
-                       C_MAKE(st_ptr->stock, st_ptr->stock_size, object_type);
+                       C_MAKE(store_ptr->stock, store_ptr->stock_size, object_type);
 
                        /* No table for the black market or home */
                        if ((j == STORE_BLACK) || (j == STORE_HOME) || (j == STORE_MUSEUM)) continue;
 
                        /* Assume full table */
-                       st_ptr->table_size = STORE_CHOICES;
+                       store_ptr->table_size = STORE_CHOICES;
 
                        /* Allocate the stock */
-                       C_MAKE(st_ptr->table, st_ptr->table_size, s16b);
+                       C_MAKE(store_ptr->table, store_ptr->table_size, s16b);
 
                        /* Scan the choices */
                        for (int k = 0; k < STORE_CHOICES; k++)
@@ -821,7 +821,7 @@ static errr init_towns(void)
                                if (k_idx == max_k_idx) continue;
 
                                /* Add that item index to the table */
-                               st_ptr->table[st_ptr->table_num++] = k_idx;
+                               store_ptr->table[store_ptr->table_num++] = k_idx;
                        }
                }
        }
index 08543c2..d15f92e 100644 (file)
@@ -1281,7 +1281,7 @@ static void rd_lore(MONRACE_IDX r_idx)
 /*!
  * @brief 店置きのアイテムオブジェクトを読み込む / Add the item "o_ptr" to the inventory of the "Home"
  * @param player_ptr プレーヤーへの参照ポインタ
- * @param st_ptr 店舗の参照ポインタ
+ * @param store_ptr 店舗の参照ポインタ
  * @param o_ptr アイテムオブジェクト参照ポインタ
  * @return なし
  * @details
@@ -1292,34 +1292,34 @@ static void rd_lore(MONRACE_IDX r_idx)
  * Also note that it may not correctly "adapt" to "knowledge" bacoming
  * known, the player may have to pick stuff up and drop it again.
  */
-static void home_carry(player_type *player_ptr, store_type *st_ptr, object_type *o_ptr)
+static void home_carry(player_type *player_ptr, store_type *store_ptr, object_type *o_ptr)
 {
-       for (int i = 0; i < st_ptr->stock_num; i++)
+       for (int i = 0; i < store_ptr->stock_num; i++)
        {
                object_type *j_ptr;
-               j_ptr = &st_ptr->stock[i];
+               j_ptr = &store_ptr->stock[i];
                if (!object_similar(j_ptr, o_ptr)) continue;
 
                object_absorb(j_ptr, o_ptr);
                return;
        }
 
-       if (st_ptr->stock_num >= STORE_INVEN_MAX * 10) return;
+       if (store_ptr->stock_num >= STORE_INVEN_MAX * 10) return;
 
        s32b value = object_value(o_ptr);
        int slot;
-       for (slot = 0; slot < st_ptr->stock_num; slot++)
+       for (slot = 0; slot < store_ptr->stock_num; slot++)
        {
-               if (object_sort_comp(o_ptr, value, &st_ptr->stock[slot])) break;
+               if (object_sort_comp(o_ptr, value, &store_ptr->stock[slot])) break;
        }
 
-       for (int i = st_ptr->stock_num; i > slot; i--)
+       for (int i = store_ptr->stock_num; i > slot; i--)
        {
-               st_ptr->stock[i] = st_ptr->stock[i - 1];
+               store_ptr->stock[i] = store_ptr->stock[i - 1];
        }
 
-       st_ptr->stock_num++;
-       st_ptr->stock[slot] = *o_ptr;
+       store_ptr->stock_num++;
+       store_ptr->stock[slot] = *o_ptr;
        chg_virtue(player_ptr, V_SACRIFICE, -1);
 }
 
@@ -1333,23 +1333,23 @@ static void home_carry(player_type *player_ptr, store_type *st_ptr, object_type
  */
 static errr rd_store(player_type *player_ptr, int town_number, int store_number)
 {
-       store_type *st_ptr;
+       store_type *store_ptr;
        bool sort = FALSE;
        if (z_older_than(10, 3, 3) && (store_number == STORE_HOME))
        {
-               st_ptr = &town_info[1].store[store_number];
-               if (st_ptr->stock_num) sort = TRUE;
+               store_ptr = &town_info[1].store[store_number];
+               if (store_ptr->stock_num) sort = TRUE;
        }
        else
        {
-               st_ptr = &town_info[town_number].store[store_number];
+               store_ptr = &town_info[town_number].store[store_number];
        }
 
        byte own;
        byte tmp8u;
        s16b num;
-       rd_s32b(&st_ptr->store_open);
-       rd_s16b(&st_ptr->insult_cur);
+       rd_s32b(&store_ptr->store_open);
+       rd_s16b(&store_ptr->insult_cur);
        rd_byte(&own);
        if (z_older_than(11, 0, 4))
        {
@@ -1361,11 +1361,11 @@ static errr rd_store(player_type *player_ptr, int town_number, int store_number)
                rd_s16b(&num);
        }
 
-       rd_s16b(&st_ptr->good_buy);
-       rd_s16b(&st_ptr->bad_buy);
+       rd_s16b(&store_ptr->good_buy);
+       rd_s16b(&store_ptr->bad_buy);
 
-       rd_s32b(&st_ptr->last_visit);
-       st_ptr->owner = own;
+       rd_s32b(&store_ptr->last_visit);
+       store_ptr->owner = own;
 
        for (int j = 0; j < num; j++)
        {
@@ -1376,17 +1376,17 @@ static errr rd_store(player_type *player_ptr, int town_number, int store_number)
 
                rd_item(q_ptr);
 
-               bool is_valid_item = st_ptr->stock_num < (store_number == STORE_HOME ? STORE_INVEN_MAX * 10 : store_number == STORE_MUSEUM ? STORE_INVEN_MAX * 50 : STORE_INVEN_MAX);
+               bool is_valid_item = store_ptr->stock_num < (store_number == STORE_HOME ? STORE_INVEN_MAX * 10 : store_number == STORE_MUSEUM ? STORE_INVEN_MAX * 50 : STORE_INVEN_MAX);
                if (!is_valid_item) continue;
 
                if (sort)
                {
-                       home_carry(player_ptr, st_ptr, q_ptr);
+                       home_carry(player_ptr, store_ptr, q_ptr);
                }
                else
                {
-                       int k = st_ptr->stock_num++;
-                       object_copy(&st_ptr->stock[k], q_ptr);
+                       int k = store_ptr->stock_num++;
+                       object_copy(&store_ptr->stock[k], q_ptr);
                }
        }
 
diff --git a/src/market/black-market.c b/src/market/black-market.c
new file mode 100644 (file)
index 0000000..9eaa76b
--- /dev/null
@@ -0,0 +1,41 @@
+#include "angband.h"
+#include "floor-town.h"
+#include "object-hook.h"
+#include "market/black-market.h"
+#include "market/store-owners.h"
+#include "market/store-util.h"
+
+/*!
+ * @brief ブラックマーケット用の無価値品の排除判定 /
+ * This function will keep 'crap' out of the black market.
+ * @param player_ptr プレーヤーへの参照ポインタ
+ * @param o_ptr 判定したいオブジェクトの構造体参照ポインタ
+ * @return ブラックマーケットにとって無価値な品ならばTRUEを返す
+ * @details
+ * <pre>
+ * Crap is defined as any item that is "available" elsewhere
+ * Based on a suggestion by "Lee Vogt" <lvogt@cig.mcel.mot.com>
+ * </pre>
+ */
+bool black_market_crap(player_type *player_ptr, object_type *o_ptr)
+{
+       if (object_is_ego(o_ptr)) return FALSE;
+
+       if (o_ptr->to_a > 0) return FALSE;
+       if (o_ptr->to_h > 0) return FALSE;
+       if (o_ptr->to_d > 0) return FALSE;
+
+       for (int i = 0; i < MAX_STORES; i++)
+       {
+               if (i == STORE_HOME) continue;
+               if (i == STORE_MUSEUM) continue;
+
+               for (int j = 0; j < town_info[player_ptr->town_num].store[i].stock_num; j++)
+               {
+                       object_type *j_ptr = &town_info[player_ptr->town_num].store[i].stock[j];
+                       if (o_ptr->k_idx == j_ptr->k_idx) return TRUE;
+               }
+       }
+
+       return FALSE;
+}
diff --git a/src/market/black-market.h b/src/market/black-market.h
new file mode 100644 (file)
index 0000000..fc0a918
--- /dev/null
@@ -0,0 +1,3 @@
+#pragma once
+
+bool black_market_crap(player_type *player_ptr, object_type *o_ptr);
index e7047b4..596aae7 100644 (file)
@@ -6,7 +6,6 @@
 #include "rumor.h"
 
 #define RUMOR_CHANCE 8
-int cur_store_num = 0;
 
 /*!
  * @brief 取引成功時の店主のメッセージ処理 /
index cb72e17..2de542d 100644 (file)
@@ -1,7 +1,5 @@
 #pragma once
 
-extern int cur_store_num;
-
 void say_comment_1(player_type *player_ptr);
 void say_comment_2(PRICE value, int annoyed);
 void say_comment_3(PRICE value, int annoyed);
index 6a2fa41..3436731 100644 (file)
@@ -1,5 +1,645 @@
-#include "market/store-util.h"
+#include "angband.h"
+#include "market/store-util.h"
+#include "object-hook.h"
+#include "objectkind.h"
+
+int cur_store_num = 0;
+store_type *st_ptr = NULL;
+
+/*!
+ * @brief 店舗のオブジェクト数を増やす /
+ * Add the item "o_ptr" to a real stores inventory.
+ * @param item 増やしたいアイテムのID
+ * @param num 増やしたい数
+ * @return なし
+ * @details
+ * <pre>
+ * Increase, by a given amount, the number of a certain item
+ * in a certain store. This can result in zero items.
+ * </pre>
+ * @todo numは本来ITEM_NUMBER型にしたい。
+ */
+void store_item_increase(INVENTORY_IDX item, int num)
+{
+       object_type *o_ptr;
+       o_ptr = &st_ptr->stock[item];
+       int cnt = o_ptr->number + num;
+       if (cnt > 255) cnt = 255;
+       else if (cnt < 0) cnt = 0;
+
+       num = cnt - o_ptr->number;
+       o_ptr->number += (ITEM_NUMBER)num;
+}
+
+
+/*!
+ * @brief 店舗のオブジェクト数を削除する /
+ * Remove a slot if it is empty
+ * @param item 削除したいアイテムのID
+ * @return なし
+ */
+void store_item_optimize(INVENTORY_IDX item)
+{
+       object_type *o_ptr;
+       o_ptr = &st_ptr->stock[item];
+       if (!o_ptr->k_idx) return;
+       if (o_ptr->number) return;
+
+       st_ptr->stock_num--;
+       for (int j = item; j < st_ptr->stock_num; j++)
+       {
+               st_ptr->stock[j] = st_ptr->stock[j + 1];
+       }
+
+       object_wipe(&st_ptr->stock[st_ptr->stock_num]);
+}
+
+
+/*!
+ * @brief 店舗の品揃え変化のためにアイテムを削除する /
+ * Attempt to delete (some of) a random item from the store
+ * @return なし
+ * @details
+ * <pre>
+ * Hack -- we attempt to "maintain" piles of items when possible.
+ * </pre>
+ */
+void store_delete(void)
+{
+       INVENTORY_IDX what = (INVENTORY_IDX)randint0(st_ptr->stock_num);
+       int num = st_ptr->stock[what].number;
+       if (randint0(100) < 50) num = (num + 1) / 2;
+       if (randint0(100) < 50) num = 1;
+       if ((st_ptr->stock[what].tval == TV_ROD) || (st_ptr->stock[what].tval == TV_WAND))
+       {
+               st_ptr->stock[what].pval -= num * st_ptr->stock[what].pval / st_ptr->stock[what].number;
+       }
+
+       store_item_increase(what, -num);
+       store_item_optimize(what);
+}
+
+
+/*!
+ * @brief 安価な消耗品の販売数を増やし、低確率で割引にする /
+ * Certain "cheap" objects should be created in "piles"
+ * @param o_ptr 店舗に並べるオブジェクト構造体の参照ポインタ
+ * @return なし
+ * @details
+ * <pre>
+ * Some objects can be sold at a "discount" (in small piles)
+ * </pre>
+ */
+static void mass_produce(object_type *o_ptr)
+{
+       int size = 1;
+       PRICE cost = object_value(o_ptr);
+       switch (o_ptr->tval)
+       {
+       case TV_FOOD:
+       case TV_FLASK:
+       case TV_LITE:
+       {
+               if (cost <= 5L) size += damroll(3, 5);
+               if (cost <= 20L) size += damroll(3, 5);
+               if (cost <= 50L) size += damroll(2, 2);
+               break;
+       }
+       case TV_POTION:
+       case TV_SCROLL:
+       {
+               if (cost <= 60L) size += damroll(3, 5);
+               if (cost <= 240L) size += damroll(1, 5);
+               if (o_ptr->sval == SV_SCROLL_STAR_IDENTIFY) size += damroll(3, 5);
+               if (o_ptr->sval == SV_SCROLL_STAR_REMOVE_CURSE) size += damroll(1, 4);
+               break;
+       }
+       case TV_LIFE_BOOK:
+       case TV_SORCERY_BOOK:
+       case TV_NATURE_BOOK:
+       case TV_CHAOS_BOOK:
+       case TV_DEATH_BOOK:
+       case TV_TRUMP_BOOK:
+       case TV_ARCANE_BOOK:
+       case TV_CRAFT_BOOK:
+       case TV_DAEMON_BOOK:
+       case TV_CRUSADE_BOOK:
+       case TV_MUSIC_BOOK:
+       case TV_HISSATSU_BOOK:
+       case TV_HEX_BOOK:
+       {
+               if (cost <= 50L) size += damroll(2, 3);
+               if (cost <= 500L) size += damroll(1, 3);
+               break;
+       }
+       case TV_SOFT_ARMOR:
+       case TV_HARD_ARMOR:
+       case TV_SHIELD:
+       case TV_GLOVES:
+       case TV_BOOTS:
+       case TV_CLOAK:
+       case TV_HELM:
+       case TV_CROWN:
+       case TV_SWORD:
+       case TV_POLEARM:
+       case TV_HAFTED:
+       case TV_DIGGING:
+       case TV_BOW:
+       {
+               if (object_is_artifact(o_ptr)) break;
+               if (object_is_ego(o_ptr)) break;
+               if (cost <= 10L) size += damroll(3, 5);
+               if (cost <= 100L) size += damroll(3, 5);
+               break;
+       }
+       case TV_SPIKE:
+       case TV_SHOT:
+       case TV_ARROW:
+       case TV_BOLT:
+       {
+               if (cost <= 5L) size += damroll(5, 5);
+               if (cost <= 50L) size += damroll(5, 5);
+               if (cost <= 500L) size += damroll(5, 5);
+               break;
+       }
+       case TV_FIGURINE:
+       {
+               if (cost <= 100L) size += damroll(2, 2);
+               if (cost <= 1000L) size += damroll(2, 2);
+               break;
+       }
+       case TV_CAPTURE:
+       case TV_STATUE:
+       case TV_CARD:
+       {
+               size = 1;
+               break;
+       }
+
+       /*
+        * Because many rods (and a few wands and staffs) are useful mainly
+        * in quantity, the Black Market will occasionally have a bunch of
+        * one kind. -LM-
+        */
+       case TV_ROD:
+       case TV_WAND:
+       case TV_STAFF:
+       {
+               if ((cur_store_num == STORE_BLACK) && one_in_(3))
+               {
+                       if (cost < 1601L) size += damroll(1, 5);
+                       else if (cost < 3201L) size += damroll(1, 3);
+               }
+               break;
+       }
+       }
+
+       DISCOUNT_RATE discount = 0;
+       if (cost < 5)
+       {
+               discount = 0;
+       }
+       else if (one_in_(25))
+       {
+               discount = 25;
+       }
+       else if (one_in_(150))
+       {
+               discount = 50;
+       }
+       else if (one_in_(300))
+       {
+               discount = 75;
+       }
+       else if (one_in_(500))
+       {
+               discount = 90;
+       }
+
+       if (o_ptr->art_name)
+       {
+               discount = 0;
+       }
+
+       o_ptr->discount = discount;
+       o_ptr->number = size - (size * discount / 100);
+       if ((o_ptr->tval == TV_ROD) || (o_ptr->tval == TV_WAND))
+       {
+               o_ptr->pval *= (PARAMETER_VALUE)o_ptr->number;
+       }
+}
+
+
+/*!
+ * @brief 店舗の品揃え変化のためにアイテムを追加する /
+ * Creates a random item and gives it to a store
+ * @param player_ptr プレーヤーへの参照ポインタ
+ * @return なし
+ * @details
+ * <pre>
+ * This algorithm needs to be rethought.  A lot.
+ * Currently, "normal" stores use a pre-built array.
+ * Note -- the "level" given to "obj_get_num()" is a "favored"
+ * level, that is, there is a much higher chance of getting
+ * items with a level approaching that of the given level...
+ * Should we check for "permission" to have the given item?
+ * </pre>
+ */
+void store_create(player_type *player_ptr, bool (*black_market_crap)(player_type*, object_type*))
+{
+       if (st_ptr->stock_num >= st_ptr->stock_size) return;
+
+       for (int tries = 0; tries < 4; tries++)
+       {
+               OBJECT_IDX i;
+               DEPTH level;
+               if (cur_store_num == STORE_BLACK)
+               {
+                       /* Pick a level for object/magic */
+                       level = 25 + randint0(25);
+
+                       /* Random item (usually of given level) */
+                       i = get_obj_num(player_ptr, level, 0x00000000);
+
+                       /* Handle failure */
+                       if (i == 0) continue;
+               }
+               else
+               {
+                       i = st_ptr->table[randint0(st_ptr->table_num)];
+                       level = rand_range(1, STORE_OBJ_LEVEL);
+               }
+
+               object_type forge;
+               object_type *q_ptr;
+               q_ptr = &forge;
+               object_prep(q_ptr, i);
+               apply_magic(player_ptr, q_ptr, level, AM_NO_FIXED_ART);
+               if (!store_will_buy(q_ptr)) continue;
+
+               if (q_ptr->tval == TV_LITE)
+               {
+                       if (q_ptr->sval == SV_LITE_TORCH) q_ptr->xtra4 = FUEL_TORCH / 2;
+                       if (q_ptr->sval == SV_LITE_LANTERN) q_ptr->xtra4 = FUEL_LAMP / 2;
+               }
+
+               object_known(q_ptr);
+               q_ptr->ident |= IDENT_STORE;
+               if (q_ptr->tval == TV_CHEST) continue;
+
+               if (cur_store_num == STORE_BLACK)
+               {
+                       if (black_market_crap(player_ptr, q_ptr)) continue;
+                       if (object_value(q_ptr) < 10) continue;
+               }
+               else
+               {
+                       if (object_value(q_ptr) <= 0) continue;
+               }
+
+               mass_produce(q_ptr);
+               (void)store_carry(q_ptr);
+               break;
+       }
+}
+
+
+/*!
+ * @brief オブジェクトが祝福されているかの判定を返す /
+ * @param o_ptr 判定したいオブジェクト構造体の参照ポインタ
+ * @return アイテムが祝福されたアイテムならばTRUEを返す
+ */
+static bool is_blessed_item(object_type *o_ptr)
+{
+       BIT_FLAGS flgs[TR_FLAG_SIZE];
+       object_flags(o_ptr, flgs);
+       if (have_flag(flgs, TR_BLESSED)) return TRUE;
+       else return FALSE;
+}
+
+
+/*!
+ * @brief オブジェクトが所定の店舗で引き取れるかどうかを返す /
+ * Determine if the current store will purchase the given item
+ * @param o_ptr 判定したいオブジェクト構造体の参照ポインタ
+ * @return アイテムが買い取れるならばTRUEを返す
+ * @note
+ * Note that a shop-keeper must refuse to buy "worthless" items
+ */
+bool store_will_buy(object_type *o_ptr)
+{
+       if ((cur_store_num == STORE_HOME) || (cur_store_num == STORE_MUSEUM)) return TRUE;
+       switch (cur_store_num)
+       {
+       case STORE_GENERAL:
+       {
+               switch (o_ptr->tval)
+               {
+               case TV_POTION:
+                       if (o_ptr->sval != SV_POTION_WATER) return FALSE;
+
+               case TV_WHISTLE:
+               case TV_FOOD:
+               case TV_LITE:
+               case TV_FLASK:
+               case TV_SPIKE:
+               case TV_SHOT:
+               case TV_ARROW:
+               case TV_BOLT:
+               case TV_DIGGING:
+               case TV_CLOAK:
+               case TV_BOTTLE:
+               case TV_FIGURINE:
+               case TV_STATUE:
+               case TV_CAPTURE:
+               case TV_CARD:
+                       break;
+               default:
+                       return FALSE;
+               }
+
+               break;
+       }
+       case STORE_ARMOURY:
+       {
+               switch (o_ptr->tval)
+               {
+               case TV_BOOTS:
+               case TV_GLOVES:
+               case TV_CROWN:
+               case TV_HELM:
+               case TV_SHIELD:
+               case TV_CLOAK:
+               case TV_SOFT_ARMOR:
+               case TV_HARD_ARMOR:
+               case TV_DRAG_ARMOR:
+                       break;
+               default:
+                       return FALSE;
+               }
+
+               break;
+       }
+       case STORE_WEAPON:
+       {
+               switch (o_ptr->tval)
+               {
+               case TV_SHOT:
+               case TV_BOLT:
+               case TV_ARROW:
+               case TV_BOW:
+               case TV_DIGGING:
+               case TV_POLEARM:
+               case TV_SWORD:
+               case TV_HISSATSU_BOOK:
+                       break;
+               case TV_HAFTED:
+               {
+                       if (o_ptr->sval == SV_WIZSTAFF) return FALSE;
+               }
+               break;
+               default:
+                       return FALSE;
+               }
+
+               break;
+       }
+       case STORE_TEMPLE:
+       {
+               switch (o_ptr->tval)
+               {
+               case TV_LIFE_BOOK:
+               case TV_CRUSADE_BOOK:
+               case TV_SCROLL:
+               case TV_POTION:
+               case TV_HAFTED:
+               {
+                       break;
+               }
+               case TV_FIGURINE:
+               case TV_STATUE:
+               {
+                       monster_race *r_ptr = &r_info[o_ptr->pval];
+                       if (!(r_ptr->flags3 & RF3_EVIL))
+                       {
+                               if (r_ptr->flags3 & RF3_GOOD) break;
+                               if (r_ptr->flags3 & RF3_ANIMAL) break;
+                               if (my_strchr("?!", r_ptr->d_char)) break;
+                       }
+               }
+               case TV_POLEARM:
+               case TV_SWORD:
+               {
+                       if (is_blessed_item(o_ptr)) break;
+               }
+               default:
+                       return FALSE;
+               }
+
+               break;
+       }
+       case STORE_ALCHEMIST:
+       {
+               switch (o_ptr->tval)
+               {
+               case TV_SCROLL:
+               case TV_POTION:
+                       break;
+               default:
+                       return FALSE;
+               }
+
+               break;
+       }
+       case STORE_MAGIC:
+       {
+               switch (o_ptr->tval)
+               {
+               case TV_SORCERY_BOOK:
+               case TV_NATURE_BOOK:
+               case TV_CHAOS_BOOK:
+               case TV_DEATH_BOOK:
+               case TV_TRUMP_BOOK:
+               case TV_ARCANE_BOOK:
+               case TV_CRAFT_BOOK:
+               case TV_DAEMON_BOOK:
+               case TV_MUSIC_BOOK:
+               case TV_HEX_BOOK:
+               case TV_AMULET:
+               case TV_RING:
+               case TV_STAFF:
+               case TV_WAND:
+               case TV_ROD:
+               case TV_SCROLL:
+               case TV_POTION:
+               case TV_FIGURINE:
+                       break;
+               case TV_HAFTED:
+               {
+                       if (o_ptr->sval == SV_WIZSTAFF) break;
+                       else return FALSE;
+               }
+               default:
+                       return FALSE;
+               }
+
+               break;
+       }
+       case STORE_BOOK:
+       {
+               switch (o_ptr->tval)
+               {
+               case TV_SORCERY_BOOK:
+               case TV_NATURE_BOOK:
+               case TV_CHAOS_BOOK:
+               case TV_DEATH_BOOK:
+               case TV_LIFE_BOOK:
+               case TV_TRUMP_BOOK:
+               case TV_ARCANE_BOOK:
+               case TV_CRAFT_BOOK:
+               case TV_DAEMON_BOOK:
+               case TV_CRUSADE_BOOK:
+               case TV_MUSIC_BOOK:
+               case TV_HEX_BOOK:
+                       break;
+               default:
+                       return FALSE;
+               }
+
+               break;
+       }
+       }
+
+       if (object_value(o_ptr) <= 0) return FALSE;
+       return TRUE;
+}
+
 
 /*!
- * todo store.c のユーティリティ関数に相応しいものをここに置く
+ * @brief 店舗に並べた品を同一品であるかどうか判定する /
+ * Determine if a store item can "absorb" another item
+ * @param o_ptr 判定するオブジェクト構造体の参照ポインタ1
+ * @param j_ptr 判定するオブジェクト構造体の参照ポインタ2
+ * @return 同一扱いできるならTRUEを返す
+ * @details
+ * <pre>
+ * See "object_similar()" for the same function for the "player"
+ * </pre>
  */
+bool store_object_similar(object_type *o_ptr, object_type *j_ptr)
+{
+       if (o_ptr == j_ptr) return 0;
+       if (o_ptr->k_idx != j_ptr->k_idx) return 0;
+       if ((o_ptr->pval != j_ptr->pval) && (o_ptr->tval != TV_WAND) && (o_ptr->tval != TV_ROD)) return 0;
+       if (o_ptr->to_h != j_ptr->to_h) return 0;
+       if (o_ptr->to_d != j_ptr->to_d) return 0;
+       if (o_ptr->to_a != j_ptr->to_a) return 0;
+       if (o_ptr->name2 != j_ptr->name2) return 0;
+       if (object_is_artifact(o_ptr) || object_is_artifact(j_ptr)) return 0;
+       for (int i = 0; i < TR_FLAG_SIZE; i++)
+               if (o_ptr->art_flags[i] != j_ptr->art_flags[i]) return 0;
+       if (o_ptr->xtra1 || j_ptr->xtra1) return 0;
+       if (o_ptr->timeout || j_ptr->timeout) return 0;
+       if (o_ptr->ac != j_ptr->ac)   return 0;
+       if (o_ptr->dd != j_ptr->dd)   return 0;
+       if (o_ptr->ds != j_ptr->ds)   return 0;
+       if (o_ptr->tval == TV_CHEST) return 0;
+       if (o_ptr->tval == TV_STATUE) return 0;
+       if (o_ptr->tval == TV_CAPTURE) return 0;
+       if (o_ptr->discount != j_ptr->discount) return 0;
+       return TRUE;
+}
+
+
+/*!
+ * @brief 店舗に並べた品を重ね合わせできるかどうか判定する /
+ * Allow a store item to absorb another item
+ * @param o_ptr 判定するオブジェクト構造体の参照ポインタ1
+ * @param j_ptr 判定するオブジェクト構造体の参照ポインタ2
+ * @return 重ね合わせできるならTRUEを返す
+ * @details
+ * <pre>
+ * See "object_similar()" for the same function for the "player"
+ * </pre>
+ */
+static void store_object_absorb(object_type *o_ptr, object_type *j_ptr)
+{
+       int max_num = (o_ptr->tval == TV_ROD) ?
+               MIN(99, MAX_SHORT / k_info[o_ptr->k_idx].pval) : 99;
+       int total = o_ptr->number + j_ptr->number;
+       int diff = (total > max_num) ? total - max_num : 0;
+       o_ptr->number = (total > max_num) ? max_num : total;
+       if (o_ptr->tval == TV_ROD)
+       {
+               o_ptr->pval += j_ptr->pval * (j_ptr->number - diff) / j_ptr->number;
+       }
+
+       if (o_ptr->tval == TV_WAND)
+       {
+               o_ptr->pval += j_ptr->pval * (j_ptr->number - diff) / j_ptr->number;
+       }
+}
+
+
+/*!
+ * @brief 店舗にオブジェクトを加える /
+ * Add the item "o_ptr" to a real stores inventory.
+ * @param o_ptr 加えたいオブジェクトの構造体参照ポインタ
+ * @return 収めた先のID
+ * @details
+ * <pre>
+ * In all cases, return the slot (or -1) where the object was placed
+ * Note that this is a hacked up version of "inven_carry()".
+ * Also note that it may not correctly "adapt" to "knowledge" bacoming
+ * known, the player may have to pick stuff up and drop it again.
+ * </pre>
+ */
+int store_carry(object_type *o_ptr)
+{
+       PRICE value = object_value(o_ptr);
+       if (value <= 0) return -1;
+       o_ptr->ident |= IDENT_FULL_KNOWN;
+       o_ptr->inscription = 0;
+       o_ptr->feeling = FEEL_NONE;
+       int slot;
+       for (slot = 0; slot < st_ptr->stock_num; slot++)
+       {
+               object_type *j_ptr;
+               j_ptr = &st_ptr->stock[slot];
+               if (store_object_similar(j_ptr, o_ptr))
+               {
+                       store_object_absorb(j_ptr, o_ptr);
+                       return slot;
+               }
+       }
+
+       if (st_ptr->stock_num >= st_ptr->stock_size) return -1;
+
+       for (slot = 0; slot < st_ptr->stock_num; slot++)
+       {
+               object_type *j_ptr;
+               j_ptr = &st_ptr->stock[slot];
+               if (o_ptr->tval > j_ptr->tval) break;
+               if (o_ptr->tval < j_ptr->tval) continue;
+               if (o_ptr->sval < j_ptr->sval) break;
+               if (o_ptr->sval > j_ptr->sval) continue;
+               if (o_ptr->tval == TV_ROD)
+               {
+                       if (o_ptr->pval < j_ptr->pval) break;
+                       if (o_ptr->pval > j_ptr->pval) continue;
+               }
+
+               PRICE j_value = object_value(j_ptr);
+               if (value > j_value) break;
+               if (value < j_value) continue;
+       }
+
+       for (int i = st_ptr->stock_num; i > slot; i--)
+       {
+               st_ptr->stock[i] = st_ptr->stock[i - 1];
+       }
+
+       st_ptr->stock_num++;
+       st_ptr->stock[slot] = *o_ptr;
+       return slot;
+}
index 23eb5f5..83fd60b 100644 (file)
@@ -1,5 +1,7 @@
 #pragma once
 
+#define STORE_OBJ_LEVEL 5 /* Magic Level for normal stores */
+
 #define STORE_GENERAL   0 /*!< 店舗の種類: 雑貨屋 */
 #define STORE_ARMOURY   1 /*!< 店舗の種類: 防具屋 */
 #define STORE_WEAPON    2 /*!< 店舗の種類: 武器屋 */
 #define STORE_HOME      7 /*!< 店舗の種類: 我が家 */
 #define STORE_BOOK      8 /*!< 店舗の種類: 書店 */
 #define STORE_MUSEUM    9 /*!< 店舗の種類: 博物館 */
+
+/*
+ * A store, with an owner, various state flags, a current stock
+ * of items, and a table of items that are often purchased.
+ */
+typedef struct store_type store_type;
+
+struct store_type
+{
+       byte type;                              /* Store type */
+
+       byte owner;                             /* Owner index */
+       byte extra;                             /* Unused for now */
+
+       s16b insult_cur;                /* Insult counter */
+
+       s16b good_buy;                  /* Number of "good" buys */
+       s16b bad_buy;                   /* Number of "bad" buys */
+
+       s32b store_open;                /* Closed until this turn */
+
+       s32b last_visit;                /* Last visited on this turn */
+
+       s16b table_num;                 /* Table -- Number of entries */
+       s16b table_size;                /* Table -- Total Size of Array */
+       s16b *table;                    /* Table -- Legal item kinds */
+
+       s16b stock_num;                 /* Stock -- Number of entries */
+       s16b stock_size;                /* Stock -- Total Size of Array */
+       object_type *stock;             /* Stock -- Actual stock items */
+};
+
+extern int cur_store_num;
+extern store_type *st_ptr;
+
+void store_delete(void);
+void store_create(player_type *player_ptr, bool(*black_market_crap)(player_type*, object_type*));
+void store_item_increase(INVENTORY_IDX item, int num);
+void store_item_optimize(INVENTORY_IDX item);
+bool store_will_buy(object_type *o_ptr);
+int store_carry(object_type *o_ptr);
+bool store_object_similar(object_type *o_ptr, object_type *j_ptr);
index fbc2e69..c33521e 100644 (file)
@@ -285,13 +285,13 @@ static void inventory_aware(player_type *creature_ptr)
 static void home_aware(player_type *creature_ptr)
 {
        object_type *o_ptr;
-       store_type *st_ptr;
+       store_type *store_ptr;
        for (int i = 1; i < max_towns; i++)
        {
-               st_ptr = &town_info[i].store[STORE_HOME];
-               for (int j = 0; j < st_ptr->stock_num; j++)
+               store_ptr = &town_info[i].store[STORE_HOME];
+               for (int j = 0; j < store_ptr->stock_num; j++)
                {
-                       o_ptr = &st_ptr->stock[j];
+                       o_ptr = &store_ptr->stock[j];
                        if (!o_ptr->k_idx) continue;
 
                        object_aware(creature_ptr, o_ptr);
@@ -338,19 +338,19 @@ static void show_dead_home_items(player_type *creature_ptr)
 {
        for (int l = 1; l < max_towns; l++)
        {
-               store_type *st_ptr;
-               st_ptr = &town_info[l].store[STORE_HOME];
-               if (st_ptr->stock_num == 0) continue;
+               store_type *store_ptr;
+               store_ptr = &town_info[l].store[STORE_HOME];
+               if (store_ptr->stock_num == 0) continue;
 
-               for (int i = 0, k = 0; i < st_ptr->stock_num; k++)
+               for (int i = 0, k = 0; i < store_ptr->stock_num; k++)
                {
                        Term_clear();
-                       for (int j = 0; (j < 12) && (i < st_ptr->stock_num); j++, i++)
+                       for (int j = 0; (j < 12) && (i < store_ptr->stock_num); j++, i++)
                        {
                                GAME_TEXT o_name[MAX_NLEN];
                                char tmp_val[80];
                                object_type *o_ptr;
-                               o_ptr = &st_ptr->stock[i];
+                               o_ptr = &store_ptr->stock[i];
                                sprintf(tmp_val, "%c) ", I2A(j));
                                prt(tmp_val, j + 2, 4);
                                object_desc(creature_ptr, o_name, o_ptr, 0);
index 50d89f7..ab5cb43 100644 (file)
@@ -23,6 +23,7 @@
 #include "dungeon.h"
 #include "quest.h"
 #include "store.h"
+#include "market/store-util.h"
 #include "wild.h"
 #include "floor.h"
 #include "floor-events.h"
@@ -402,34 +403,34 @@ static void wr_xtra(KIND_OBJECT_IDX k_idx)
 
 /*!
  * @brief セーブデータに店舗情報を書き込む / Write a "store" record
- * @param st_ptr 店舗情報の参照ポインタ
+ * @param store_ptr 店舗情報の参照ポインタ
  * @return なし
  */
-static void wr_store(store_type *st_ptr)
+static void wr_store(store_type *store_ptr)
 {
        /* Save the "open" counter */
-       wr_u32b(st_ptr->store_open);
+       wr_u32b(store_ptr->store_open);
 
        /* Save the "insults" */
-       wr_s16b(st_ptr->insult_cur);
+       wr_s16b(store_ptr->insult_cur);
 
        /* Save the current owner */
-       wr_byte(st_ptr->owner);
+       wr_byte(store_ptr->owner);
 
        /* Save the stock size */
-       wr_s16b(st_ptr->stock_num);
+       wr_s16b(store_ptr->stock_num);
 
        /* Save the "haggle" info */
-       wr_s16b(st_ptr->good_buy);
-       wr_s16b(st_ptr->bad_buy);
+       wr_s16b(store_ptr->good_buy);
+       wr_s16b(store_ptr->bad_buy);
 
-       wr_s32b(st_ptr->last_visit);
+       wr_s32b(store_ptr->last_visit);
 
        /* Save the stock */
-       for (int j = 0; j < st_ptr->stock_num; j++)
+       for (int j = 0; j < store_ptr->stock_num; j++)
        {
                /* Save each item in stock */
-               wr_item(&st_ptr->stock[j]);
+               wr_item(&store_ptr->stock[j]);
        }
 }
 
index 3ff56e4..952b002 100644 (file)
@@ -15,6 +15,8 @@
 #include "market/store-owners.h"
 #include "market/store-util.h"
 #include "market/gold-magnification-table.h"
+#include "market/store-util.h"
+#include "market/black-market.h"
 #include "core.h"
 #include "util.h"
 #include "term.h"
@@ -61,7 +63,6 @@
 static int store_top = 0;
 static int store_bottom = 0;
 static int xtra_stock = 0;
-static store_type *st_ptr = NULL;
 static const owner_type *ot_ptr = NULL;
 static s16b old_town_num = 0;
 static s16b inner_town_num = 0;
@@ -126,222 +127,6 @@ static PRICE price_item(player_type *player_ptr, object_type *o_ptr, int greed,
 
 
 /*!
- * @brief 安価な消耗品の販売数を増やし、低確率で割引にする /
- * Certain "cheap" objects should be created in "piles"
- * @param o_ptr 店舗に並べるオブジェクト構造体の参照ポインタ
- * @return なし
- * @details
- * <pre>
- * Some objects can be sold at a "discount" (in small piles)
- * </pre>
- */
-static void mass_produce(object_type *o_ptr)
-{
-       int size = 1;
-       PRICE cost = object_value(o_ptr);
-       switch (o_ptr->tval)
-       {
-       case TV_FOOD:
-       case TV_FLASK:
-       case TV_LITE:
-       {
-               if (cost <= 5L) size += damroll(3, 5);
-               if (cost <= 20L) size += damroll(3, 5);
-               if (cost <= 50L) size += damroll(2, 2);
-               break;
-       }
-       case TV_POTION:
-       case TV_SCROLL:
-       {
-               if (cost <= 60L) size += damroll(3, 5);
-               if (cost <= 240L) size += damroll(1, 5);
-               if (o_ptr->sval == SV_SCROLL_STAR_IDENTIFY) size += damroll(3, 5);
-               if (o_ptr->sval == SV_SCROLL_STAR_REMOVE_CURSE) size += damroll(1, 4);
-               break;
-       }
-       case TV_LIFE_BOOK:
-       case TV_SORCERY_BOOK:
-       case TV_NATURE_BOOK:
-       case TV_CHAOS_BOOK:
-       case TV_DEATH_BOOK:
-       case TV_TRUMP_BOOK:
-       case TV_ARCANE_BOOK:
-       case TV_CRAFT_BOOK:
-       case TV_DAEMON_BOOK:
-       case TV_CRUSADE_BOOK:
-       case TV_MUSIC_BOOK:
-       case TV_HISSATSU_BOOK:
-       case TV_HEX_BOOK:
-       {
-               if (cost <= 50L) size += damroll(2, 3);
-               if (cost <= 500L) size += damroll(1, 3);
-               break;
-       }
-       case TV_SOFT_ARMOR:
-       case TV_HARD_ARMOR:
-       case TV_SHIELD:
-       case TV_GLOVES:
-       case TV_BOOTS:
-       case TV_CLOAK:
-       case TV_HELM:
-       case TV_CROWN:
-       case TV_SWORD:
-       case TV_POLEARM:
-       case TV_HAFTED:
-       case TV_DIGGING:
-       case TV_BOW:
-       {
-               if (object_is_artifact(o_ptr)) break;
-               if (object_is_ego(o_ptr)) break;
-               if (cost <= 10L) size += damroll(3, 5);
-               if (cost <= 100L) size += damroll(3, 5);
-               break;
-       }
-       case TV_SPIKE:
-       case TV_SHOT:
-       case TV_ARROW:
-       case TV_BOLT:
-       {
-               if (cost <= 5L) size += damroll(5, 5);
-               if (cost <= 50L) size += damroll(5, 5);
-               if (cost <= 500L) size += damroll(5, 5);
-               break;
-       }
-       case TV_FIGURINE:
-       {
-               if (cost <= 100L) size += damroll(2, 2);
-               if (cost <= 1000L) size += damroll(2, 2);
-               break;
-       }
-       case TV_CAPTURE:
-       case TV_STATUE:
-       case TV_CARD:
-       {
-               size = 1;
-               break;
-       }
-
-       /*
-        * Because many rods (and a few wands and staffs) are useful mainly
-        * in quantity, the Black Market will occasionally have a bunch of
-        * one kind. -LM-
-        */
-       case TV_ROD:
-       case TV_WAND:
-       case TV_STAFF:
-       {
-               if ((cur_store_num == STORE_BLACK) && one_in_(3))
-               {
-                       if (cost < 1601L) size += damroll(1, 5);
-                       else if (cost < 3201L) size += damroll(1, 3);
-               }
-               break;
-       }
-       }
-
-       DISCOUNT_RATE discount = 0;
-       if (cost < 5)
-       {
-               discount = 0;
-       }
-       else if (one_in_(25))
-       {
-               discount = 25;
-       }
-       else if (one_in_(150))
-       {
-               discount = 50;
-       }
-       else if (one_in_(300))
-       {
-               discount = 75;
-       }
-       else if (one_in_(500))
-       {
-               discount = 90;
-       }
-
-       if (o_ptr->art_name)
-       {
-               discount = 0;
-       }
-
-       o_ptr->discount = discount;
-       o_ptr->number = size - (size * discount / 100);
-       if ((o_ptr->tval == TV_ROD) || (o_ptr->tval == TV_WAND))
-       {
-               o_ptr->pval *= (PARAMETER_VALUE)o_ptr->number;
-       }
-}
-
-
-/*!
- * @brief 店舗に並べた品を同一品であるかどうか判定する /
- * Determine if a store item can "absorb" another item
- * @param o_ptr 判定するオブジェクト構造体の参照ポインタ1
- * @param j_ptr 判定するオブジェクト構造体の参照ポインタ2
- * @return 同一扱いできるならTRUEを返す
- * @details
- * <pre>
- * See "object_similar()" for the same function for the "player"
- * </pre>
- */
-static bool store_object_similar(object_type *o_ptr, object_type *j_ptr)
-{
-       if (o_ptr == j_ptr) return 0;
-       if (o_ptr->k_idx != j_ptr->k_idx) return 0;
-       if ((o_ptr->pval != j_ptr->pval) && (o_ptr->tval != TV_WAND) && (o_ptr->tval != TV_ROD)) return 0;
-       if (o_ptr->to_h != j_ptr->to_h) return 0;
-       if (o_ptr->to_d != j_ptr->to_d) return 0;
-       if (o_ptr->to_a != j_ptr->to_a) return 0;
-       if (o_ptr->name2 != j_ptr->name2) return 0;
-       if (object_is_artifact(o_ptr) || object_is_artifact(j_ptr)) return 0;
-       for (int i = 0; i < TR_FLAG_SIZE; i++)
-               if (o_ptr->art_flags[i] != j_ptr->art_flags[i]) return 0;
-       if (o_ptr->xtra1 || j_ptr->xtra1) return 0;
-       if (o_ptr->timeout || j_ptr->timeout) return 0;
-       if (o_ptr->ac != j_ptr->ac)   return 0;
-       if (o_ptr->dd != j_ptr->dd)   return 0;
-       if (o_ptr->ds != j_ptr->ds)   return 0;
-       if (o_ptr->tval == TV_CHEST) return 0;
-       if (o_ptr->tval == TV_STATUE) return 0;
-       if (o_ptr->tval == TV_CAPTURE) return 0;
-       if (o_ptr->discount != j_ptr->discount) return 0;
-       return TRUE;
-}
-
-
-/*!
- * @brief 店舗に並べた品を重ね合わせできるかどうか判定する /
- * Allow a store item to absorb another item
- * @param o_ptr 判定するオブジェクト構造体の参照ポインタ1
- * @param j_ptr 判定するオブジェクト構造体の参照ポインタ2
- * @return 重ね合わせできるならTRUEを返す
- * @details
- * <pre>
- * See "object_similar()" for the same function for the "player"
- * </pre>
- */
-static void store_object_absorb(object_type *o_ptr, object_type *j_ptr)
-{
-       int max_num = (o_ptr->tval == TV_ROD) ?
-               MIN(99, MAX_SHORT / k_info[o_ptr->k_idx].pval) : 99;
-       int total = o_ptr->number + j_ptr->number;
-       int diff = (total > max_num) ? total - max_num : 0;
-       o_ptr->number = (total > max_num) ? max_num : total;
-       if (o_ptr->tval == TV_ROD)
-       {
-               o_ptr->pval += j_ptr->pval * (j_ptr->number - diff) / j_ptr->number;
-       }
-
-       if (o_ptr->tval == TV_WAND)
-       {
-               o_ptr->pval += j_ptr->pval * (j_ptr->number - diff) / j_ptr->number;
-       }
-}
-
-
-/*!
  * @brief 店舗に品を置くスペースがあるかどうかの判定を返す /
  * Check to see if the shop will be carrying too many objects  -RAK-
  * @param o_ptr 店舗に置きたいオブジェクト構造体の参照ポインタ
@@ -425,217 +210,6 @@ static int store_check_num(object_type *o_ptr)
 
 
 /*!
- * @brief オブジェクトが祝福されているかの判定を返す /
- * @param o_ptr 判定したいオブジェクト構造体の参照ポインタ
- * @return アイテムが祝福されたアイテムならばTRUEを返す
- */
-static bool is_blessed_item(object_type *o_ptr)
-{
-       BIT_FLAGS flgs[TR_FLAG_SIZE];
-       object_flags(o_ptr, flgs);
-       if (have_flag(flgs, TR_BLESSED)) return TRUE;
-       else return FALSE;
-}
-
-
-/*!
- * @brief オブジェクトが所定の店舗で引き取れるかどうかを返す /
- * Determine if the current store will purchase the given item
- * @param o_ptr 判定したいオブジェクト構造体の参照ポインタ
- * @return アイテムが買い取れるならばTRUEを返す
- * @note
- * Note that a shop-keeper must refuse to buy "worthless" items
- */
-static bool store_will_buy(object_type *o_ptr)
-{
-       if ((cur_store_num == STORE_HOME) || (cur_store_num == STORE_MUSEUM)) return TRUE;
-       switch (cur_store_num)
-       {
-       case STORE_GENERAL:
-       {
-               switch (o_ptr->tval)
-               {
-               case TV_POTION:
-                       if (o_ptr->sval != SV_POTION_WATER) return FALSE;
-
-               case TV_WHISTLE:
-               case TV_FOOD:
-               case TV_LITE:
-               case TV_FLASK:
-               case TV_SPIKE:
-               case TV_SHOT:
-               case TV_ARROW:
-               case TV_BOLT:
-               case TV_DIGGING:
-               case TV_CLOAK:
-               case TV_BOTTLE:
-               case TV_FIGURINE:
-               case TV_STATUE:
-               case TV_CAPTURE:
-               case TV_CARD:
-                       break;
-               default:
-                       return FALSE;
-               }
-
-               break;
-       }
-       case STORE_ARMOURY:
-       {
-               switch (o_ptr->tval)
-               {
-               case TV_BOOTS:
-               case TV_GLOVES:
-               case TV_CROWN:
-               case TV_HELM:
-               case TV_SHIELD:
-               case TV_CLOAK:
-               case TV_SOFT_ARMOR:
-               case TV_HARD_ARMOR:
-               case TV_DRAG_ARMOR:
-                       break;
-               default:
-                       return FALSE;
-               }
-
-               break;
-       }
-       case STORE_WEAPON:
-       {
-               switch (o_ptr->tval)
-               {
-               case TV_SHOT:
-               case TV_BOLT:
-               case TV_ARROW:
-               case TV_BOW:
-               case TV_DIGGING:
-               case TV_POLEARM:
-               case TV_SWORD:
-               case TV_HISSATSU_BOOK:
-                       break;
-               case TV_HAFTED:
-               {
-                       if (o_ptr->sval == SV_WIZSTAFF) return FALSE;
-               }
-               break;
-               default:
-                       return FALSE;
-               }
-
-               break;
-       }
-       case STORE_TEMPLE:
-       {
-               switch (o_ptr->tval)
-               {
-               case TV_LIFE_BOOK:
-               case TV_CRUSADE_BOOK:
-               case TV_SCROLL:
-               case TV_POTION:
-               case TV_HAFTED:
-               {
-                       break;
-               }
-               case TV_FIGURINE:
-               case TV_STATUE:
-               {
-                       monster_race *r_ptr = &r_info[o_ptr->pval];
-                       if (!(r_ptr->flags3 & RF3_EVIL))
-                       {
-                               if (r_ptr->flags3 & RF3_GOOD) break;
-                               if (r_ptr->flags3 & RF3_ANIMAL) break;
-                               if (my_strchr("?!", r_ptr->d_char)) break;
-                       }
-               }
-               case TV_POLEARM:
-               case TV_SWORD:
-               {
-                       if (is_blessed_item(o_ptr)) break;
-               }
-               default:
-                       return FALSE;
-               }
-
-               break;
-       }
-       case STORE_ALCHEMIST:
-       {
-               switch (o_ptr->tval)
-               {
-               case TV_SCROLL:
-               case TV_POTION:
-                       break;
-               default:
-                       return FALSE;
-               }
-
-               break;
-       }
-       case STORE_MAGIC:
-       {
-               switch (o_ptr->tval)
-               {
-               case TV_SORCERY_BOOK:
-               case TV_NATURE_BOOK:
-               case TV_CHAOS_BOOK:
-               case TV_DEATH_BOOK:
-               case TV_TRUMP_BOOK:
-               case TV_ARCANE_BOOK:
-               case TV_CRAFT_BOOK:
-               case TV_DAEMON_BOOK:
-               case TV_MUSIC_BOOK:
-               case TV_HEX_BOOK:
-               case TV_AMULET:
-               case TV_RING:
-               case TV_STAFF:
-               case TV_WAND:
-               case TV_ROD:
-               case TV_SCROLL:
-               case TV_POTION:
-               case TV_FIGURINE:
-                       break;
-               case TV_HAFTED:
-               {
-                       if (o_ptr->sval == SV_WIZSTAFF) break;
-                       else return FALSE;
-               }
-               default:
-                       return FALSE;
-               }
-
-               break;
-       }
-       case STORE_BOOK:
-       {
-               switch (o_ptr->tval)
-               {
-               case TV_SORCERY_BOOK:
-               case TV_NATURE_BOOK:
-               case TV_CHAOS_BOOK:
-               case TV_DEATH_BOOK:
-               case TV_LIFE_BOOK:
-               case TV_TRUMP_BOOK:
-               case TV_ARCANE_BOOK:
-               case TV_CRAFT_BOOK:
-               case TV_DAEMON_BOOK:
-               case TV_CRUSADE_BOOK:
-               case TV_MUSIC_BOOK:
-               case TV_HEX_BOOK:
-                       break;
-               default:
-                       return FALSE;
-               }
-
-               break;
-       }
-       }
-
-       if (object_value(o_ptr) <= 0) return FALSE;
-       return TRUE;
-}
-
-
-/*!
  * @brief 現在の町の指定された店舗のアイテムを整理する /
  * Combine and reorder items in store.
  * @param store_num 店舗ID
@@ -839,254 +413,6 @@ static int home_carry(player_type *player_ptr, object_type *o_ptr)
 
 
 /*!
- * @brief 店舗にオブジェクトを加える /
- * Add the item "o_ptr" to a real stores inventory.
- * @param o_ptr 加えたいオブジェクトの構造体参照ポインタ
- * @return 収めた先のID
- * @details
- * <pre>
- * In all cases, return the slot (or -1) where the object was placed
- * Note that this is a hacked up version of "inven_carry()".
- * Also note that it may not correctly "adapt" to "knowledge" bacoming
- * known, the player may have to pick stuff up and drop it again.
- * </pre>
- */
-static int store_carry(object_type *o_ptr)
-{
-       PRICE value = object_value(o_ptr);
-       if (value <= 0) return -1;
-       o_ptr->ident |= IDENT_FULL_KNOWN;
-       o_ptr->inscription = 0;
-       o_ptr->feeling = FEEL_NONE;
-       int slot;
-       for (slot = 0; slot < st_ptr->stock_num; slot++)
-       {
-               object_type *j_ptr;
-               j_ptr = &st_ptr->stock[slot];
-               if (store_object_similar(j_ptr, o_ptr))
-               {
-                       store_object_absorb(j_ptr, o_ptr);
-                       return slot;
-               }
-       }
-
-       if (st_ptr->stock_num >= st_ptr->stock_size) return -1;
-
-       for (slot = 0; slot < st_ptr->stock_num; slot++)
-       {
-               object_type *j_ptr;
-               j_ptr = &st_ptr->stock[slot];
-               if (o_ptr->tval > j_ptr->tval) break;
-               if (o_ptr->tval < j_ptr->tval) continue;
-               if (o_ptr->sval < j_ptr->sval) break;
-               if (o_ptr->sval > j_ptr->sval) continue;
-               if (o_ptr->tval == TV_ROD)
-               {
-                       if (o_ptr->pval < j_ptr->pval) break;
-                       if (o_ptr->pval > j_ptr->pval) continue;
-               }
-
-               PRICE j_value = object_value(j_ptr);
-               if (value > j_value) break;
-               if (value < j_value) continue;
-       }
-
-       for (int i = st_ptr->stock_num; i > slot; i--)
-       {
-               st_ptr->stock[i] = st_ptr->stock[i - 1];
-       }
-
-       st_ptr->stock_num++;
-       st_ptr->stock[slot] = *o_ptr;
-       return slot;
-}
-
-
-/*!
- * @brief 店舗のオブジェクト数を増やす /
- * Add the item "o_ptr" to a real stores inventory.
- * @param item 増やしたいアイテムのID
- * @param num 増やしたい数
- * @return なし
- * @details
- * <pre>
- * Increase, by a given amount, the number of a certain item
- * in a certain store. This can result in zero items.
- * </pre>
- * @todo numは本来ITEM_NUMBER型にしたい。
- */
-static void store_item_increase(INVENTORY_IDX item, int num)
-{
-       object_type *o_ptr;
-       o_ptr = &st_ptr->stock[item];
-       int cnt = o_ptr->number + num;
-       if (cnt > 255) cnt = 255;
-       else if (cnt < 0) cnt = 0;
-
-       num = cnt - o_ptr->number;
-       o_ptr->number += (ITEM_NUMBER)num;
-}
-
-
-/*!
- * @brief 店舗のオブジェクト数を削除する /
- * Remove a slot if it is empty
- * @param item 削除したいアイテムのID
- * @return なし
- */
-static void store_item_optimize(INVENTORY_IDX item)
-{
-       object_type *o_ptr;
-       o_ptr = &st_ptr->stock[item];
-       if (!o_ptr->k_idx) return;
-       if (o_ptr->number) return;
-
-       st_ptr->stock_num--;
-       for (int j = item; j < st_ptr->stock_num; j++)
-       {
-               st_ptr->stock[j] = st_ptr->stock[j + 1];
-       }
-
-       object_wipe(&st_ptr->stock[st_ptr->stock_num]);
-}
-
-
-/*!
- * @brief ブラックマーケット用の無価値品の排除判定 /
- * This function will keep 'crap' out of the black market.
- * @param player_ptr プレーヤーへの参照ポインタ
- * @param o_ptr 判定したいオブジェクトの構造体参照ポインタ
- * @return ブラックマーケットにとって無価値な品ならばTRUEを返す
- * @details
- * <pre>
- * Crap is defined as any item that is "available" elsewhere
- * Based on a suggestion by "Lee Vogt" <lvogt@cig.mcel.mot.com>
- * </pre>
- */
-static bool black_market_crap(player_type *player_ptr, object_type *o_ptr)
-{
-       if (object_is_ego(o_ptr)) return FALSE;
-
-       if (o_ptr->to_a > 0) return FALSE;
-       if (o_ptr->to_h > 0) return FALSE;
-       if (o_ptr->to_d > 0) return FALSE;
-
-       for (int i = 0; i < MAX_STORES; i++)
-       {
-               if (i == STORE_HOME) continue;
-               if (i == STORE_MUSEUM) continue;
-
-               for (int j = 0; j < town_info[player_ptr->town_num].store[i].stock_num; j++)
-               {
-                       object_type *j_ptr = &town_info[player_ptr->town_num].store[i].stock[j];
-                       if (o_ptr->k_idx == j_ptr->k_idx) return TRUE;
-               }
-       }
-
-       return FALSE;
-}
-
-
-/*!
- * @brief 店舗の品揃え変化のためにアイテムを削除する /
- * Attempt to delete (some of) a random item from the store
- * @return なし
- * @details
- * <pre>
- * Hack -- we attempt to "maintain" piles of items when possible.
- * </pre>
- */
-static void store_delete(void)
-{
-       INVENTORY_IDX what = (INVENTORY_IDX)randint0(st_ptr->stock_num);
-       int num = st_ptr->stock[what].number;
-       if (randint0(100) < 50) num = (num + 1) / 2;
-       if (randint0(100) < 50) num = 1;
-       if ((st_ptr->stock[what].tval == TV_ROD) || (st_ptr->stock[what].tval == TV_WAND))
-       {
-               st_ptr->stock[what].pval -= num * st_ptr->stock[what].pval / st_ptr->stock[what].number;
-       }
-
-       store_item_increase(what, -num);
-       store_item_optimize(what);
-}
-
-
-/*!
- * @brief 店舗の品揃え変化のためにアイテムを追加する /
- * Creates a random item and gives it to a store
- * @param player_ptr プレーヤーへの参照ポインタ
- * @return なし
- * @details
- * <pre>
- * This algorithm needs to be rethought.  A lot.
- * Currently, "normal" stores use a pre-built array.
- * Note -- the "level" given to "obj_get_num()" is a "favored"
- * level, that is, there is a much higher chance of getting
- * items with a level approaching that of the given level...
- * Should we check for "permission" to have the given item?
- * </pre>
- */
-static void store_create(player_type *player_ptr)
-{
-       if (st_ptr->stock_num >= st_ptr->stock_size) return;
-
-       for (int tries = 0; tries < 4; tries++)
-       {
-               OBJECT_IDX i;
-               DEPTH level;
-               if (cur_store_num == STORE_BLACK)
-               {
-                       /* Pick a level for object/magic */
-                       level = 25 + randint0(25);
-
-                       /* Random item (usually of given level) */
-                       i = get_obj_num(player_ptr, level, 0x00000000);
-
-                       /* Handle failure */
-                       if (i == 0) continue;
-               }
-               else
-               {
-                       i = st_ptr->table[randint0(st_ptr->table_num)];
-                       level = rand_range(1, STORE_OBJ_LEVEL);
-               }
-
-               object_type forge;
-               object_type *q_ptr;
-               q_ptr = &forge;
-               object_prep(q_ptr, i);
-               apply_magic(player_ptr, q_ptr, level, AM_NO_FIXED_ART);
-               if (!store_will_buy(q_ptr)) continue;
-
-               if (q_ptr->tval == TV_LITE)
-               {
-                       if (q_ptr->sval == SV_LITE_TORCH) q_ptr->xtra4 = FUEL_TORCH / 2;
-                       if (q_ptr->sval == SV_LITE_LANTERN) q_ptr->xtra4 = FUEL_LAMP / 2;
-               }
-
-               object_known(q_ptr);
-               q_ptr->ident |= IDENT_STORE;
-               if (q_ptr->tval == TV_CHEST) continue;
-
-               if (cur_store_num == STORE_BLACK)
-               {
-                       if (black_market_crap(player_ptr, q_ptr)) continue;
-                       if (object_value(q_ptr) < 10) continue;
-               }
-               else
-               {
-                       if (object_value(q_ptr) <= 0) continue;
-               }
-
-               mass_produce(q_ptr);
-               (void)store_carry(q_ptr);
-               break;
-       }
-}
-
-
-/*!
  * @brief 店舗の割引対象外にするかどうかを判定 /
  * Eliminate need to bargain if player has haggled well in the past
  * @param minprice アイテムの最低販売価格
@@ -2988,7 +2314,7 @@ void store_maint(player_type *player_ptr, int town_num, int store_num)
        if (j < STORE_MIN_KEEP) j = STORE_MIN_KEEP;
        if (j >= st_ptr->stock_size) j = st_ptr->stock_size - 1;
 
-       while (st_ptr->stock_num < j) store_create(player_ptr);
+       while (st_ptr->stock_num < j) store_create(player_ptr, black_market_crap);
 }
 
 
index c47a8eb..282f0f2 100644 (file)
@@ -3,42 +3,10 @@
 #include "angband.h"
 #include "market/store-owners.h"
 
-/*
- * A store, with an owner, various state flags, a current stock
- * of items, and a table of items that are often purchased.
- */
-typedef struct store_type store_type;
-
-struct store_type
-{
-       byte type;                              /* Store type */
-
-       byte owner;                             /* Owner index */
-       byte extra;                             /* Unused for now */
-
-       s16b insult_cur;                /* Insult counter */
-
-       s16b good_buy;                  /* Number of "good" buys */
-       s16b bad_buy;                   /* Number of "bad" buys */
-
-       s32b store_open;                /* Closed until this turn */
-
-       s32b last_visit;                /* Last visited on this turn */
-
-       s16b table_num;                 /* Table -- Number of entries */
-       s16b table_size;                /* Table -- Total Size of Array */
-       s16b *table;                    /* Table -- Legal item kinds */
-
-       s16b stock_num;                 /* Stock -- Number of entries */
-       s16b stock_size;                /* Stock -- Total Size of Array */
-       object_type *stock;             /* Stock -- Actual stock items */
-};
-
  /*
   * Store constants
   */
 #define STORE_INVEN_MAX 24              /* Max number of discrete objs in inven */
-#define STORE_OBJ_LEVEL 5               /* Magic Level for normal stores */
 #define STORE_TURNOVER  9               /* Normal shop turnover, per day */
 #define STORE_MIN_KEEP  6               /* Min slots to "always" keep full */
 #define STORE_MAX_KEEP  18              /* Max slots to "always" keep full */
index b2991df..c09acdf 100644 (file)
@@ -27,7 +27,6 @@
 #include "floor-town.h"
 #include "files.h"
 
-
  /*
   * The spoiler file being created
   */
@@ -2474,7 +2473,7 @@ void spoil_random_artifact(player_type *creature_ptr, concptr fname)
 {
        int i, j;
 
-       store_type  *st_ptr;
+       store_type  *store_ptr;
        object_type *q_ptr;
 
        char buf[1024];
@@ -2511,18 +2510,18 @@ void spoil_random_artifact(player_type *creature_ptr, concptr fname)
                }
 
                /* random artifacts in home */
-               st_ptr = &town_info[1].store[STORE_HOME];
-               for (i = 0; i < st_ptr->stock_num; i++)
+               store_ptr = &town_info[1].store[STORE_HOME];
+               for (i = 0; i < store_ptr->stock_num; i++)
                {
-                       q_ptr = &st_ptr->stock[i];
+                       q_ptr = &store_ptr->stock[i];
                        spoil_random_artifact_aux(creature_ptr, q_ptr, j);
                }
 
                /* random artifacts in museum */
-               st_ptr = &town_info[1].store[STORE_MUSEUM];
-               for (i = 0; i < st_ptr->stock_num; i++)
+               store_ptr = &town_info[1].store[STORE_MUSEUM];
+               for (i = 0; i < store_ptr->stock_num; i++)
                {
-                       q_ptr = &st_ptr->stock[i];
+                       q_ptr = &store_ptr->stock[i];
                        spoil_random_artifact_aux(creature_ptr, q_ptr, j);
                }
        }