OSDN Git Service

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