OSDN Git Service

[Refactor] #40399 Renamed object-appraiser.c/h to object-perception.c/h and simple...
[hengband/hengband.git] / src / cmd-item / cmd-read.c
1 /*!
2  * @brief プレイヤーの読むコマンド実装
3  * @date 2018/09/07
4  * @author deskull
5  */
6
7 #include "cmd-item/cmd-read.h"
8 #include "cmd/cmd-basic.h"
9 #include "core/show-file.h"
10 #include "floor/floor.h"
11 #include "inventory/inventory-object.h"
12 #include "inventory/player-inventory.h"
13 #include "io/files-util.h"
14 #include "main/sound-definitions-table.h"
15 #include "object-enchant/artifact.h"
16 #include "object/item-use-flags.h"
17 #include "perception/object-perception.h"
18 #include "object/object-flavor.h"
19 #include "object/object-hook.h"
20 #include "object/object-kind.h"
21 #include "sv-definition/sv-scroll-types.h"
22 #include "player/avatar.h"
23 #include "player/player-class.h"
24 #include "player/player-damage.h"
25 #include "player/player-effects.h"
26 #include "player/player-status.h"
27 #include "realm/realm-hex.h"
28 #include "spell/spells-detection.h"
29 #include "spell/spells-floor.h"
30 #include "spell/spells-object.h"
31 #include "spell/spells-status.h"
32 #include "spell/spells-summon.h"
33 #include "spell/spells-type.h"
34 #include "spell/spells2.h"
35 #include "spell/spells3.h"
36 #include "store/rumor.h"
37 #include "util/util.h"
38 #include "view/display-main-window.h"
39
40 /*!
41  * @brief 巻物を読むコマンドのサブルーチン
42  * Read a scroll (from the pack or floor).
43  * @param creature_ptr プレーヤーへの参照ポインタ
44  * @param item 読むオブジェクトの所持品ID
45  * @param known 判明済ならばTRUE
46  * @return なし
47  * @details
48  * <pre>
49  * Certain scrolls can be "aborted" without losing the scroll.  These
50  * include scrolls with no effects but recharge or identify, which are
51  * cancelled before use.  XXX Reading them still takes a turn, though.
52  * </pre>
53  */
54 void exe_read(player_type *creature_ptr, INVENTORY_IDX item, bool known)
55 {
56         int k, used_up, ident, lev;
57         object_type *o_ptr;
58
59         o_ptr = ref_item(creature_ptr, item);
60
61         take_turn(creature_ptr, 100);
62         if (cmd_limit_time_walk(creature_ptr)) return;
63
64         if (creature_ptr->pclass == CLASS_BERSERKER)
65         {
66                 msg_print(_("巻物なんて読めない。", "You cannot read."));
67                 return;
68         }
69
70         if (music_singing_any(creature_ptr)) stop_singing(creature_ptr);
71         if (hex_spelling_any(creature_ptr) && ((creature_ptr->lev < 35) || hex_spell_fully(creature_ptr))) stop_hex_spell_all(creature_ptr);
72
73         /* Not identified yet */
74         ident = FALSE;
75
76         /* Object level */
77         lev = k_info[o_ptr->k_idx].level;
78
79         /* Assume the scroll will get used up */
80         used_up = TRUE;
81
82         if (o_ptr->tval == TV_SCROLL)
83         {
84         /* Analyze the scroll */
85         switch (o_ptr->sval)
86         {
87                 case SV_SCROLL_DARKNESS:
88                 {
89                         if (!(creature_ptr->resist_blind) && !(creature_ptr->resist_dark))
90                         {
91                                 (void)set_blind(creature_ptr, creature_ptr->blind + 3 + randint1(5));
92                         }
93                         if (unlite_area(creature_ptr, 10, 3)) ident = TRUE;
94                         break;
95                 }
96
97                 case SV_SCROLL_AGGRAVATE_MONSTER:
98                 {
99                         msg_print(_("カン高くうなる様な音が辺りを覆った。", "There is a high pitched humming noise."));
100                         aggravate_monsters(creature_ptr, 0);
101                         ident = TRUE;
102                         break;
103                 }
104
105                 case SV_SCROLL_CURSE_ARMOR:
106                 {
107                         if (curse_armor(creature_ptr)) ident = TRUE;
108                         break;
109                 }
110
111                 case SV_SCROLL_CURSE_WEAPON:
112                 {
113                         k = 0;
114                         if (has_melee_weapon(creature_ptr, INVEN_RARM))
115                         {
116                                 k = INVEN_RARM;
117                                 if (has_melee_weapon(creature_ptr, INVEN_LARM) && one_in_(2)) k = INVEN_LARM;
118                         }
119                         else if (has_melee_weapon(creature_ptr, INVEN_LARM)) k = INVEN_LARM;
120                         if (k && curse_weapon_object(creature_ptr, FALSE, &creature_ptr->inventory_list[k])) ident = TRUE;
121                         break;
122                 }
123
124                 case SV_SCROLL_SUMMON_MONSTER:
125                 {
126                         for (k = 0; k < randint1(3); k++)
127                         {
128                                 if (summon_specific(creature_ptr, 0, creature_ptr->y, creature_ptr->x, creature_ptr->current_floor_ptr->dun_level, 0, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET)))
129                                 {
130                                         ident = TRUE;
131                                 }
132                         }
133                         break;
134                 }
135
136                 case SV_SCROLL_SUMMON_UNDEAD:
137                 {
138                         for (k = 0; k < randint1(3); k++)
139                         {
140                                 if (summon_specific(creature_ptr, 0, creature_ptr->y, creature_ptr->x, creature_ptr->current_floor_ptr->dun_level, SUMMON_UNDEAD, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET)))
141                                 {
142                                         ident = TRUE;
143                                 }
144                         }
145                         break;
146                 }
147
148                 case SV_SCROLL_SUMMON_PET:
149                 {
150                         if (summon_specific(creature_ptr, -1, creature_ptr->y, creature_ptr->x, creature_ptr->current_floor_ptr->dun_level, 0, (PM_ALLOW_GROUP | PM_FORCE_PET)))
151                         {
152                                 ident = TRUE;
153                         }
154                         break;
155                 }
156
157                 case SV_SCROLL_SUMMON_KIN:
158                 {
159                         if (summon_kin_player(creature_ptr, creature_ptr->lev, creature_ptr->y, creature_ptr->x, (PM_FORCE_PET | PM_ALLOW_GROUP)))
160                         {
161                                 ident = TRUE;
162                         }
163                         break;
164                 }
165
166                 case SV_SCROLL_TRAP_CREATION:
167                 {
168                         if (trap_creation(creature_ptr, creature_ptr->y, creature_ptr->x)) ident = TRUE;
169                         break;
170                 }
171
172                 case SV_SCROLL_PHASE_DOOR:
173                 {
174                         teleport_player(creature_ptr, 10, TELEPORT_SPONTANEOUS);
175                         ident = TRUE;
176                         break;
177                 }
178
179                 case SV_SCROLL_TELEPORT:
180                 {
181                         teleport_player(creature_ptr, 100, TELEPORT_SPONTANEOUS);
182                         ident = TRUE;
183                         break;
184                 }
185
186                 case SV_SCROLL_TELEPORT_LEVEL:
187                 {
188                         (void)teleport_level(creature_ptr, 0);
189                         ident = TRUE;
190                         break;
191                 }
192
193                 case SV_SCROLL_WORD_OF_RECALL:
194                 {
195                         if (!recall_player(creature_ptr, randint0(21) + 15)) used_up = FALSE;
196                         ident = TRUE;
197                         break;
198                 }
199
200                 case SV_SCROLL_IDENTIFY:
201                 {
202                         if (!ident_spell(creature_ptr, FALSE, 0)) used_up = FALSE;
203                         ident = TRUE;
204                         break;
205                 }
206
207                 case SV_SCROLL_STAR_IDENTIFY:
208                 {
209                         if (!identify_fully(creature_ptr, FALSE, 0)) used_up = FALSE;
210                         ident = TRUE;
211                         break;
212                 }
213
214                 case SV_SCROLL_REMOVE_CURSE:
215                 {
216                         if (remove_curse(creature_ptr))
217                         {
218                                 ident = TRUE;
219                         }
220                         break;
221                 }
222
223                 case SV_SCROLL_STAR_REMOVE_CURSE:
224                 {
225                         if (remove_all_curse(creature_ptr))
226                         {
227                                 ident = TRUE;
228                         }
229                         break;
230                 }
231
232                 case SV_SCROLL_ENCHANT_ARMOR:
233                 {
234                         ident = TRUE;
235                         if (!enchant_spell(creature_ptr, 0, 0, 1)) used_up = FALSE;
236                         break;
237                 }
238
239                 case SV_SCROLL_ENCHANT_WEAPON_TO_HIT:
240                 {
241                         if (!enchant_spell(creature_ptr, 1, 0, 0)) used_up = FALSE;
242                         ident = TRUE;
243                         break;
244                 }
245
246                 case SV_SCROLL_ENCHANT_WEAPON_TO_DAM:
247                 {
248                         if (!enchant_spell(creature_ptr, 0, 1, 0)) used_up = FALSE;
249                         ident = TRUE;
250                         break;
251                 }
252
253                 case SV_SCROLL_STAR_ENCHANT_ARMOR:
254                 {
255                         if (!enchant_spell(creature_ptr, 0, 0, randint1(3) + 2)) used_up = FALSE;
256                         ident = TRUE;
257                         break;
258                 }
259
260                 case SV_SCROLL_STAR_ENCHANT_WEAPON:
261                 {
262                         if (!enchant_spell(creature_ptr, randint1(3), randint1(3), 0)) used_up = FALSE;
263                         ident = TRUE;
264                         break;
265                 }
266
267                 case SV_SCROLL_RECHARGING:
268                 {
269                         if (!recharge(creature_ptr, 130)) used_up = FALSE;
270                         ident = TRUE;
271                         break;
272                 }
273
274                 case SV_SCROLL_MUNDANITY:
275                 {
276                         ident = TRUE;
277                         if (!mundane_spell(creature_ptr, FALSE)) used_up = FALSE;
278                         break;
279                 }
280
281                 case SV_SCROLL_LIGHT:
282                 {
283                         if (lite_area(creature_ptr, damroll(2, 8), 2)) ident = TRUE;
284                         break;
285                 }
286
287                 case SV_SCROLL_MAPPING:
288                 {
289                         map_area(creature_ptr, DETECT_RAD_MAP);
290                         ident = TRUE;
291                         break;
292                 }
293
294                 case SV_SCROLL_DETECT_GOLD:
295                 {
296                         if (detect_treasure(creature_ptr, DETECT_RAD_DEFAULT)) ident = TRUE;
297                         if (detect_objects_gold(creature_ptr, DETECT_RAD_DEFAULT)) ident = TRUE;
298                         break;
299                 }
300
301                 case SV_SCROLL_DETECT_ITEM:
302                 {
303                         if (detect_objects_normal(creature_ptr, DETECT_RAD_DEFAULT)) ident = TRUE;
304                         break;
305                 }
306
307                 case SV_SCROLL_DETECT_TRAP:
308                 {
309                         if (detect_traps(creature_ptr, DETECT_RAD_DEFAULT, known)) ident = TRUE;
310                         break;
311                 }
312
313                 case SV_SCROLL_DETECT_DOOR:
314                 {
315                         if (detect_doors(creature_ptr, DETECT_RAD_DEFAULT)) ident = TRUE;
316                         if (detect_stairs(creature_ptr, DETECT_RAD_DEFAULT)) ident = TRUE;
317                         break;
318                 }
319
320                 case SV_SCROLL_DETECT_INVIS:
321                 {
322                         if (detect_monsters_invis(creature_ptr, DETECT_RAD_DEFAULT)) ident = TRUE;
323                         break;
324                 }
325
326                 case SV_SCROLL_SATISFY_HUNGER:
327                 {
328                         if (set_food(creature_ptr, PY_FOOD_MAX - 1)) ident = TRUE;
329                         break;
330                 }
331
332                 case SV_SCROLL_BLESSING:
333                 {
334                         if (set_blessed(creature_ptr, creature_ptr->blessed + randint1(12) + 6, FALSE)) ident = TRUE;
335                         break;
336                 }
337
338                 case SV_SCROLL_HOLY_CHANT:
339                 {
340                         if (set_blessed(creature_ptr, creature_ptr->blessed + randint1(24) + 12, FALSE)) ident = TRUE;
341                         break;
342                 }
343
344                 case SV_SCROLL_HOLY_PRAYER:
345                 {
346                         if (set_blessed(creature_ptr, creature_ptr->blessed + randint1(48) + 24, FALSE)) ident = TRUE;
347                         break;
348                 }
349
350                 case SV_SCROLL_MONSTER_CONFUSION:
351                 {
352                         if (!(creature_ptr->special_attack & ATTACK_CONFUSE))
353                         {
354                                 msg_print(_("手が輝き始めた。", "Your hands begin to glow."));
355                                 creature_ptr->special_attack |= ATTACK_CONFUSE;
356                                 creature_ptr->redraw |= (PR_STATUS);
357                                 ident = TRUE;
358                         }
359                         break;
360                 }
361
362                 case SV_SCROLL_PROTECTION_FROM_EVIL:
363                 {
364                         k = 3 * creature_ptr->lev;
365                         if (set_protevil(creature_ptr, creature_ptr->protevil + randint1(25) + k, FALSE)) ident = TRUE;
366                         break;
367                 }
368
369                 case SV_SCROLL_RUNE_OF_PROTECTION:
370                 {
371                         warding_glyph(creature_ptr);
372                         ident = TRUE;
373                         break;
374                 }
375
376                 case SV_SCROLL_TRAP_DOOR_DESTRUCTION:
377                 {
378                         if (destroy_doors_touch(creature_ptr)) ident = TRUE;
379                         break;
380                 }
381
382                 case SV_SCROLL_STAR_DESTRUCTION:
383                 {
384                         if (destroy_area(creature_ptr, creature_ptr->y, creature_ptr->x, 13 + randint0(5), FALSE))
385                                 ident = TRUE;
386                         else
387                                 msg_print(_("ダンジョンが揺れた...", "The dungeon trembles..."));
388
389                         break;
390                 }
391
392                 case SV_SCROLL_DISPEL_UNDEAD:
393                 {
394                         if (dispel_undead(creature_ptr, 80)) ident = TRUE;
395                         break;
396                 }
397
398                 case SV_SCROLL_SPELL:
399                 {
400                         if ((creature_ptr->pclass == CLASS_WARRIOR) ||
401                                 (creature_ptr->pclass == CLASS_IMITATOR) ||
402                                 (creature_ptr->pclass == CLASS_MINDCRAFTER) ||
403                                 (creature_ptr->pclass == CLASS_SORCERER) ||
404                                 (creature_ptr->pclass == CLASS_ARCHER) ||
405                                 (creature_ptr->pclass == CLASS_MAGIC_EATER) ||
406                                 (creature_ptr->pclass == CLASS_RED_MAGE) ||
407                                 (creature_ptr->pclass == CLASS_SAMURAI) ||
408                                 (creature_ptr->pclass == CLASS_BLUE_MAGE) ||
409                                 (creature_ptr->pclass == CLASS_CAVALRY) ||
410                                 (creature_ptr->pclass == CLASS_BERSERKER) ||
411                                 (creature_ptr->pclass == CLASS_SMITH) ||
412                                 (creature_ptr->pclass == CLASS_MIRROR_MASTER) ||
413                                 (creature_ptr->pclass == CLASS_NINJA) ||
414                                 (creature_ptr->pclass == CLASS_SNIPER)) break;
415                         creature_ptr->add_spells++;
416                         creature_ptr->update |= (PU_SPELLS);
417                         ident = TRUE;
418                         break;
419                 }
420
421                 case SV_SCROLL_GENOCIDE:
422                 {
423                         (void)symbol_genocide(creature_ptr, 300, TRUE);
424                         ident = TRUE;
425                         break;
426                 }
427
428                 case SV_SCROLL_MASS_GENOCIDE:
429                 {
430                         (void)mass_genocide(creature_ptr, 300, TRUE);
431                         ident = TRUE;
432                         break;
433                 }
434
435                 case SV_SCROLL_ACQUIREMENT:
436                 {
437                         acquirement(creature_ptr, creature_ptr->y, creature_ptr->x, 1, TRUE, FALSE, FALSE);
438                         ident = TRUE;
439                         break;
440                 }
441
442                 case SV_SCROLL_STAR_ACQUIREMENT:
443                 {
444                         acquirement(creature_ptr, creature_ptr->y, creature_ptr->x, randint1(2) + 1, TRUE, FALSE, FALSE);
445                         ident = TRUE;
446                         break;
447                 }
448
449                 /* New Hengband scrolls */
450                 case SV_SCROLL_FIRE:
451                 {
452                         fire_ball(creature_ptr, GF_FIRE, 0, 666, 4);
453                         /* Note: "Double" damage since it is centered on the player ... */
454                         if (!(is_oppose_fire(creature_ptr) || creature_ptr->resist_fire || creature_ptr->immune_fire))
455                                 take_hit(creature_ptr, DAMAGE_NOESCAPE, 50+randint1(50), _("炎の巻物", "a Scroll of Fire"), -1);
456
457                         ident = TRUE;
458                         break;
459                 }
460
461
462                 case SV_SCROLL_ICE:
463                 {
464                         fire_ball(creature_ptr, GF_ICE, 0, 777, 4);
465                         if (!(is_oppose_cold(creature_ptr) || creature_ptr->resist_cold || creature_ptr->immune_cold))
466                                 take_hit(creature_ptr, DAMAGE_NOESCAPE, 100+randint1(100), _("氷の巻物", "a Scroll of Ice"), -1);
467
468                         ident = TRUE;
469                         break;
470                 }
471
472                 case SV_SCROLL_CHAOS:
473                 {
474                         fire_ball(creature_ptr, GF_CHAOS, 0, 1000, 4);
475                         if (!creature_ptr->resist_chaos)
476                                 take_hit(creature_ptr, DAMAGE_NOESCAPE, 111+randint1(111), _("ログルスの巻物", "a Scroll of Logrus"), -1);
477
478                         ident = TRUE;
479                         break;
480                 }
481
482                 case SV_SCROLL_RUMOR:
483                 {
484                         msg_print(_("巻物にはメッセージが書かれている:", "There is message on the scroll. It says:"));
485                         msg_print(NULL);
486                         display_rumor(creature_ptr, TRUE);
487                         msg_print(NULL);
488                         msg_print(_("巻物は煙を立てて消え去った!", "The scroll disappears in a puff of smoke!"));
489
490                         ident = TRUE;
491                         break;
492                 }
493
494                 case SV_SCROLL_ARTIFACT:
495                 {
496                         ident = TRUE;
497                         if (!artifact_scroll(creature_ptr)) used_up = FALSE;
498                         break;
499                 }
500
501                 case SV_SCROLL_RESET_RECALL:
502                 {
503                         ident = TRUE;
504                         if (!reset_recall(creature_ptr)) used_up = FALSE;
505                         break;
506                 }
507
508                 case SV_SCROLL_AMUSEMENT:
509                 {
510                         ident = TRUE;
511                         amusement(creature_ptr, creature_ptr->y, creature_ptr->x, 1, FALSE);
512                         break;
513                 }
514
515                 case SV_SCROLL_STAR_AMUSEMENT:
516                 {
517                         ident = TRUE;
518                         amusement(creature_ptr, creature_ptr->y, creature_ptr->x,  randint1(2) + 1, FALSE);
519                         break;
520                 }
521         }
522         }
523         else if (o_ptr->name1 == ART_GHB)
524         {
525                 msg_print(_("私は苦労して『グレーター・ヘル=ビースト』を倒した。", "I had a very hard time to kill the Greater hell-beast, "));
526                 msg_print(_("しかし手に入ったのはこのきたないTシャツだけだった。", "but all I got was this lousy t-shirt!"));
527                 used_up = FALSE;
528         }
529         else if (o_ptr->name1 == ART_POWER)
530         {
531                 msg_print(_("「一つの指輪は全てを統べ、", "'One Ring to rule them all, "));
532                 msg_print(NULL);
533                 msg_print(_("一つの指輪は全てを見つけ、", "One Ring to find them, "));
534                 msg_print(NULL);
535                 msg_print(_("一つの指輪は全てを捕らえて", "One Ring to bring them all "));
536                 msg_print(NULL);
537                 msg_print(_("暗闇の中に繋ぎとめる。」", "and in the darkness bind them.'"));
538                 used_up = FALSE;
539         }
540         else if (o_ptr->tval==TV_PARCHMENT)
541         {
542                 concptr q;
543                 GAME_TEXT o_name[MAX_NLEN];
544                 char buf[1024];
545                 screen_save();
546
547                 q=format("book-%d_jp.txt",o_ptr->sval);
548
549                 /* Display object description */
550                 object_desc(creature_ptr, o_name, o_ptr, OD_NAME_ONLY);
551                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, q);
552
553                 /* Peruse the help file */
554                 (void)show_file(creature_ptr, TRUE, buf, o_name, 0, 0);
555                 screen_load();
556
557                 used_up=FALSE;
558         }
559
560         /*
561          * Store what may have to be updated for the inventory (including
562          * autodestroy if set by something else).  Then turn off those flags
563          * so that updates triggered by calling gain_exp() below do not
564          * rearrange the inventory before destroying the scroll in the pack.
565          */
566         BIT_FLAGS inventory_flags = (PU_COMBINE | PU_REORDER | (creature_ptr->update & PU_AUTODESTROY));
567         creature_ptr->update &= ~(PU_COMBINE | PU_REORDER | PU_AUTODESTROY);
568
569         if (!(object_is_aware(o_ptr)))
570         {
571                 chg_virtue(creature_ptr, V_PATIENCE, -1);
572                 chg_virtue(creature_ptr, V_CHANCE, 1);
573                 chg_virtue(creature_ptr, V_KNOWLEDGE, -1);
574         }
575
576         /* The item was tried */
577         object_tried(o_ptr);
578
579         /* An identification was made */
580         if (ident && !object_is_aware(o_ptr))
581         {
582                 object_aware(creature_ptr, o_ptr);
583                 gain_exp(creature_ptr, (lev + (creature_ptr->lev >> 1)) / creature_ptr->lev);
584         }
585
586         creature_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
587         creature_ptr->update |= inventory_flags;
588
589         /* Hack -- allow certain scrolls to be "preserved" */
590         if (!used_up)
591         {
592                 return;
593         }
594
595         sound(SOUND_SCROLL);
596         vary_item(creature_ptr, item, -1);
597 }
598
599
600 /*!
601  * @brief 読むコマンドのメインルーチン /
602  * Eat some food (from the pack or floor)
603  * @return なし
604  */
605 void do_cmd_read_scroll(player_type *creature_ptr)
606 {
607         object_type *o_ptr;
608         OBJECT_IDX item;
609         concptr q, s;
610
611         if (creature_ptr->wild_mode)
612         {
613                 return;
614         }
615
616         if (cmd_limit_arena(creature_ptr)) return;
617
618         if (creature_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN))
619         {
620                 set_action(creature_ptr, ACTION_NONE);
621         }
622
623         if (cmd_limit_blind(creature_ptr)) return;
624         if (cmd_limit_confused(creature_ptr)) return;
625
626         /* Restrict choices to scrolls */
627         item_tester_hook = item_tester_hook_readable;
628
629         q = _("どの巻物を読みますか? ", "Read which scroll? ");
630         s = _("読める巻物がない。", "You have no scrolls to read.");
631
632         o_ptr = choose_object(creature_ptr, &item, q, s, (USE_INVEN | USE_FLOOR), 0);
633         if (!o_ptr) return;
634
635         /* Read the scroll */
636         exe_read(creature_ptr, item, object_is_aware(o_ptr));
637 }