OSDN Git Service

[Refactor] #40569 Separated floor-type-definition.h from floor.h
[hengband/hengband.git] / src / world / world-object.c
1 #include "world/world-object.h"
2 #include "dungeon/dungeon.h"
3 #include "object-enchant/item-apply-magic.h"
4 #include "object/object-kind.h"
5 #include "system/alloc-entries.h"
6 #include "system/floor-type-definition.h"
7 #include "view/display-messages.h"
8 #include "world/world.h"
9
10 /*!
11  * @brief グローバルオブジェクト配列から空きを取得する /
12  * Acquires and returns the index of a "free" object.
13  * @param floo_ptr 現在フロアへの参照ポインタ
14  * @return 開いているオブジェクト要素のID
15  * @details
16  * This routine should almost never fail, but in case it does,
17  * we must be sure to handle "failure" of this routine.
18  */
19 OBJECT_IDX o_pop(floor_type *floor_ptr)
20 {
21     if (floor_ptr->o_max < current_world_ptr->max_o_idx) {
22         OBJECT_IDX i = floor_ptr->o_max;
23         floor_ptr->o_max++;
24         floor_ptr->o_cnt++;
25         return i;
26     }
27
28     for (OBJECT_IDX i = 1; i < floor_ptr->o_max; i++) {
29         object_type *o_ptr;
30         o_ptr = &floor_ptr->o_list[i];
31         if (o_ptr->k_idx)
32             continue;
33         floor_ptr->o_cnt++;
34
35         return i;
36     }
37
38     if (current_world_ptr->character_dungeon)
39         msg_print(_("アイテムが多すぎる!", "Too many objects!"));
40
41     return 0;
42 }
43
44 /*!
45  * @brief オブジェクト生成テーブルからアイテムを取得する /
46  * Choose an object kind that seems "appropriate" to the given level
47  * @param owner_ptr プレーヤーへの参照ポインタ
48  * @param level 生成階
49  * @return 選ばれたオブジェクトベースID
50  * @details
51  * This function uses the "prob2" field of the "object allocation table",\n
52  * and various local information, to calculate the "prob3" field of the\n
53  * same table, which is then used to choose an "appropriate" object, in\n
54  * a relatively efficient manner.\n
55  *\n
56  * It is (slightly) more likely to acquire an object of the given level\n
57  * than one of a lower level.  This is done by choosing several objects\n
58  * appropriate to the given level and keeping the "hardest" one.\n
59  *\n
60  * Note that if no objects are "appropriate", then this function will\n
61  * fail, and return zero, but this should *almost* never happen.\n
62  */
63 OBJECT_IDX get_obj_num(player_type *owner_ptr, DEPTH level, BIT_FLAGS mode)
64 {
65     int i, j, p;
66     KIND_OBJECT_IDX k_idx;
67     long value, total;
68     object_kind *k_ptr;
69     alloc_entry *table = alloc_kind_table;
70
71     if (level > MAX_DEPTH - 1)
72         level = MAX_DEPTH - 1;
73
74     if ((level > 0) && !(d_info[owner_ptr->dungeon_idx].flags1 & DF1_BEGINNER)) {
75         if (one_in_(GREAT_OBJ)) {
76             level = 1 + (level * MAX_DEPTH / randint1(MAX_DEPTH));
77         }
78     }
79
80     total = 0L;
81     for (i = 0; i < alloc_kind_size; i++) {
82         if (table[i].level > level)
83             break;
84
85         table[i].prob3 = 0;
86         k_idx = table[i].index;
87         k_ptr = &k_info[k_idx];
88
89         if ((mode & AM_FORBID_CHEST) && (k_ptr->tval == TV_CHEST))
90             continue;
91
92         table[i].prob3 = table[i].prob2;
93         total += table[i].prob3;
94     }
95
96     if (total <= 0)
97         return 0;
98
99     value = randint0(total);
100     for (i = 0; i < alloc_kind_size; i++) {
101         if (value < table[i].prob3)
102             break;
103
104         value = value - table[i].prob3;
105     }
106
107     p = randint0(100);
108     if (p < 60) {
109         j = i;
110         value = randint0(total);
111         for (i = 0; i < alloc_kind_size; i++) {
112             if (value < table[i].prob3)
113                 break;
114
115             value = value - table[i].prob3;
116         }
117
118         if (table[i].level < table[j].level)
119             i = j;
120     }
121
122     if (p >= 10)
123         return (table[i].index);
124
125     j = i;
126     value = randint0(total);
127     for (i = 0; i < alloc_kind_size; i++) {
128         if (value < table[i].prob3)
129             break;
130
131         value = value - table[i].prob3;
132     }
133
134     if (table[i].level < table[j].level)
135         i = j;
136     return (table[i].index);
137 }