OSDN Git Service

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