OSDN Git Service

f1de8638c05a9c66fa48b4d7335bf532e8601070
[hengbandforosx/hengbandosx.git] / src / wizard / wizard-item-modifier.cpp
1 #include "wizard/wizard-item-modifier.h"
2 #include "artifact/fixed-art-generator.h"
3 #include "artifact/fixed-art-types.h"
4 #include "artifact/random-art-effects.h"
5 #include "artifact/random-art-generator.h"
6 #include "core/asking-player.h"
7 #include "core/show-file.h"
8 #include "core/stuff-handler.h"
9 #include "core/window-redrawer.h"
10 #include "flavor/flavor-describer.h"
11 #include "flavor/object-flavor-types.h"
12 #include "floor/floor-object.h"
13 #include "game-option/cheat-options.h"
14 #include "inventory/inventory-slot-types.h"
15 #include "io/input-key-acceptor.h"
16 #include "io/input-key-requester.h"
17 #include "object-enchant/item-apply-magic.h"
18 #include "object-enchant/item-magic-applier.h"
19 #include "object-enchant/object-ego.h"
20 #include "object-enchant/special-object-flags.h"
21 #include "object-enchant/tr-types.h"
22 #include "object/item-use-flags.h"
23 #include "object/object-info.h"
24 #include "object/object-kind-hook.h"
25 #include "object/object-mark-types.h"
26 #include "object/object-value.h"
27 #include "spell-kind/spells-perception.h"
28 #include "spell/spells-object.h"
29 #include "system/alloc-entries.h"
30 #include "system/artifact-type-definition.h"
31 #include "system/baseitem-info.h"
32 #include "system/floor-type-definition.h"
33 #include "system/item-entity.h"
34 #include "system/player-type-definition.h"
35 #include "system/redrawing-flags-updater.h"
36 #include "system/system-variables.h"
37 #include "term/screen-processor.h"
38 #include "term/term-color-types.h"
39 #include "term/z-form.h"
40 #include "util/bit-flags-calculator.h"
41 #include "util/int-char-converter.h"
42 #include "util/string-processor.h"
43 #include "view/display-messages.h"
44 #include "wizard/wizard-messages.h"
45 #include "wizard/wizard-special-process.h"
46 #include "world/world.h"
47 #include <algorithm>
48 #include <limits>
49 #include <sstream>
50 #include <string>
51 #include <tuple>
52 #include <vector>
53
54 constexpr auto BASEITEM_MAX_DEPTH = 110; /*!< アイテムの階層毎生成率を表示する最大階 */
55
56 namespace {
57 /*!
58  * @brief アイテム設定コマンド一覧表
59  */
60 constexpr std::array wizard_sub_menu_table = {
61     std::make_tuple('a', _("アーティファクト出現フラグリセット", "Restore aware flag of fixed artifact")),
62     std::make_tuple('A', _("アーティファクトを出現済みにする", "Make a fixed artifact awared")),
63     std::make_tuple('B', _("フロア相当の呪物ドロップ", "Drop cursed item")),
64     std::make_tuple('c', _("フロア相当の一般品獲得ドロップ (★不許可)", "Drop normal item (excluding fixed artifacts)")),
65     std::make_tuple('C', _("フロア相当の一般品獲得ドロップ (★許可)", "Drop normal item (including fixed artifacts)")),
66     std::make_tuple('d', _("フロア相当の上質品獲得ドロップ", "Drop good item")),
67     std::make_tuple('D', _("フロア相当の高級品獲得ドロップ", "Drop excellent item")),
68     std::make_tuple('e', _("フロア相当のエゴ品獲得ドロップ", "Drop excellent item")),
69     std::make_tuple('E', _("フロア相当の特別品獲得ドロップ", "Drop special item")),
70     std::make_tuple('f', _("*鑑定*", "*Idenfity*")),
71     std::make_tuple('i', _("鑑定", "Idenfity")),
72     std::make_tuple('I', _("インベントリ全*鑑定*", "Idenfity all items fully in inventory")),
73     std::make_tuple('l', _("指定アイテム番号まで一括鑑定", "Make items awared to target item id")),
74     std::make_tuple('U', _("発動を変更する", "Modify item activation")),
75     std::make_tuple('w', _("願い", "Wishing")),
76 };
77
78 /*!
79  * @brief ゲーム設定コマンドの一覧を表示する
80  */
81 void display_wizard_sub_menu()
82 {
83     for (auto y = 1U; y <= wizard_sub_menu_table.size(); y++) {
84         term_erase(14, y, 64);
85     }
86
87     int r = 1;
88     int c = 15;
89     for (const auto &[symbol, desc] : wizard_sub_menu_table) {
90         std::stringstream ss;
91         ss << symbol << ") " << desc;
92         put_str(ss.str(), r++, c);
93     }
94 }
95 }
96
97 void wiz_restore_aware_flag_of_fixed_arfifact(FixedArtifactId reset_artifact_idx, bool aware = false);
98 void wiz_modify_item_activation(PlayerType *player_ptr);
99 void wiz_identify_full_inventory(PlayerType *player_ptr);
100
101 static void wiz_item_drop(PlayerType *player_ptr, const int num_items, const EnumClassFlagGroup<ItemMagicAppliance> &appliance)
102 {
103     uint mode = AM_NONE;
104     const auto is_cursed = appliance.has(ItemMagicAppliance::CURSED);
105     if (is_cursed) {
106         mode |= AM_CURSED;
107     }
108
109     if (appliance.has(ItemMagicAppliance::GOOD)) {
110         mode |= AM_GOOD;
111     }
112
113     if (appliance.has(ItemMagicAppliance::GREAT)) {
114         mode |= AM_GREAT;
115     }
116
117     if (appliance.has(ItemMagicAppliance::SPECIAL)) {
118         mode |= AM_SPECIAL;
119     }
120
121     for (auto i = 0; i < num_items; i++) {
122         ItemEntity item;
123         if (!make_object(player_ptr, &item, mode)) {
124             continue;
125         }
126
127         if (is_cursed && !item.is_cursed()) {
128             i--;
129             continue;
130         }
131
132         if (appliance.has(ItemMagicAppliance::EGO) && !item.is_ego()) {
133             i--;
134             continue;
135         }
136
137         if (!drop_near(player_ptr, &item, -1, player_ptr->y, player_ptr->x)) {
138             msg_print_wizard(player_ptr, 0, "No item dropping space!");
139             return;
140         }
141     }
142 }
143
144 /*!
145  * @brief ゲーム設定コマンドの入力を受け付ける
146  * @param player_ptr プレイヤーの情報へのポインタ
147  */
148 void wizard_item_modifier(PlayerType *player_ptr)
149 {
150     screen_save();
151     display_wizard_sub_menu();
152
153     const auto command = input_command("Player Command: ");
154     const auto cmd = command.value_or(ESCAPE);
155     screen_load();
156
157     switch (cmd) {
158     case ESCAPE:
159     case ' ':
160     case '\n':
161     case '\r':
162         break;
163     case 'a':
164         wiz_restore_aware_flag_of_fixed_arfifact(i2enum<FixedArtifactId>(command_arg));
165         break;
166     case 'A':
167         wiz_restore_aware_flag_of_fixed_arfifact(i2enum<FixedArtifactId>(command_arg), true);
168         break;
169     case 'B':
170         command_arg = std::clamp<short>(command_arg, 1, 999);
171         wiz_item_drop(player_ptr, command_arg, { ItemMagicAppliance::CURSED });
172         break;
173     case 'c':
174         command_arg = std::clamp<short>(command_arg, 1, 999);
175         wiz_item_drop(player_ptr, command_arg, { ItemMagicAppliance::NO_FIXED_ART });
176         break;
177     case 'C':
178         command_arg = std::clamp<short>(command_arg, 1, 999);
179         wiz_item_drop(player_ptr, command_arg, {});
180         break;
181     case 'd':
182         command_arg = std::clamp<short>(command_arg, 1, 999);
183         wiz_item_drop(player_ptr, command_arg, { ItemMagicAppliance::GOOD });
184         break;
185     case 'D':
186         command_arg = std::clamp<short>(command_arg, 1, 999);
187         wiz_item_drop(player_ptr, command_arg, { ItemMagicAppliance::GOOD, ItemMagicAppliance::GREAT });
188         break;
189     case 'e':
190         command_arg = std::clamp<short>(command_arg, 1, 999);
191         wiz_item_drop(player_ptr, command_arg, { ItemMagicAppliance::GOOD, ItemMagicAppliance::GREAT, ItemMagicAppliance::EGO });
192         break;
193     case 'E':
194         command_arg = std::clamp<short>(command_arg, 1, 999);
195         wiz_item_drop(player_ptr, command_arg, { ItemMagicAppliance::GOOD, ItemMagicAppliance::GREAT, ItemMagicAppliance::SPECIAL });
196         break;
197     case 'f':
198         identify_fully(player_ptr, false);
199         break;
200     case 'i':
201         (void)ident_spell(player_ptr, false);
202         break;
203     case 'I':
204         wiz_identify_full_inventory(player_ptr);
205         break;
206     case 'l':
207         wiz_learn_items_all(player_ptr);
208         break;
209     case 'U':
210         wiz_modify_item_activation(player_ptr);
211         break;
212     case 'w':
213         do_cmd_wishing(player_ptr, -1, true, true, true);
214         break;
215     }
216 }
217
218 /*!
219  * @brief 固定アーティファクトの出現フラグをリセットする
220  * @param reset_artifact_idx 指定したアーティファクトID
221  */
222 void wiz_restore_aware_flag_of_fixed_arfifact(FixedArtifactId reset_artifact_idx, bool aware)
223 {
224     const auto max_a_idx = enum2i(artifacts_info.rbegin()->first);
225     const auto message = aware ? "Modified." : "Restored.";
226     auto &artifacts = ArtifactsInfo::get_instance();
227     if (reset_artifact_idx != FixedArtifactId::NONE) {
228         artifacts.get_artifact(reset_artifact_idx).is_generated = aware;
229         msg_print(message);
230         return;
231     }
232
233     const auto input_artifact_id = input_numerics("Artifact ID", 1, max_a_idx, FixedArtifactId::GALADRIEL_PHIAL);
234     if (!input_artifact_id.has_value()) {
235         return;
236     }
237
238     artifacts.get_artifact(input_artifact_id.value()).is_generated = aware;
239     msg_print(message);
240 }
241
242 /*!
243  * @brief オブジェクトに発動を追加する/変更する
244  * @param catser_ptr プレイヤー情報への参照ポインタ
245  */
246 void wiz_modify_item_activation(PlayerType *player_ptr)
247 {
248     constexpr auto q = _("どのアイテムの発動を変更しますか? ", "Which item? ");
249     constexpr auto s = _("発動を変更するアイテムがない。", "Nothing to do with.");
250     short i_idx;
251     auto *o_ptr = choose_object(player_ptr, &i_idx, q, s, USE_EQUIP | USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT);
252     if (!o_ptr) {
253         return;
254     }
255
256     constexpr auto min = enum2i(RandomArtActType::NONE);
257     constexpr auto max = enum2i(RandomArtActType::MAX) - 1;
258     const auto act_id = input_numerics<RandomArtActType>("Activation ID", min, max);
259     if (!act_id.has_value()) {
260         return;
261     }
262
263     auto act_idx = act_id.value();
264     o_ptr->art_flags.set(TR_ACTIVATE);
265     o_ptr->activation_id = act_idx;
266 }
267
268 /*!
269  * @brief インベントリ内のアイテムを全て*鑑定*済みにする
270  * @param catser_ptr プレイヤー情報への参照ポインタ
271  */
272 void wiz_identify_full_inventory(PlayerType *player_ptr)
273 {
274     for (int i = 0; i < INVEN_TOTAL; i++) {
275         auto *o_ptr = &player_ptr->inventory_list[i];
276         if (!o_ptr->is_valid()) {
277             continue;
278         }
279
280         auto &baseitem = o_ptr->get_baseitem();
281         baseitem.aware = true; //!< @note 記録には残さないためTRUEを立てるのみ
282         set_bits(o_ptr->ident, IDENT_KNOWN | IDENT_FULL_KNOWN);
283         o_ptr->marked.set(OmType::TOUCHED);
284     }
285
286     auto &rfu = RedrawingFlagsUpdater::get_instance();
287     static constexpr auto flags_srf = {
288         StatusRecalculatingFlag::COMBINATION,
289         StatusRecalculatingFlag::REORDER,
290     };
291     rfu.set_flags(flags_srf);
292     static constexpr auto flags_swrf = {
293         SubWindowRedrawingFlag::INVENTORY,
294         SubWindowRedrawingFlag::EQUIPMENT,
295     };
296     rfu.set_flags(flags_swrf);
297 }
298
299 /*!
300  * @brief アイテムの階層毎生成率を表示する / Output a rarity graph for a type of object.
301  * @param tval ベースアイテムの大項目ID
302  * @param sval ベースアイテムの小項目ID
303  * @param row 表示列
304  * @param col 表示行
305  */
306 static void prt_alloc(const BaseitemKey &bi_key, TERM_LEN row, TERM_LEN col)
307 {
308     uint32_t rarity[BASEITEM_MAX_DEPTH]{};
309     uint32_t total[BASEITEM_MAX_DEPTH]{};
310     int32_t display[22]{};
311
312     auto home = 0;
313     for (auto i = 0; i < BASEITEM_MAX_DEPTH; i++) {
314         auto total_frac = 0;
315         constexpr auto magnificant = CHANCE_BASEITEM_LEVEL_BOOST * BASEITEM_MAX_DEPTH;
316         for (const auto &entry : alloc_kind_table) {
317             auto prob = 0;
318             if (entry.level <= i) {
319                 prob = entry.prob1 * magnificant;
320             } else if (entry.level - 1 > 0) {
321                 prob = entry.prob1 * i * BASEITEM_MAX_DEPTH / (entry.level - 1);
322             }
323
324             const auto &baseitem = entry.get_baseitem();
325             total[i] += prob / magnificant;
326             total_frac += prob % magnificant;
327
328             if (baseitem.bi_key == bi_key) {
329                 home = baseitem.level;
330                 rarity[i] += prob / magnificant;
331             }
332         }
333
334         total[i] += total_frac / magnificant;
335     }
336
337     for (auto i = 0; i < 22; i++) {
338         auto possibility = 0;
339         for (int j = i * BASEITEM_MAX_DEPTH / 22; j < (i + 1) * BASEITEM_MAX_DEPTH / 22; j++) {
340             possibility += rarity[j] * 100000 / total[j];
341         }
342
343         display[i] = possibility / 5;
344     }
345
346     for (auto i = 0; i < 22; i++) {
347         term_putch(col, row + i + 1, TERM_WHITE, '|');
348         prt(format("%2dF", (i * 5)), row + i + 1, col);
349         if ((i * BASEITEM_MAX_DEPTH / 22 <= home) && (home < (i + 1) * BASEITEM_MAX_DEPTH / 22)) {
350             c_prt(TERM_RED, format("%3d.%04d%%", display[i] / 1000, display[i] % 1000), row + i + 1, col + 3);
351         } else {
352             c_prt(TERM_WHITE, format("%3d.%04d%%", display[i] / 1000, display[i] % 1000), row + i + 1, col + 3);
353         }
354     }
355
356     concptr r = "+---Rate---+";
357     prt(r, row, col);
358 }
359
360 /*!
361  * @brief 32ビット変数のビット配列を並べて描画する / Output a long int in binary format.
362  */
363 static void prt_binary(BIT_FLAGS flags, const int row, int col)
364 {
365     uint32_t bitmask;
366     for (int i = bitmask = 1; i <= 32; i++, bitmask *= 2) {
367         if (flags & bitmask) {
368             term_putch(col++, row, TERM_BLUE, '*');
369         } else {
370             term_putch(col++, row, TERM_WHITE, '-');
371         }
372     }
373 }
374
375 /*!
376  * @brief アイテムの詳細ステータスを表示する /
377  * Change various "permanent" player variables.
378  * @param player_ptr プレイヤーへの参照ポインタ
379  * @param o_ptr 詳細を表示するアイテム情報の参照ポインタ
380  */
381 static void wiz_display_item(PlayerType *player_ptr, ItemEntity *o_ptr)
382 {
383     auto get_seq_32bits = [](const TrFlags &flags, uint start) {
384         BIT_FLAGS result = 0U;
385         for (auto i = 0U; i < 32 && start + i < flags.size(); i++) {
386             if (flags.has(i2enum<tr_type>(start + i))) {
387                 result |= 1U << i;
388             }
389         }
390         return result;
391     };
392     int j = 13;
393     for (int i = 1; i <= 23; i++) {
394         prt("", i, j - 2);
395     }
396
397     prt_alloc(o_ptr->bi_key, 1, 0);
398     const auto item_name = describe_flavor(player_ptr, o_ptr, OD_STORE);
399     prt(item_name, 2, j);
400
401     auto line = 4;
402     const auto &bi_key = o_ptr->bi_key;
403     const auto item_level = o_ptr->get_baseitem().level;
404     prt(format("kind = %-5d  level = %-4d  tval = %-5d  sval = %-5d", o_ptr->bi_id, item_level, enum2i(bi_key.tval()), bi_key.sval().value()), line, j);
405     prt(format("number = %-3d  wgt = %-6d  ac = %-5d    damage = %dd%d", o_ptr->number, o_ptr->weight, o_ptr->ac, o_ptr->dd, o_ptr->ds), ++line, j);
406     prt(format("pval = %-5d  toac = %-5d  tohit = %-4d  todam = %-4d", o_ptr->pval, o_ptr->to_a, o_ptr->to_h, o_ptr->to_d), ++line, j);
407     prt(format("fixed_artifact_idx = %-4d  ego_idx = %-4d  cost = %d", enum2i(o_ptr->fixed_artifact_idx), enum2i(o_ptr->ego_idx), object_value_real(o_ptr)), ++line, j);
408     prt(format("ident = %04x  activation_id = %-4d  timeout = %-d", o_ptr->ident, enum2i(o_ptr->activation_id), o_ptr->timeout), ++line, j);
409     prt(format("chest_level = %-4d  fuel = %-d", o_ptr->chest_level, o_ptr->fuel), ++line, j);
410     prt(format("smith_hit = %-4d  smith_damage = %-4d", o_ptr->smith_hit, o_ptr->smith_damage), ++line, j);
411     prt(format("cursed  = %-4lX  captured_monster_speed = %-4d", o_ptr->curse_flags.to_ulong(), o_ptr->captured_monster_speed), ++line, j);
412     prt(format("captured_monster_max_hp = %-4d  captured_monster_max_hp = %-4d", o_ptr->captured_monster_current_hp, o_ptr->captured_monster_max_hp), ++line, j);
413
414     const auto flags = o_ptr->get_flags();
415     prt("+------------FLAGS1------------+", ++line, j);
416     prt("AFFECT........SLAY........BRAND.", ++line, j);
417     prt("      mf      cvae      xsqpaefc", ++line, j);
418     prt("siwdccsossidsahanvudotgddhuoclio", ++line, j);
419     prt("tnieohtctrnipttmiinmrrnrrraiierl", ++line, j);
420     prt("rtsxnarelcfgdkcpmldncltggpksdced", ++line, j);
421     prt_binary(get_seq_32bits(flags, 32 * 0), ++line, j);
422
423     prt("+------------FLAGS2------------+", ++line, j);
424     prt("SUST....IMMUN.RESIST............", ++line, j);
425     prt("      reaefctrpsaefcpfldbc sn   ", ++line, j);
426     prt("siwdcciaclioheatcliooeialoshtncd", ++line, j);
427     prt("tnieohdsierlrfraierliatrnnnrhehi", ++line, j);
428     prt("rtsxnaeydcedwlatdcedsrekdfddrxss", ++line, j);
429     prt_binary(get_seq_32bits(flags, 32 * 1), ++line, j);
430
431     line = 13;
432     prt("+------------FLAGS3------------+", line, j + 32);
433     prt("fe cnn t      stdrmsiiii d ab   ", ++line, j + 32);
434     prt("aa aoomywhs lleeieihgggg rtgl   ", ++line, j + 32);
435     prt("uu utmacaih eielgggonnnnaaere   ", ++line, j + 32);
436     prt("rr reanurdo vtieeehtrrrrcilas   ", ++line, j + 32);
437     prt("aa algarnew ienpsntsaefctnevs   ", ++line, j + 32);
438     prt_binary(get_seq_32bits(flags, 32 * 2), ++line, j + 32);
439
440     prt("+------------FLAGS4------------+", ++line, j + 32);
441     prt("KILL....ESP.........            ", ++line, j + 32);
442     prt("aeud tghaud tgdhegnu            ", ++line, j + 32);
443     prt("nvneoriunneoriruvoon            ", ++line, j + 32);
444     prt("iidmroamidmroagmionq            ", ++line, j + 32);
445     prt("mlenclnmmenclnnnldlu            ", ++line, j + 32);
446     prt_binary(get_seq_32bits(flags, 32 * 3), ++line, j + 32);
447 }
448
449 /*!
450  * @brief 検査対象のアイテムを基準とした生成テストを行う /
451  * Try to create an item again. Output some statistics.    -Bernd-
452  * @param player_ptr プレイヤーへの参照ポインタ
453  * @param o_ptr 生成テストの基準となるアイテム情報の参照ポインタ
454  * The statistics are correct now.  We acquire a clean grid, and then
455  * repeatedly place an object in this grid, copying it into an item
456  * holder, and then deleting the object.  We fiddle with the artifact
457  * counter flags to prevent weirdness.  We use the items to collect
458  * statistics on item creation relative to the initial item.
459  */
460 static void wiz_statistics(PlayerType *player_ptr, ItemEntity *o_ptr)
461 {
462     constexpr auto prompt = "Roll for [n]ormal, [g]ood, or [e]xcellent treasure? ";
463     if (o_ptr->is_fixed_artifact()) {
464         o_ptr->get_fixed_artifact().is_generated = false;
465     }
466
467     auto rolls = 1000000;
468     while (true) {
469         wiz_display_item(player_ptr, o_ptr);
470         const auto command = input_command(prompt);
471         if (!command.has_value()) {
472             break;
473         }
474
475         const auto ch = command.value();
476         BIT_FLAGS mode;
477         std::string quality;
478         if (ch == 'n' || ch == 'N') {
479             mode = 0L;
480             quality = "normal";
481         } else if (ch == 'g' || ch == 'G') {
482             mode = AM_GOOD;
483             quality = "good";
484         } else if (ch == 'e' || ch == 'E') {
485             mode = AM_GOOD | AM_GREAT;
486             quality = "excellent";
487         } else {
488             break;
489         }
490
491         constexpr auto p = "Enter number of items to roll: ";
492         const auto rolls_opt = input_numerics(p, 0, MAX_INT, rolls);
493         if (rolls_opt.has_value()) {
494             rolls = rolls_opt.value();
495         }
496
497         constexpr auto q = "Rolls: %d  Correct: %d  Matches: %d  Better: %d  Worse: %d  Other: %d";
498         msg_format("Creating a lot of %s items. Base level = %d.", quality.data(), player_ptr->current_floor_ptr->dun_level);
499         msg_print(nullptr);
500         auto correct = 0;
501         auto matches = 0;
502         auto better = 0;
503         auto worse = 0;
504         auto other = 0;
505         auto count = 0;
506         for (; count <= rolls; count++) {
507             if ((count < 100) || (count % 100 == 0)) {
508                 inkey_scan = true;
509                 if (inkey()) {
510                     flush();
511                     break; // stop rolling
512                 }
513
514                 prt(format(q, count, correct, matches, better, worse, other), 0, 0);
515                 term_fresh();
516             }
517
518             ItemEntity item;
519             if (!make_object(player_ptr, &item, mode)) {
520                 continue;
521             }
522
523             if (item.is_fixed_artifact()) {
524                 item.get_fixed_artifact().is_generated = false;
525             }
526
527             if (o_ptr->bi_key != item.bi_key) {
528                 continue;
529             }
530
531             correct++;
532             const auto is_same_fixed_artifact_idx = o_ptr->is_specific_artifact(item.fixed_artifact_idx);
533             if ((item.pval == o_ptr->pval) && (item.to_a == o_ptr->to_a) && (item.to_h == o_ptr->to_h) && (item.to_d == o_ptr->to_d) && is_same_fixed_artifact_idx) {
534                 matches++;
535             } else if ((item.pval >= o_ptr->pval) && (item.to_a >= o_ptr->to_a) && (item.to_h >= o_ptr->to_h) && (item.to_d >= o_ptr->to_d)) {
536                 better++;
537             } else if ((item.pval <= o_ptr->pval) && (item.to_a <= o_ptr->to_a) && (item.to_h <= o_ptr->to_h) && (item.to_d <= o_ptr->to_d)) {
538                 worse++;
539             } else {
540                 other++;
541             }
542         }
543
544         msg_format(q, count, correct, matches, better, worse, other);
545         msg_print(nullptr);
546     }
547
548     if (o_ptr->is_fixed_artifact()) {
549         o_ptr->get_fixed_artifact().is_generated = true;
550     }
551 }
552
553 /*!
554  * @brief アイテムの質を選択して再生成する /
555  * Apply magic to an item or turn it into an artifact. -Bernd-
556  * @param o_ptr 再生成の対象となるアイテム情報の参照ポインタ
557  */
558 static void wiz_reroll_item(PlayerType *player_ptr, ItemEntity *o_ptr)
559 {
560     if (o_ptr->is_fixed_or_random_artifact()) {
561         return;
562     }
563
564     ItemEntity forge;
565     auto *q_ptr = &forge;
566     q_ptr->copy_from(o_ptr);
567
568     auto changed = false;
569     constexpr auto prompt = "[a]ccept, [w]orthless, [c]ursed, [n]ormal, [g]ood, [e]xcellent, [s]pecial? ";
570     while (true) {
571         wiz_display_item(player_ptr, q_ptr);
572         const auto command = input_command(prompt);
573         if (!command.has_value()) {
574             if (q_ptr->is_fixed_artifact()) {
575                 q_ptr->get_fixed_artifact().is_generated = false;
576                 q_ptr->fixed_artifact_idx = FixedArtifactId::NONE;
577             }
578
579             changed = false;
580             break;
581         }
582
583         const auto ch = command.value();
584         if (ch == 'A' || ch == 'a') {
585             changed = true;
586             break;
587         }
588
589         if (q_ptr->is_fixed_artifact()) {
590             q_ptr->get_fixed_artifact().is_generated = false;
591             q_ptr->fixed_artifact_idx = FixedArtifactId::NONE;
592         }
593
594         switch (tolower(ch)) {
595         /* Apply bad magic, but first clear object */
596         case 'w':
597             q_ptr->prep(o_ptr->bi_id);
598             ItemMagicApplier(player_ptr, q_ptr, player_ptr->current_floor_ptr->dun_level, AM_NO_FIXED_ART | AM_GOOD | AM_GREAT | AM_CURSED).execute();
599             break;
600         /* Apply bad magic, but first clear object */
601         case 'c':
602             q_ptr->prep(o_ptr->bi_id);
603             ItemMagicApplier(player_ptr, q_ptr, player_ptr->current_floor_ptr->dun_level, AM_NO_FIXED_ART | AM_GOOD | AM_CURSED).execute();
604             break;
605         /* Apply normal magic, but first clear object */
606         case 'n':
607             q_ptr->prep(o_ptr->bi_id);
608             ItemMagicApplier(player_ptr, q_ptr, player_ptr->current_floor_ptr->dun_level, AM_NO_FIXED_ART).execute();
609             break;
610         /* Apply good magic, but first clear object */
611         case 'g':
612             q_ptr->prep(o_ptr->bi_id);
613             ItemMagicApplier(player_ptr, q_ptr, player_ptr->current_floor_ptr->dun_level, AM_NO_FIXED_ART | AM_GOOD).execute();
614             break;
615         /* Apply great magic, but first clear object */
616         case 'e':
617             q_ptr->prep(o_ptr->bi_id);
618             ItemMagicApplier(player_ptr, q_ptr, player_ptr->current_floor_ptr->dun_level, AM_NO_FIXED_ART | AM_GOOD | AM_GREAT).execute();
619             break;
620         /* Apply special magic, but first clear object */
621         case 's':
622             q_ptr->prep(o_ptr->bi_id);
623             ItemMagicApplier(player_ptr, q_ptr, player_ptr->current_floor_ptr->dun_level, AM_GOOD | AM_GREAT | AM_SPECIAL).execute();
624             if (!q_ptr->is_fixed_or_random_artifact()) {
625                 become_random_artifact(player_ptr, q_ptr, false);
626             }
627
628             break;
629         default:
630             break;
631         }
632
633         q_ptr->iy = o_ptr->iy;
634         q_ptr->ix = o_ptr->ix;
635         q_ptr->marked = o_ptr->marked;
636     }
637
638     if (!changed) {
639         return;
640     }
641
642     o_ptr->copy_from(q_ptr);
643     auto &rfu = RedrawingFlagsUpdater::get_instance();
644     static constexpr auto flags_srf = {
645         StatusRecalculatingFlag::BONUS,
646         StatusRecalculatingFlag::COMBINATION,
647         StatusRecalculatingFlag::REORDER,
648     };
649     rfu.set_flags(flags_srf);
650     static constexpr auto flags_swrf = {
651         SubWindowRedrawingFlag::INVENTORY,
652         SubWindowRedrawingFlag::EQUIPMENT,
653         SubWindowRedrawingFlag::SPELL,
654         SubWindowRedrawingFlag::PLAYER,
655         SubWindowRedrawingFlag::FLOOR_ITEMS,
656         SubWindowRedrawingFlag::FOUND_ITEMS,
657     };
658     rfu.set_flags(flags_swrf);
659 }
660
661 /*!
662  * @briefアイテムの基礎能力値を調整する / Tweak an item
663  * @param player_ptr プレイヤーへの参照ポインタ
664  * @param o_ptr 調整するアイテムの参照ポインタ
665  */
666 static void wiz_tweak_item(PlayerType *player_ptr, ItemEntity *o_ptr)
667 {
668     if (o_ptr->is_fixed_or_random_artifact()) {
669         return;
670     }
671
672     const auto pval = input_numerics("Enter new 'pval' setting: ", -MAX_SHORT, MAX_SHORT, o_ptr->pval);
673     if (!pval.has_value()) {
674         return;
675     }
676
677     o_ptr->pval = pval.value();
678     wiz_display_item(player_ptr, o_ptr);
679     const auto bonus_ac = input_numerics("Enter new AC Bonus setting: ", -MAX_SHORT, MAX_SHORT, o_ptr->to_a);
680     if (!bonus_ac.has_value()) {
681         return;
682     }
683
684     o_ptr->to_a = bonus_ac.value();
685     wiz_display_item(player_ptr, o_ptr);
686     const auto bonus_hit = input_numerics("Enter new Hit Bonus setting: ", -MAX_SHORT, MAX_SHORT, o_ptr->to_h);
687     if (!bonus_hit.has_value()) {
688         return;
689     }
690
691     o_ptr->to_h = bonus_hit.value();
692     wiz_display_item(player_ptr, o_ptr);
693     const auto bonus_damage = input_numerics("Enter new Damage Bonus setting: ", -MAX_SHORT, MAX_SHORT, o_ptr->to_d);
694     if (!bonus_damage.has_value()) {
695         return;
696     }
697
698     o_ptr->to_d = bonus_damage.value();
699     wiz_display_item(player_ptr, o_ptr);
700 }
701
702 /*!
703  * @brief 検査対象のアイテムの数を変更する
704  * @param o_ptr 変更するアイテム情報構造体の参照ポインタ
705  */
706 static void wiz_quantity_item(ItemEntity *o_ptr)
707 {
708     if (o_ptr->is_fixed_or_random_artifact()) {
709         return;
710     }
711
712     const auto quantity_opt = input_numerics("Quantity: ", 1, 99, o_ptr->number);
713     if (!quantity_opt.has_value()) {
714         return;
715     }
716
717     const auto quantity = quantity_opt.value();
718     o_ptr->number = quantity;
719     if (o_ptr->bi_key.tval() == ItemKindType::ROD) {
720         o_ptr->pval = o_ptr->pval * o_ptr->number / quantity;
721     }
722 }
723
724 /*!
725  * @brief アイテムを弄るデバッグコマンド
726  * Play with an item. Options include:
727  * @details
728  *   - Output statistics (via wiz_roll_item)<br>
729  *   - Reroll item (via wiz_reroll_item)<br>
730  *   - Change properties (via wiz_tweak_item)<br>
731  *   - Change the number of items (via wiz_quantity_item)<br>
732  */
733 void wiz_modify_item(PlayerType *player_ptr)
734 {
735     constexpr auto q = "Play with which object? ";
736     constexpr auto s = "You have nothing to play with.";
737     short i_idx;
738     auto *o_ptr = choose_object(player_ptr, &i_idx, q, s, USE_EQUIP | USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT);
739     if (!o_ptr) {
740         return;
741     }
742
743     screen_save();
744
745     ItemEntity forge;
746     auto *q_ptr = &forge;
747     q_ptr->copy_from(o_ptr);
748     auto changed = false;
749     constexpr auto prompt = "[a]ccept [s]tatistics [r]eroll [t]weak [q]uantity? ";
750     while (true) {
751         wiz_display_item(player_ptr, q_ptr);
752         const auto command = input_command(prompt);
753         if (!command.has_value()) {
754             changed = false;
755             break;
756         }
757
758         const auto ch = command.value();
759         if (ch == 'A' || ch == 'a') {
760             changed = true;
761             break;
762         }
763
764         if (ch == 's' || ch == 'S') {
765             wiz_statistics(player_ptr, q_ptr);
766         }
767
768         if (ch == 'r' || ch == 'R') {
769             wiz_reroll_item(player_ptr, q_ptr);
770         }
771
772         if (ch == 't' || ch == 'T') {
773             wiz_tweak_item(player_ptr, q_ptr);
774         }
775
776         if (ch == 'q' || ch == 'Q') {
777             wiz_quantity_item(q_ptr);
778         }
779     }
780
781     screen_load();
782     if (changed) {
783         msg_print("Changes accepted.");
784
785         o_ptr->copy_from(q_ptr);
786         auto &rfu = RedrawingFlagsUpdater::get_instance();
787         static constexpr auto flags_srf = {
788             StatusRecalculatingFlag::BONUS,
789             StatusRecalculatingFlag::COMBINATION,
790             StatusRecalculatingFlag::REORDER,
791         };
792         rfu.set_flags(flags_srf);
793         static constexpr auto flags_swrf = {
794             SubWindowRedrawingFlag::INVENTORY,
795             SubWindowRedrawingFlag::EQUIPMENT,
796             SubWindowRedrawingFlag::SPELL,
797             SubWindowRedrawingFlag::PLAYER,
798             SubWindowRedrawingFlag::FLOOR_ITEMS,
799             SubWindowRedrawingFlag::FOUND_ITEMS,
800         };
801         rfu.set_flags(flags_swrf);
802     } else {
803         msg_print("Changes ignored.");
804     }
805 }
806
807 /*!
808  * @brief オブジェクトの装備スロットがエゴが有効なスロットかどうか判定
809  */
810 static int is_slot_able_to_be_ego(PlayerType *player_ptr, ItemEntity *o_ptr)
811 {
812     int slot = wield_slot(player_ptr, o_ptr);
813
814     if (slot > -1) {
815         return slot;
816     }
817
818     if (o_ptr->is_ammo()) {
819         return INVEN_AMMO;
820     }
821
822     return -1;
823 }
824
825 /*!
826  * @brief 願ったが消えてしまった場合のメッセージ
827  */
828 static void wishing_puff_of_smoke(void)
829 {
830     msg_print(_("何かが足下に転がってきたが、煙のように消えてしまった。",
831         "You feel something roll beneath your feet, but it disappears in a puff of smoke!"));
832 }
833
834 /*!
835  * @brief 願ったが消えてしまった場合のメッセージ
836  * @param player_ptr 願ったプレイヤー情報への参照ポインタ
837  * @param prob ★などを願った場合の生成確率
838  * @param art_ok アーティファクトの生成を許すならTRUE
839  * @param ego_ok エゴの生成を許すならTRUE
840  * @param confirm 願わない場合に確認するかどうか
841  * @return 願った結果
842  */
843 WishResultType do_cmd_wishing(PlayerType *player_ptr, int prob, bool allow_art, bool allow_ego, bool confirm)
844 {
845     const std::array<std::string, _(4, 6)> fixed_expressions = {
846 #ifdef JP
847         "燃えない",
848         "錆びない",
849         "腐食しない",
850         "安定した",
851 #else
852         "rotproof",
853         "fireproof",
854         "rustproof",
855         "erodeproof",
856         "corrodeproof",
857         "fixed",
858 #endif
859     };
860
861     ItemEntity forge;
862     auto *o_ptr = &forge;
863     auto wish_art = false;
864     auto wish_randart = false;
865     auto wish_ego = false;
866     auto exam_base = true;
867     auto ok_art = randint0(100) < prob;
868     auto ok_ego = randint0(100) < 50 + prob;
869     auto must = prob < 0;
870     auto blessed = false;
871     auto fixed = true;
872
873     std::string pray;
874     while (true) {
875         const auto pray_opt = input_string(_("何をお望み? ", "For what do you wish?"), MAX_NLEN);
876         if (pray_opt.has_value()) {
877             pray = pray_opt.value();
878             break;
879         }
880
881         if (confirm) {
882             if (!input_check(_("何も願いません。本当によろしいですか?", "Do you wish nothing, really? "))) {
883                 continue;
884             }
885         }
886
887         return WishResultType::NOTHING;
888     }
889
890     auto *str = pray.data();
891 #ifndef JP
892     str_tolower(str);
893     const std::string article_single("a ");
894     const std::string article_multi("an ");
895     if (pray.starts_with("a ")) {
896         str += article_single.length();
897     } else if (pray.starts_with("an ")) {
898         str += article_multi.length();
899     }
900
901     str = ltrim(str);
902 #endif // !JP
903
904     str = rtrim(str);
905
906     if (!strncmp(str, _("祝福された", "blessed"), _(10, 7))) {
907         str = ltrim(str + _(10, 7));
908         blessed = true;
909     }
910
911     for (const auto &expression : fixed_expressions) {
912         auto len = expression.length();
913         if (std::string_view(str).starts_with(expression)) {
914             str = ltrim(str + len);
915             fixed = true;
916             break;
917         }
918     }
919
920 #ifdef JP
921     if (!strncmp(str, "★", 2)) {
922         str = ltrim(str + 2);
923         wish_art = true;
924         exam_base = false;
925     } else
926 #endif
927
928         if (!strncmp(str, _("☆", "The "), _(2, 4))) {
929         str = ltrim(str + _(2, 4));
930         wish_art = true;
931         wish_randart = true;
932     }
933
934     /* wishing random ego ? */
935     else if (!strncmp(str, _("高級な", "excellent "), _(6, 9))) {
936         str = ltrim(str + _(6, 9));
937         wish_ego = true;
938     }
939
940     if (strlen(str) < 1) {
941         msg_print(_("名前がない!", "What?"));
942         return WishResultType::NOTHING;
943     }
944
945     if (!allow_art && wish_art) {
946         msg_print(_("アーティファクトは願えない!", "You can not wish artifacts!"));
947         return WishResultType::NOTHING;
948     }
949
950     if (cheat_xtra) {
951         msg_format("Wishing %s....", pray.data());
952     }
953
954     std::vector<short> baseitem_ids;
955     std::vector<EgoType> ego_ids;
956     if (exam_base) {
957         auto max_len = 0;
958         for (const auto &baseitem : baseitems_info) {
959             if (baseitem.idx == 0 || baseitem.name.empty()) {
960                 continue;
961             }
962
963             o_ptr->prep(baseitem.idx);
964 #ifdef JP
965             const auto item_name = describe_flavor(player_ptr, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY | OD_STORE));
966 #else
967             auto item_name = describe_flavor(player_ptr, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY | OD_STORE));
968             str_tolower(item_name.data());
969 #endif
970             if (cheat_xtra) {
971                 msg_format("Matching object No.%d %s", baseitem.idx, item_name.data());
972             }
973
974             const int len = item_name.length();
975             if (std::string(str).find(item_name) != std::string::npos) {
976                 if (len > max_len) {
977                     baseitem_ids.push_back(baseitem.idx);
978                     max_len = len;
979                 }
980             }
981         }
982
983         if (allow_ego && baseitem_ids.size() == 1) {
984             short bi_id = baseitem_ids.back();
985             o_ptr->prep(bi_id);
986
987             for (const auto &[e_idx, ego] : egos_info) {
988                 if (ego.idx == EgoType::NONE || ego.name.empty()) {
989                     continue;
990                 }
991
992                 std::string item_name(ego.name);
993 #ifdef JP
994 #else
995                 str_tolower(item_name.data());
996 #endif
997                 if (cheat_xtra) {
998                     msg_format("matching ego no.%d %s...", enum2i(ego.idx), item_name.data());
999                 }
1000
1001                 if (std::string(str).find(item_name) != std::string::npos) {
1002                     if (is_slot_able_to_be_ego(player_ptr, o_ptr) != ego.slot) {
1003                         continue;
1004                     }
1005
1006                     ego_ids.push_back(ego.idx);
1007                 }
1008             }
1009         }
1010     }
1011
1012     std::vector<FixedArtifactId> artifact_ids;
1013
1014     if (allow_art) {
1015         char a_desc[MAX_NLEN] = "\0";
1016         char *a_str = a_desc;
1017
1018         int len;
1019         auto mlen = 0;
1020         for (const auto &[a_idx, artifact] : artifacts_info) {
1021             if (a_idx == FixedArtifactId::NONE || artifact.name.empty()) {
1022                 continue;
1023             }
1024
1025             const auto bi_id = lookup_baseitem_id(artifact.bi_key);
1026             if (bi_id == 0) {
1027                 continue;
1028             }
1029
1030             o_ptr->prep(bi_id);
1031             o_ptr->fixed_artifact_idx = a_idx;
1032
1033 #ifdef JP
1034             const auto item_name = describe_flavor(player_ptr, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY | OD_STORE));
1035 #else
1036             auto item_name = describe_flavor(player_ptr, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY | OD_STORE));
1037             str_tolower(item_name.data());
1038 #endif
1039             a_str = a_desc;
1040             strcpy(a_desc, artifact.name.data());
1041
1042             if (*a_str == '$') {
1043                 a_str++;
1044             }
1045 #ifdef JP
1046             /* remove quotes */
1047             if (!strncmp(a_str, "『", 2)) {
1048                 a_str += 2;
1049                 char *s = strstr(a_str, "』");
1050                 *s = '\0';
1051             }
1052             /* remove 'of' */
1053             else {
1054                 int l = strlen(a_str);
1055                 if (!strrncmp(a_str, "の", 2)) {
1056                     a_str[l - 2] = '\0';
1057                 }
1058             }
1059 #else
1060             /* remove quotes */
1061             if (a_str[0] == '\'') {
1062                 a_str += 1;
1063                 auto *s = angband_strchr(a_desc, '\'');
1064                 *s = '\0';
1065             }
1066             /* remove 'of ' */
1067             else if (!strncmp(a_str, (const char *)"of ", 3)) {
1068                 a_str += 3;
1069             }
1070
1071             str_tolower(a_str);
1072 #endif
1073             const auto match_name = _(item_name.data() + 2, item_name.data());
1074             if (cheat_xtra) {
1075                 msg_format("Matching artifact No.%d %s(%s)", enum2i(a_idx), a_desc, match_name);
1076             }
1077
1078             std::vector<const char *> l = { a_str, artifact.name.data(), match_name };
1079             for (size_t c = 0; c < l.size(); c++) {
1080                 if (!strcmp(str, l.at(c))) {
1081                     len = strlen(l.at(c));
1082                     if (len > mlen) {
1083                         artifact_ids.push_back(a_idx);
1084                         mlen = len;
1085                     }
1086                 }
1087             }
1088         }
1089     }
1090
1091     if (w_ptr->wizard && ((artifact_ids.size() > 1) || (ego_ids.size() > 1))) {
1092         msg_print(_("候補が多すぎる!", "Too many matches!"));
1093         return WishResultType::FAIL;
1094     }
1095
1096     if (artifact_ids.size() == 1) {
1097         const auto a_idx = artifact_ids.back();
1098         const auto &artifact = ArtifactsInfo::get_instance().get_artifact(a_idx);
1099         if (must || (ok_art && !artifact.is_generated)) {
1100             (void)create_named_art(player_ptr, a_idx, player_ptr->y, player_ptr->x);
1101         } else {
1102             wishing_puff_of_smoke();
1103         }
1104
1105         return WishResultType::ARTIFACT;
1106     }
1107
1108     if (!allow_ego && (wish_ego || ego_ids.size() > 0)) {
1109         msg_print(_("エゴアイテムは願えない!", "Can not wish ego item."));
1110         return WishResultType::NOTHING;
1111     }
1112
1113     if (baseitem_ids.size() == 1) {
1114         const auto bi_id = baseitem_ids.back();
1115         const auto &baseitem = baseitems_info[bi_id];
1116         auto a_idx = FixedArtifactId::NONE;
1117         if (baseitem.gen_flags.has(ItemGenerationTraitType::INSTA_ART)) {
1118             for (const auto &[a_idx_loop, artifact_loop] : artifacts_info) {
1119                 if (a_idx_loop == FixedArtifactId::NONE || artifact_loop.bi_key != baseitem.bi_key) {
1120                     continue;
1121                 }
1122
1123                 a_idx = a_idx_loop;
1124                 break;
1125             }
1126         }
1127
1128         if (a_idx != FixedArtifactId::NONE) {
1129             const auto &artifact = ArtifactsInfo::get_instance().get_artifact(a_idx);
1130             if (must || (ok_art && !artifact.is_generated)) {
1131                 (void)create_named_art(player_ptr, a_idx, player_ptr->y, player_ptr->x);
1132             } else {
1133                 wishing_puff_of_smoke();
1134             }
1135
1136             return WishResultType::ARTIFACT;
1137         }
1138
1139         if (wish_randart) {
1140             if (must || ok_art) {
1141                 do {
1142                     o_ptr->prep(bi_id);
1143                     ItemMagicApplier(player_ptr, o_ptr, baseitem.level, AM_SPECIAL | AM_NO_FIXED_ART).execute();
1144                 } while (!o_ptr->is_random_artifact() || o_ptr->is_ego() || o_ptr->is_cursed());
1145
1146                 if (o_ptr->is_random_artifact()) {
1147                     drop_near(player_ptr, o_ptr, -1, player_ptr->y, player_ptr->x);
1148                 }
1149             } else {
1150                 wishing_puff_of_smoke();
1151             }
1152             return WishResultType::ARTIFACT;
1153         }
1154
1155         WishResultType res = WishResultType::NOTHING;
1156         if (allow_ego && (wish_ego || ego_ids.size() > 0)) {
1157             if (must || ok_ego) {
1158                 if (ego_ids.size() > 0) {
1159                     o_ptr->prep(bi_id);
1160                     o_ptr->ego_idx = ego_ids[0];
1161                     apply_ego(o_ptr, player_ptr->current_floor_ptr->base_level);
1162                 } else {
1163                     auto max_roll = 1000;
1164                     auto i = 0;
1165                     for (i = 0; i < max_roll; i++) {
1166                         o_ptr->prep(bi_id);
1167                         ItemMagicApplier(player_ptr, o_ptr, baseitem.level, AM_GREAT | AM_NO_FIXED_ART).execute();
1168                         if (o_ptr->is_random_artifact()) {
1169                             continue;
1170                         }
1171
1172                         if (wish_ego) {
1173                             break;
1174                         }
1175
1176                         auto e_idx = EgoType::NONE;
1177                         for (auto e : ego_ids) {
1178                             if (o_ptr->ego_idx == e) {
1179                                 e_idx = e;
1180                                 break;
1181                             }
1182                         }
1183
1184                         if (e_idx != EgoType::NONE) {
1185                             break;
1186                         }
1187                     }
1188
1189                     if (i == max_roll) {
1190                         msg_print(_("失敗!もう一度願ってみてください。", "Failed! Try again."));
1191                         return WishResultType::FAIL;
1192                     }
1193                 }
1194             } else {
1195                 wishing_puff_of_smoke();
1196             }
1197
1198             res = WishResultType::EGO;
1199         } else {
1200             for (auto i = 0; i < 100; i++) {
1201                 o_ptr->prep(bi_id);
1202                 ItemMagicApplier(player_ptr, o_ptr, 0, AM_NO_FIXED_ART).execute();
1203                 if (!o_ptr->is_cursed()) {
1204                     break;
1205                 }
1206             }
1207
1208             res = WishResultType::NORMAL;
1209         }
1210
1211         if (blessed && wield_slot(player_ptr, o_ptr) != -1) {
1212             o_ptr->art_flags.set(TR_BLESSED);
1213         }
1214
1215         if (fixed && wield_slot(player_ptr, o_ptr) != -1) {
1216             o_ptr->art_flags.set(TR_IGNORE_ACID);
1217             o_ptr->art_flags.set(TR_IGNORE_FIRE);
1218         }
1219
1220         (void)drop_near(player_ptr, o_ptr, -1, player_ptr->y, player_ptr->x);
1221         return res;
1222     }
1223
1224     msg_print(_("うーん、そんなものは存在しないようだ。", "Ummmm, that is not existing..."));
1225     return WishResultType::FAIL;
1226 }