2 * @brief 固定アーティファクトの生成 / Artifact code
5 * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
6 * This software may be copied and distributed for educational, research, and
7 * not for profit purposes provided that this copyright and statement are
8 * included in all such copies.
9 * 2013 Deskull rearranged comment for Doxygen.
10 * 2020 Hourier rearranged
13 #include "artifact/fixed-art-generator.h"
14 #include "artifact/fixed-art-types.h"
15 #include "floor/floor-object.h"
16 #include "object-enchant/object-boost.h"
17 #include "object-enchant/object-curse.h"
18 #include "object-enchant/special-object-flags.h"
19 #include "object-enchant/tr-types.h"
20 #include "object-enchant/trc-types.h"
21 #include "object-enchant/trg-types.h"
22 #include "object/object-generator.h"
23 #include "object/object-kind-hook.h"
24 #include "object/object-kind.h"
25 #include "specific-object/bloody-moon.h"
26 #include "system/artifact-type-definition.h"
27 #include "system/floor-type-definition.h"
28 #include "system/system-variables.h"
29 #include "util/bit-flags-calculator.h"
32 * @brief 恐怖の仮面への特殊処理 (一部職業のみ追加能力&耐性、それ以外は反感&太古の怨念)
33 * @param player_ptr プレーヤーへの参照ポインタ
34 * @param o_ptr 対象のオブジェクト構造体への参照ポインタ
35 * @param give_power 追加能力の有無
36 * @param give_resistance 追加耐性の有無
37 * @return そもそも対象のオブジェクトが恐怖の仮面ではないか、「その他の職業」であればTRUE
39 static bool invest_terror_mask(player_type *player_ptr, object_type *o_ptr, bool *give_power, bool *give_resistance)
41 if (o_ptr->name1 != ART_TERROR)
44 bool is_special_class = player_ptr->pclass == CLASS_WARRIOR;
45 is_special_class |= player_ptr->pclass == CLASS_ARCHER;
46 is_special_class |= player_ptr->pclass == CLASS_CAVALRY;
47 is_special_class |= player_ptr->pclass == CLASS_BERSERKER;
48 if (is_special_class) {
50 *give_resistance = TRUE;
54 add_flag(o_ptr->art_flags, TR_AGGRAVATE);
55 add_flag(o_ptr->art_flags, TR_TY_CURSE);
56 o_ptr->curse_flags |= (TRC_CURSED | TRC_HEAVY_CURSE);
57 o_ptr->curse_flags |= get_curse(player_ptr, 2, o_ptr);
62 * @brief 戦乙女ミリムの危ない水着への特殊処理 (セクシーギャルのみpval追加)
63 * @param player_ptr プレーヤーへの参照ポインタ
64 * @param o_ptr 対象のオブジェクト構造体への参照ポインタ
67 static void milim_swimsuit(player_type *player_ptr, object_type *o_ptr)
69 if ((o_ptr->name1 != ART_MILIM) || (player_ptr->pseikaku != PERSONALITY_SEXY))
73 add_flag(o_ptr->art_flags, TR_STR);
74 add_flag(o_ptr->art_flags, TR_INT);
75 add_flag(o_ptr->art_flags, TR_WIS);
76 add_flag(o_ptr->art_flags, TR_DEX);
77 add_flag(o_ptr->art_flags, TR_CON);
78 add_flag(o_ptr->art_flags, TR_CHR);
82 * @brief 固定アーティファクト生成時の特別なハードコーディング処理を行う。.
83 * @details random_artifact_resistance()とあるが実際は固定アーティファクトである。
84 * 対象は恐怖の仮面、村正、ロビントンのハープ、龍争虎鬪、ブラッディムーン、羽衣、天女の羽衣、ミリム、
86 * @attention プレイヤーの各種ステータスに依存した処理がある。
87 * @todo 折を見て関数名を変更すること。
88 * @param player_ptr プレーヤーへの参照ポインタ
89 * @param o_ptr 対象のオブジェクト構造体ポインタ
90 * @param a_ptr 生成する固定アーティファクト構造体ポインタ
93 static void random_artifact_resistance(player_type *player_ptr, object_type *o_ptr, artifact_type *a_ptr)
95 bool give_power = FALSE;
96 bool give_resistance = FALSE;
97 if (invest_terror_mask(player_ptr, o_ptr, &give_power, &give_resistance))
100 if ((o_ptr->name1 == ART_MURAMASA) && (player_ptr->pclass != CLASS_SAMURAI)) {
101 add_flag(o_ptr->art_flags, TR_NO_MAGIC);
102 o_ptr->curse_flags |= (TRC_HEAVY_CURSE);
105 if ((o_ptr->name1 == ART_ROBINTON) && (player_ptr->pclass == CLASS_BARD))
106 add_flag(o_ptr->art_flags, TR_DEC_MANA);
108 if ((o_ptr->name1 == ART_XIAOLONG) && (player_ptr->pclass == CLASS_MONK))
109 add_flag(o_ptr->art_flags, TR_BLOWS);
111 if (o_ptr->name1 == ART_BLOOD)
112 get_bloody_moon_flags(o_ptr);
114 if ((o_ptr->name1 == ART_HEAVENLY_MAIDEN) && (player_ptr->psex != SEX_FEMALE))
115 add_flag(o_ptr->art_flags, TR_AGGRAVATE);
117 milim_swimsuit(player_ptr, o_ptr);
118 if (a_ptr->gen_flags.has(TRG::XTRA_POWER))
121 if (a_ptr->gen_flags.has(TRG::XTRA_H_RES))
122 give_resistance = TRUE;
124 if (a_ptr->gen_flags.has(TRG::XTRA_RES_OR_POWER)) {
126 give_resistance = TRUE;
135 one_high_resistance(o_ptr);
137 if (a_ptr->gen_flags.has(TRG::XTRA_DICE)) {
140 } while (one_in_(o_ptr->dd));
147 static void invest_curse_to_fixed_artifact(player_type *player_ptr, artifact_type *a_ptr, object_type *q_ptr)
149 if (a_ptr->gen_flags.has(TRG::CURSED))
150 q_ptr->curse_flags |= TRC_CURSED;
152 if (a_ptr->gen_flags.has(TRG::HEAVY_CURSE))
153 q_ptr->curse_flags |= TRC_HEAVY_CURSE;
155 if (a_ptr->gen_flags.has(TRG::PERMA_CURSE))
156 q_ptr->curse_flags |= TRC_PERMA_CURSE;
158 if (a_ptr->gen_flags.has(TRG::RANDOM_CURSE0))
159 q_ptr->curse_flags |= get_curse(player_ptr, 0, q_ptr);
161 if (a_ptr->gen_flags.has(TRG::RANDOM_CURSE1))
162 q_ptr->curse_flags |= get_curse(player_ptr, 1, q_ptr);
164 if (a_ptr->gen_flags.has(TRG::RANDOM_CURSE2))
165 q_ptr->curse_flags |= get_curse(player_ptr, 2, q_ptr);
169 * @brief フロアの指定された位置に固定アーティファクトを生成する。 / Create the artifact of the specified number
170 * @details 固定アーティファクト構造体から基本ステータスをコピーした後、所定の座標でdrop_item()で落とす。
171 * @param player_ptr プレーヤーへの参照ポインタ
172 * @param a_idx 生成する固定アーティファクト構造体のID
173 * @param y アイテムを落とす地点のy座標
174 * @param x アイテムを落とす地点のx座標
175 * @return 生成が成功したか否か、失敗はIDの不全、ベースアイテムの不全、drop_item()の失敗時に起こる。
176 * @attention この処理はdrop_near()内で普通の固定アーティファクトが重ならない性質に依存する.
177 * 仮に2個以上存在可能かつ装備品以外の固定アーティファクトが作成されれば
178 * drop_near()関数の返り値は信用できなくなる.
180 bool create_named_art(player_type *player_ptr, ARTIFACT_IDX a_idx, POSITION y, POSITION x)
182 artifact_type *a_ptr = &a_info[a_idx];
183 if (a_ptr->name.empty())
186 KIND_OBJECT_IDX i = lookup_kind(a_ptr->tval, a_ptr->sval);
193 object_prep(player_ptr, q_ptr, i);
194 q_ptr->name1 = a_idx;
195 q_ptr->pval = a_ptr->pval;
196 q_ptr->ac = a_ptr->ac;
197 q_ptr->dd = a_ptr->dd;
198 q_ptr->ds = a_ptr->ds;
199 q_ptr->to_a = a_ptr->to_a;
200 q_ptr->to_h = a_ptr->to_h;
201 q_ptr->to_d = a_ptr->to_d;
202 q_ptr->weight = a_ptr->weight;
203 invest_curse_to_fixed_artifact(player_ptr, a_ptr, q_ptr);
204 random_artifact_resistance(player_ptr, q_ptr, a_ptr);
205 return drop_near(player_ptr, q_ptr, -1, y, x) ? TRUE : FALSE;
209 * @brief 非INSTA_ART型の固定アーティファクトの生成を確率に応じて試行する。
210 * Mega-Hack -- Attempt to create one of the "Special Objects"
211 * @param player_ptr プレーヤーへの参照ポインタ
212 * @param o_ptr 生成に割り当てたいオブジェクトの構造体参照ポインタ
213 * @return 生成に成功したらTRUEを返す。
215 * Attempt to change an object into an artifact\n
216 * This routine should only be called by "apply_magic()"\n
217 * Note -- see "make_artifact_special()" and "apply_magic()"\n
219 bool make_artifact(player_type *player_ptr, object_type *o_ptr)
221 floor_type *floor_ptr = player_ptr->current_floor_ptr;
222 if (floor_ptr->dun_level == 0)
225 if (o_ptr->number != 1)
228 for (ARTIFACT_IDX i = 0; i < max_a_idx; i++) {
229 artifact_type *a_ptr = &a_info[i];
230 if (a_ptr->name.empty())
236 if (a_ptr->gen_flags.has(TRG::QUESTITEM))
239 if (a_ptr->gen_flags.has(TRG::INSTA_ART))
242 if (a_ptr->tval != o_ptr->tval)
245 if (a_ptr->sval != o_ptr->sval)
248 if (a_ptr->level > floor_ptr->dun_level) {
249 int d = (a_ptr->level - floor_ptr->dun_level) * 2;
254 if (!one_in_(a_ptr->rarity))
265 * @brief make_artifact()で選択した固定アーティファクトをオブジェクトに割り当てる。
266 * @param player_ptr プレーヤーへの参照ポインタ
267 * @param o_ptr 生成に割り当てたいオブジェクトの構造体参照ポインタ
268 * @return 適用したアーティファクト情報への参照ポインタ
270 artifact_type *apply_artifact(player_type *player_ptr, object_type *o_ptr)
272 artifact_type *a_ptr = &a_info[o_ptr->name1];
273 o_ptr->pval = a_ptr->pval;
274 o_ptr->ac = a_ptr->ac;
275 o_ptr->dd = a_ptr->dd;
276 o_ptr->ds = a_ptr->ds;
277 o_ptr->to_a = a_ptr->to_a;
278 o_ptr->to_h = a_ptr->to_h;
279 o_ptr->to_d = a_ptr->to_d;
280 o_ptr->weight = a_ptr->weight;
281 o_ptr->xtra2 = a_ptr->act_idx;
282 random_artifact_resistance(player_ptr, o_ptr, a_ptr);
284 if (o_ptr->name1 == ART_MILIM) {
285 if (player_ptr->pseikaku == PERSONALITY_SEXY) {
291 o_ptr->ident |= (IDENT_BROKEN);
292 if (a_ptr->gen_flags.has(TRG::CURSED))
293 o_ptr->curse_flags |= (TRC_CURSED);
294 if (a_ptr->gen_flags.has(TRG::HEAVY_CURSE))
295 o_ptr->curse_flags |= (TRC_HEAVY_CURSE);
296 if (a_ptr->gen_flags.has(TRG::PERMA_CURSE))
297 o_ptr->curse_flags |= (TRC_PERMA_CURSE);
298 if (a_ptr->gen_flags.has(TRG::RANDOM_CURSE0))
299 o_ptr->curse_flags |= get_curse(player_ptr, 0, o_ptr);
300 if (a_ptr->gen_flags.has(TRG::RANDOM_CURSE1))
301 o_ptr->curse_flags |= get_curse(player_ptr, 1, o_ptr);
302 if (a_ptr->gen_flags.has(TRG::RANDOM_CURSE2))
303 o_ptr->curse_flags |= get_curse(player_ptr, 2, o_ptr);
309 * @brief INSTA_ART型の固定アーティファクトの生成を確率に応じて試行する。
310 * Mega-Hack -- Attempt to create one of the "Special Objects"
311 * @param player_ptr プレーヤーへの参照ポインタ
312 * @param o_ptr 生成に割り当てたいオブジェクトの構造体参照ポインタ
313 * @return 生成に成功したらTRUEを返す。
315 * We are only called from "make_object()", and we assume that\n
316 * "apply_magic()" is called immediately after we return.\n
318 * Note -- see "make_artifact()" and "apply_magic()"\n
320 bool make_artifact_special(player_type *player_ptr, object_type *o_ptr)
322 KIND_OBJECT_IDX k_idx = 0;
324 /*! @note 地上ではキャンセルする / No artifacts in the town */
325 floor_type *floor_ptr = player_ptr->current_floor_ptr;
326 if (floor_ptr->dun_level == 0)
329 /*! @note get_obj_num_hookによる指定がある場合は生成をキャンセルする / Themed object */
330 if (get_obj_num_hook)
333 /*! @note 全固定アーティファクト中からIDの若い順に生成対象とその確率を走査する / Check the artifact list (just the "specials") */
334 for (ARTIFACT_IDX i = 0; i < max_a_idx; i++) {
335 artifact_type *a_ptr = &a_info[i];
337 /*! @note アーティファクト名が空の不正なデータは除外する / Skip "empty" artifacts */
338 if (a_ptr->name.empty())
341 /*! @note 既に生成回数がカウントされたアーティファクト、QUESTITEMと非INSTA_ARTは除外 / Cannot make an artifact twice */
344 if (a_ptr->gen_flags.has(TRG::QUESTITEM))
346 if (!(a_ptr->gen_flags.has(TRG::INSTA_ART)))
349 /*! @note アーティファクト生成階が現在に対して足りない場合は高確率で1/(不足階層*2)を満たさないと生成リストに加えられない /
350 * XXX XXX Enforce minimum "depth" (loosely) */
351 if (a_ptr->level > floor_ptr->object_level) {
352 /* @note / Acquire the "out-of-depth factor". Roll for out-of-depth creation. */
353 int d = (a_ptr->level - floor_ptr->object_level) * 2;
358 /*! @note 1/(レア度)の確率を満たさないと除外される / Artifact "rarity roll" */
359 if (!one_in_(a_ptr->rarity))
362 /*! @note INSTA_ART型固定アーティファクトのベースアイテムもチェック対象とする。ベースアイテムの生成階層が足りない場合1/(不足階層*5)
363 * を満たさないと除外される。 / Find the base object. XXX XXX Enforce minimum "object" level (loosely). Acquire the "out-of-depth factor". Roll for
364 * out-of-depth creation. */
365 k_idx = lookup_kind(a_ptr->tval, a_ptr->sval);
366 if (k_info[k_idx].level > floor_ptr->object_level) {
367 int d = (k_info[k_idx].level - floor_ptr->object_level) * 5;
372 /*! @note 前述の条件を満たしたら、後のIDのアーティファクトはチェックせずすぐ確定し生成処理に移す /
373 * Assign the template. Mega-Hack -- mark the item as an artifact. Hack: Some artifacts get random extra powers. Success. */
374 object_prep(player_ptr, o_ptr, k_idx);
380 /*! @note 全INSTA_ART固定アーティファクトを試行しても決まらなかった場合 FALSEを返す / Failure */