OSDN Git Service

[Refactor] #40399 Moved floor_increase() and floor_optimize() from object2.c/h to...
[hengbandforosx/hengbandosx.git] / src / floor / floor-object.c
1 /*!
2  * @brief フロア生成時にアイテムを配置する
3  * @date 2020/06/01
4  * @author Hourier
5  */
6
7 #include "floor/floor-object.h"
8 #include "floor/floor.h"
9 #include "object/artifact.h"
10 #include "object/item-apply-magic.h"
11 #include "object/object-appraiser.h"
12 #include "object/object-flavor.h"
13 #include "object/object-kind-hook.h"
14 #include "object/object-kind.h"
15 #include "object/object2.h"
16 #include "object/special-object-flags.h"
17 #include "view/object-describer.h"
18
19 #define MAX_GOLD 18 /* Number of "gold" entries */
20
21 /*!
22  * @brief オブジェクト生成テーブルに生成制約を加える /
23  * Apply a "object restriction function" to the "object allocation table"
24  * @return 常に0を返す。
25  * @details 生成の制約はグローバルのget_obj_num_hook関数ポインタで加える
26  */
27 static errr get_obj_num_prep(void)
28 {
29     alloc_entry *table = alloc_kind_table;
30     for (OBJECT_IDX i = 0; i < alloc_kind_size; i++) {
31         if (!get_obj_num_hook || (*get_obj_num_hook)(table[i].index)) {
32             table[i].prob2 = table[i].prob1;
33         } else {
34             table[i].prob2 = 0;
35         }
36     }
37
38     return 0;
39 }
40
41 /*!
42  * @brief デバッグ時にアイテム生成情報をメッセージに出力する / Cheat -- describe a created object for the user
43  * @param owner_ptr プレーヤーへの参照ポインタ
44  * @param o_ptr デバッグ出力するオブジェクトの構造体参照ポインタ
45  * @return なし
46  */
47 static void object_mention(player_type *owner_ptr, object_type *o_ptr)
48 {
49     object_aware(owner_ptr, o_ptr);
50     object_known(o_ptr);
51
52     o_ptr->ident |= (IDENT_FULL_KNOWN);
53     GAME_TEXT o_name[MAX_NLEN];
54     object_desc(owner_ptr, o_name, o_ptr, 0);
55     msg_format_wizard(CHEAT_OBJECT, _("%sを生成しました。", "%s was generated."), o_name);
56 }
57
58 /*!
59  * @brief 生成階に応じたベースアイテムの生成を行う。
60  * Attempt to make an object (normal or good/great)
61  * @param owner_ptr プレーヤーへの参照ポインタ
62  * @param j_ptr 生成結果を収めたいオブジェクト構造体の参照ポインタ
63  * @param mode オプションフラグ
64  * @return 生成に成功したらTRUEを返す。
65  * @details
66  * This routine plays nasty games to generate the "special artifacts".\n
67  * This routine uses "floor_ptr->object_level" for the "generation level".\n
68  * We assume that the given object has been "wiped".\n
69  */
70 bool make_object(player_type *owner_ptr, object_type *j_ptr, BIT_FLAGS mode)
71 {
72     floor_type *floor_ptr = owner_ptr->current_floor_ptr;
73     PERCENTAGE prob = ((mode & AM_GOOD) ? 10 : 1000);
74     DEPTH base = ((mode & AM_GOOD) ? (floor_ptr->object_level + 10) : floor_ptr->object_level);
75     if (!one_in_(prob) || !make_artifact_special(owner_ptr, j_ptr)) {
76         KIND_OBJECT_IDX k_idx;
77         if ((mode & AM_GOOD) && !get_obj_num_hook) {
78             get_obj_num_hook = kind_is_good;
79         }
80
81         if (get_obj_num_hook)
82             get_obj_num_prep();
83
84         k_idx = get_obj_num(owner_ptr, base, mode);
85         if (get_obj_num_hook) {
86             get_obj_num_hook = NULL;
87             get_obj_num_prep();
88         }
89
90         if (!k_idx)
91             return FALSE;
92
93         object_prep(j_ptr, k_idx);
94     }
95
96     apply_magic(owner_ptr, j_ptr, floor_ptr->object_level, mode);
97     switch (j_ptr->tval) {
98     case TV_SPIKE:
99     case TV_SHOT:
100     case TV_ARROW:
101     case TV_BOLT: {
102         if (!j_ptr->name1)
103             j_ptr->number = (byte)damroll(6, 7);
104     }
105     }
106
107     if (cheat_peek)
108         object_mention(owner_ptr, j_ptr);
109
110     return TRUE;
111 }
112
113 /*!
114  * @brief 生成階に応じた財宝オブジェクトの生成を行う。
115  * Make a treasure object
116  * @param floor_ptr 現在フロアへの参照ポインタ
117  * @param j_ptr 生成結果を収めたいオブジェクト構造体の参照ポインタ
118  * @return 生成に成功したらTRUEを返す。
119  * @details
120  * The location must be a legal, clean, floor grid.
121  */
122 bool make_gold(floor_type *floor_ptr, object_type *j_ptr)
123 {
124     int i = ((randint1(floor_ptr->object_level + 2) + 2) / 2) - 1;
125     if (one_in_(GREAT_OBJ)) {
126         i += randint1(floor_ptr->object_level + 1);
127     }
128
129     if (coin_type)
130         i = coin_type;
131     if (i >= MAX_GOLD)
132         i = MAX_GOLD - 1;
133     object_prep(j_ptr, OBJ_GOLD_LIST + i);
134
135     s32b base = k_info[OBJ_GOLD_LIST + i].cost;
136     j_ptr->pval = (base + (8L * randint1(base)) + randint1(8));
137
138     return TRUE;
139 }
140
141 /*!
142  * @brief フロア中のアイテムを全て削除する / Deletes all objects at given location
143  * Delete a dungeon object
144  * @param player_ptr プレーヤーへの参照ポインタ
145  * @param y 削除したフロアマスのY座標
146  * @param x 削除したフロアマスのX座標
147  * @return なし
148  */
149 void delete_all_items_from_floor(player_type *player_ptr, POSITION y, POSITION x)
150 {
151     grid_type *g_ptr;
152     OBJECT_IDX this_o_idx, next_o_idx = 0;
153     floor_type *floor_ptr = player_ptr->current_floor_ptr;
154     if (!in_bounds(floor_ptr, y, x))
155         return;
156
157     g_ptr = &floor_ptr->grid_array[y][x];
158     for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) {
159         object_type *o_ptr;
160         o_ptr = &floor_ptr->o_list[this_o_idx];
161         next_o_idx = o_ptr->next_o_idx;
162         object_wipe(o_ptr);
163         floor_ptr->o_cnt--;
164     }
165
166     g_ptr->o_idx = 0;
167     lite_spot(player_ptr, y, x);
168 }
169
170 /*!
171  * @brief 床上のアイテムの数を増やす /
172  * Increase the "number" of an item on the floor
173  * @param floo_ptr 現在フロアへの参照ポインタ
174  * @param item 増やしたいアイテムの所持スロット
175  * @param num 増やしたいアイテムの数
176  * @return なし
177  */
178 void floor_item_increase(floor_type *floor_ptr, INVENTORY_IDX item, ITEM_NUMBER num)
179 {
180     object_type *o_ptr = &floor_ptr->o_list[item];
181     num += o_ptr->number;
182     if (num > 255)
183         num = 255;
184     else if (num < 0)
185         num = 0;
186
187     num -= o_ptr->number;
188     o_ptr->number += num;
189 }
190
191 /*!
192  * @brief 床上の数の無くなったアイテムスロットを消去する /
193  * Optimize an item on the floor (destroy "empty" items)
194  * @param player_ptr プレーヤーへの参照ポインタ
195  * @param item 消去したいアイテムの所持スロット
196  * @return なし
197  */
198 void floor_item_optimize(player_type *owner_ptr, INVENTORY_IDX item)
199 {
200     object_type *o_ptr = &owner_ptr->current_floor_ptr->o_list[item];
201     if (!o_ptr->k_idx)
202         return;
203     if (o_ptr->number)
204         return;
205
206     delete_object_idx(owner_ptr, item);
207 }