OSDN Git Service

[Refactor] #38844 Removed inclusion of cmd-building.h from angband.h
[hengband/hengband.git] / src / object / object-info.c
1 /*!
2  * @brief オブジェクトの実装 / Object code, part 1
3  * @date 2014/01/10
4  * @author
5  * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n
6  *\n
7  * This software may be copied and distributed for educational, research,\n
8  * and not for profit purposes provided that this copyright and statement\n
9  * are included in all such copies.  Other copyrights may also apply.\n
10  * 2014 Deskull rearranged comment for Doxygen.\n
11  */
12
13 #include "object/object-info.h"
14 #include "art-definition/art-weapon-types.h"
15 #include "art-definition/random-art-effects.h"
16 #include "floor/floor.h"
17 #include "monster-race/monster-race.h"
18 #include "object-enchant/activation-info-table.h"
19 #include "object-enchant/artifact.h"
20 #include "object-enchant/dragon-breaths-table.h"
21 #include "object-enchant/object-ego.h"
22 #include "object/object-flags.h"
23 #include "object/object-kind.h"
24 #include "realm/realm-names-table.h"
25 #include "sv-definition/sv-other-types.h"
26 #include "sv-definition/sv-ring-types.h"
27 #include "term/term-color-types.h"
28 #include "util/bit-flags-calculator.h"
29 #include "util/int-char-converter.h"
30
31 /*!
32  * @brief オブジェクトの発動効果名称を返す(サブルーチン/ブレス)
33  * @param o_ptr 名称を取得する元のオブジェクト構造体参照ポインタ
34  * @return concptr 発動名称を返す文字列ポインタ
35  */
36 static concptr item_activation_dragon_breath(object_type *o_ptr)
37 {
38     static char desc[256];
39     BIT_FLAGS flgs[TR_FLAG_SIZE]; /* for resistance flags */
40     int n = 0;
41
42     object_flags(o_ptr, flgs);
43     strcpy(desc, _("", "breath "));
44
45     for (int i = 0; dragonbreath_info[i].flag != 0; i++) {
46         if (have_flag(flgs, dragonbreath_info[i].flag)) {
47             if (n > 0)
48                 strcat(desc, _("、", ", "));
49
50             strcat(desc, dragonbreath_info[i].name);
51             n++;
52         }
53     }
54
55     strcat(desc, _("のブレス(250)", ""));
56     return (desc);
57 }
58
59 /*!
60  * @brief オブジェクトの発動効果名称を返す(サブルーチン/汎用)
61  * @param o_ptr 名称を取得する元のオブジェクト構造体参照ポインタ
62  * @return concptr 発動名称を返す文字列ポインタ
63  */
64 static concptr item_activation_aux(object_type *o_ptr)
65 {
66     static char activation_detail[256];
67     char timeout[32];
68     const activation_type *const act_ptr = find_activation_info(o_ptr);
69
70     if (!act_ptr)
71         return _("未定義", "something undefined");
72
73     concptr desc = act_ptr->desc;
74     switch (act_ptr->index) {
75     case ACT_BR_FIRE:
76         if ((o_ptr->tval == TV_RING) && (o_ptr->sval == SV_RING_FLAMES))
77             desc = _("火炎のブレス (200) と火への耐性", "breath of fire (200) and resist fire");
78         break;
79     case ACT_BR_COLD:
80         if ((o_ptr->tval == TV_RING) && (o_ptr->sval == SV_RING_ICE))
81             desc = _("冷気のブレス (200) と冷気への耐性", "breath of cold (200) and resist cold");
82         break;
83     case ACT_BR_DRAGON:
84         desc = item_activation_dragon_breath(o_ptr);
85         break;
86     case ACT_AGGRAVATE:
87         if (o_ptr->name1 == ART_HYOUSIGI)
88             desc = _("拍子木を打ちならす", "beat wooden clappers");
89         break;
90     case ACT_RESIST_ACID:
91         if (((o_ptr->tval == TV_RING) && (o_ptr->sval == SV_RING_ACID)) || (o_ptr->name2 == EGO_BRAND_ACID))
92             desc = _("アシッド・ボール (100) と酸への耐性", "ball of acid (100) and resist acid");
93         break;
94     case ACT_RESIST_FIRE:
95         if (((o_ptr->tval == TV_RING) && (o_ptr->sval == SV_RING_FLAMES)) || (o_ptr->name2 == EGO_BRAND_FIRE))
96             desc = _("ファイア・ボール (100) と火への耐性", "ball of fire (100) and resist fire");
97         break;
98     case ACT_RESIST_COLD:
99         if (((o_ptr->tval == TV_RING) && (o_ptr->sval == SV_RING_ICE)) || (o_ptr->name2 == EGO_BRAND_COLD))
100             desc = _("アイス・ボール (100) と冷気への耐性", "ball of cold (100) and resist cold");
101         break;
102     case ACT_RESIST_ELEC:
103         if (((o_ptr->tval == TV_RING) && (o_ptr->sval == SV_RING_ELEC)) || (o_ptr->name2 == EGO_BRAND_ELEC))
104             desc = _("サンダー・ボール (100) と電撃への耐性", "ball of elec (100) and resist elec");
105         break;
106     case ACT_RESIST_POIS:
107         if (o_ptr->name2 == EGO_BRAND_POIS)
108             desc = _("悪臭雲 (100) と毒への耐性", "ball of poison (100) and resist elec");
109         break;
110     }
111
112     /* Timeout description */
113     int constant = act_ptr->timeout.constant;
114     int dice = act_ptr->timeout.dice;
115     if (constant == 0 && dice == 0) {
116         /* We can activate it every turn */
117         strcpy(timeout, _("いつでも", "every turn"));
118     } else if (constant < 0) {
119         /* Activations that have special timeout */
120         switch (act_ptr->index) {
121         case ACT_BR_FIRE:
122             sprintf(timeout, _("%d ターン毎", "every %d turns"), ((o_ptr->tval == TV_RING) && (o_ptr->sval == SV_RING_FLAMES)) ? 200 : 250);
123             break;
124         case ACT_BR_COLD:
125             sprintf(timeout, _("%d ターン毎", "every %d turns"), ((o_ptr->tval == TV_RING) && (o_ptr->sval == SV_RING_ICE)) ? 200 : 250);
126             break;
127         case ACT_TERROR:
128             strcpy(timeout, _("3*(レベル+10) ターン毎", "every 3 * (level+10) turns"));
129             break;
130         case ACT_MURAMASA:
131             strcpy(timeout, _("確率50%で壊れる", "(destroyed 50%)"));
132             break;
133         default:
134             strcpy(timeout, "undefined");
135             break;
136         }
137     } else {
138         char constant_str[16], dice_str[16];
139         sprintf(constant_str, "%d", constant);
140         sprintf(dice_str, "d%d", dice);
141         sprintf(timeout, _("%s%s%s ターン毎", "every %s%s%s turns"), (constant > 0) ? constant_str : "", (constant > 0 && dice > 0) ? "+" : "",
142             (dice > 0) ? dice_str : "");
143     }
144
145     sprintf(activation_detail, _("%s : %s", "%s %s"), desc, timeout);
146     return activation_detail;
147 }
148
149 /*!
150  * @brief オブジェクトの発動効果名称を返す(メインルーチン) /
151  * Determine the "Activation" (if any) for an artifact Return a string, or NULL for "no activation"
152  * @param o_ptr 名称を取得する元のオブジェクト構造体参照ポインタ
153  * @return concptr 発動名称を返す文字列ポインタ
154  */
155 concptr activation_explanation(object_type *o_ptr)
156 {
157     BIT_FLAGS flgs[TR_FLAG_SIZE];
158     object_flags(o_ptr, flgs);
159     if (!(have_flag(flgs, TR_ACTIVATE)))
160         return (_("なし", "nothing"));
161
162     if (activation_index(o_ptr)) {
163         return item_activation_aux(o_ptr);
164     }
165
166     if (o_ptr->tval == TV_WHISTLE) {
167         return _("ペット呼び寄せ : 100+d100ターン毎", "call pet every 100+d100 turns");
168     }
169
170     if (o_ptr->tval == TV_CAPTURE) {
171         return _("モンスターを捕える、又は解放する。", "captures or releases a monster.");
172     }
173
174     return _("何も起きない", "Nothing");
175 }
176
177 /*!
178  * @brief オブジェクト選択時の選択アルファベットラベルを返す /
179  * Convert an inventory index into a one character label
180  * @param i プレイヤーの所持/装備オブジェクトID
181  * @return 対応するアルファベット
182  * @details Note that the label does NOT distinguish inven/equip.
183  */
184 char index_to_label(int i) { return (i < INVEN_RARM) ? (I2A(i)) : (I2A(i - INVEN_RARM)); }
185
186 /*!
187  * @brief オブジェクトの該当装備部位IDを返す /
188  * Determine which equipment slot (if any) an item likes
189  * @param o_ptr 名称を取得する元のオブジェクト構造体参照ポインタ
190  * @return 対応する装備部位ID
191  */
192 s16b wield_slot(player_type *owner_ptr, object_type *o_ptr)
193 {
194     switch (o_ptr->tval) {
195     case TV_DIGGING:
196     case TV_HAFTED:
197     case TV_POLEARM:
198     case TV_SWORD: {
199         if (!owner_ptr->inventory_list[INVEN_RARM].k_idx)
200             return (INVEN_RARM);
201         if (owner_ptr->inventory_list[INVEN_LARM].k_idx)
202             return (INVEN_RARM);
203         return (INVEN_LARM);
204     }
205     case TV_CAPTURE:
206     case TV_CARD:
207     case TV_SHIELD: {
208         if (!owner_ptr->inventory_list[INVEN_LARM].k_idx)
209             return (INVEN_LARM);
210         if (owner_ptr->inventory_list[INVEN_RARM].k_idx)
211             return (INVEN_LARM);
212         return (INVEN_RARM);
213     }
214     case TV_BOW: {
215         return (INVEN_BOW);
216     }
217     case TV_RING: {
218         if (!owner_ptr->inventory_list[INVEN_RIGHT].k_idx)
219             return (INVEN_RIGHT);
220
221         return (INVEN_LEFT);
222     }
223     case TV_AMULET:
224     case TV_WHISTLE: {
225         return (INVEN_NECK);
226     }
227     case TV_LITE: {
228         return (INVEN_LITE);
229     }
230     case TV_DRAG_ARMOR:
231     case TV_HARD_ARMOR:
232     case TV_SOFT_ARMOR: {
233         return (INVEN_BODY);
234     }
235     case TV_CLOAK: {
236         return (INVEN_OUTER);
237     }
238     case TV_CROWN:
239     case TV_HELM: {
240         return (INVEN_HEAD);
241     }
242     case TV_GLOVES: {
243         return (INVEN_HANDS);
244     }
245     case TV_BOOTS: {
246         return (INVEN_FEET);
247     }
248     }
249
250     return -1;
251 }
252
253 /*!
254  * @brief tval/sval指定のベースアイテムがプレイヤーの使用可能な魔法書かどうかを返す /
255  * Hack: Check if a spellbook is one of the realms we can use. -- TY
256  * @param book_tval ベースアイテムのtval
257  * @param book_sval ベースアイテムのsval
258  * @return 使用可能な魔法書ならばTRUEを返す。
259  */
260 bool check_book_realm(player_type *owner_ptr, const tval_type book_tval, const OBJECT_SUBTYPE_VALUE book_sval)
261 {
262     if (book_tval < TV_LIFE_BOOK)
263         return FALSE;
264     if (owner_ptr->pclass == CLASS_SORCERER) {
265         return is_magic(tval2realm(book_tval));
266     } else if (owner_ptr->pclass == CLASS_RED_MAGE) {
267         if (is_magic(tval2realm(book_tval)))
268             return ((book_tval == TV_ARCANE_BOOK) || (book_sval < 2));
269     }
270
271     return (REALM1_BOOK == book_tval || REALM2_BOOK == book_tval);
272 }
273
274 object_type *ref_item(player_type *owner_ptr, INVENTORY_IDX item)
275 {
276     floor_type *floor_ptr = owner_ptr->current_floor_ptr;
277     return item >= 0 ? &owner_ptr->inventory_list[item] : &(floor_ptr->o_list[0 - item]);
278 }
279
280 /*
281  * Return the "attr" for a given item.
282  * Use "flavor" if available.
283  * Default to user definitions.
284  */
285 TERM_COLOR object_attr(object_type *o_ptr)
286 {
287     return ((k_info[o_ptr->k_idx].flavor)
288             ? (k_info[k_info[o_ptr->k_idx].flavor].x_attr)
289             : ((!o_ptr->k_idx || (o_ptr->tval != TV_CORPSE) || (o_ptr->sval != SV_CORPSE) || (k_info[o_ptr->k_idx].x_attr != TERM_DARK))
290                     ? (k_info[o_ptr->k_idx].x_attr)
291                     : (r_info[o_ptr->pval].x_attr)));
292 }