OSDN Git Service

[Refactor] #38997 leave_tower_check() にplayer_type * 引数を追加 / Added floor_type * argum...
[hengband/hengband.git] / src / quest.c
1 #include "angband.h"
2 #include "util.h"
3
4 #include "core.h"
5 #include "dungeon.h"
6 #include "floor.h"
7 #include "floor-save.h"
8 #include "floor-events.h"
9 #include "grid.h"
10 #include "quest.h"
11 #include "monsterrace-hook.h"
12 #include "monster.h"
13 #include "player-status.h"
14 #include "player-personality.h"
15 #include "artifact.h"
16 #include "feature.h"
17 #include "world.h"
18 #include "cmd-dump.h"
19 #include "english.h"
20 #include "view-mainwindow.h"
21
22 quest_type *quest; /*!< Quest info */
23 QUEST_IDX max_q_idx; /*!< Maximum number of quests */
24 char quest_text[10][80]; /*!< Quest text */
25 int quest_text_line; /*!< Current line of the quest text */
26 int leaving_quest = 0;
27
28 /*!
29  * @brief クエスト突入時のメッセージテーブル / Array of places to find an inscription
30  */
31 static concptr find_quest[] =
32 {
33         _("床にメッセージが刻まれている:", "You find the following inscription in the floor"),
34         _("壁にメッセージが刻まれている:", "You see a message inscribed in the wall"),
35         _("メッセージを見つけた:", "There is a sign saying"),
36         _("何かが階段の上に書いてある:", "Something is written on the staircase"),
37         _("巻物を見つけた。メッセージが書いてある:", "You find a scroll with the following message"),
38 };
39
40 /*!
41  * @brief ランダムクエストの討伐ユニークを決める / Determine the random quest uniques
42  * @param q_ptr クエスト構造体の参照ポインタ
43  * @return なし
44  */
45 void determine_random_questor(quest_type *q_ptr)
46 {
47         MONRACE_IDX r_idx;
48         monster_race *r_ptr;
49
50         get_mon_num_prep(mon_hook_quest, NULL);
51
52         while (TRUE)
53         {
54                 /*
55                  * Random monster 5 - 10 levels out of depth
56                  * (depending on level)
57                  */
58                 r_idx = get_mon_num(q_ptr->level + 5 + randint1(q_ptr->level / 10));
59                 r_ptr = &r_info[r_idx];
60
61                 if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
62                 if (r_ptr->flags1 & RF1_QUESTOR) continue;
63                 if (r_ptr->rarity > 100) continue;
64                 if (r_ptr->flags7 & RF7_FRIENDLY) continue;
65                 if (r_ptr->flags7 & RF7_AQUATIC) continue;
66                 if (r_ptr->flags8 & RF8_WILD_ONLY) continue;
67                 if (no_questor_or_bounty_uniques(r_idx)) continue;
68
69                 /*
70                  * Accept monsters that are 2 - 6 levels
71                  * out of depth depending on the quest level
72                  */
73                 if (r_ptr->level > (q_ptr->level + (q_ptr->level / 20))) break;
74         }
75
76         q_ptr->r_idx = r_idx;
77 }
78
79 /*!
80  * @brief クエストを達成状態にする /
81  * @param player_ptr プレーヤーへの参照ポインタ
82  * @param quest_num 達成状態にしたいクエストのID
83  * @return なし
84  */
85 void complete_quest(player_type *player_ptr, QUEST_IDX quest_num)
86 {
87         quest_type* const q_ptr = &quest[quest_num];
88
89         switch (q_ptr->type)
90         {
91         case QUEST_TYPE_RANDOM:
92                 if (record_rand_quest) exe_write_diary(player_ptr, NIKKI_RAND_QUEST_C, quest_num, NULL);
93                 break;
94         default:
95                 if (record_fix_quest) exe_write_diary(player_ptr, NIKKI_FIX_QUEST_C, quest_num, NULL);
96                 break;
97         }
98
99         q_ptr->status = QUEST_STATUS_COMPLETED;
100         q_ptr->complev = player_ptr->lev;
101         update_playtime();
102         q_ptr->comptime = current_world_ptr->play_time;
103
104         if (!(q_ptr->flags & QUEST_FLAG_SILENT))
105         {
106                 play_music(TERM_XTRA_MUSIC_BASIC, MUSIC_BASIC_QUEST_CLEAR);
107                 msg_print(_("クエストを達成した!", "You just completed your quest!"));
108                 msg_print(NULL);
109         }
110 }
111
112
113
114 /*!
115  * @brief 特定の敵を倒した際にクエスト達成処理 /
116  * Check for "Quest" completion when a quest monster is killed or charmed.
117  * @param player_ptr プレーヤーへの参照ポインタ
118  * @param m_ptr 撃破したモンスターの構造体参照ポインタ
119  * @return なし
120  */
121 void check_quest_completion(player_type *player_ptr, monster_type *m_ptr)
122 {
123         POSITION y, x;
124
125         bool create_stairs = FALSE;
126         bool reward = FALSE;
127
128         object_type forge;
129         object_type *o_ptr;
130
131         y = m_ptr->fy;
132         x = m_ptr->fx;
133
134         floor_type *floor_ptr = player_ptr->current_floor_ptr;
135         QUEST_IDX quest_num = floor_ptr->inside_quest;
136
137         /* Search for an active quest on this dungeon level */
138         if (!quest_num)
139         {
140                 QUEST_IDX i;
141
142                 for (i = max_q_idx - 1; i > 0; i--)
143                 {
144                         quest_type* const q_ptr = &quest[i];
145
146                         /* Quest is not active */
147                         if (q_ptr->status != QUEST_STATUS_TAKEN)
148                                 continue;
149
150                         /* Quest is not a dungeon quest */
151                         if (q_ptr->flags & QUEST_FLAG_PRESET)
152                                 continue;
153
154                         /* Quest is not on this level */
155                         if ((q_ptr->level != floor_ptr->dun_level) &&
156                                 (q_ptr->type != QUEST_TYPE_KILL_ANY_LEVEL))
157                                 continue;
158
159                         /* Not a "kill monster" quest */
160                         if ((q_ptr->type == QUEST_TYPE_FIND_ARTIFACT) ||
161                                 (q_ptr->type == QUEST_TYPE_FIND_EXIT))
162                                 continue;
163
164                         /* Interesting quest */
165                         if ((q_ptr->type == QUEST_TYPE_KILL_NUMBER) ||
166                                 (q_ptr->type == QUEST_TYPE_TOWER) ||
167                                 (q_ptr->type == QUEST_TYPE_KILL_ALL))
168                                 break;
169
170                         /* Interesting quest */
171                         if (((q_ptr->type == QUEST_TYPE_KILL_LEVEL) ||
172                                 (q_ptr->type == QUEST_TYPE_KILL_ANY_LEVEL) ||
173                                 (q_ptr->type == QUEST_TYPE_RANDOM)) &&
174                                 (q_ptr->r_idx == m_ptr->r_idx))
175                                 break;
176                 }
177
178                 quest_num = i;
179         }
180
181         /* Handle the current quest */
182         if (quest_num && (quest[quest_num].status == QUEST_STATUS_TAKEN))
183         {
184                 /* Current quest */
185                 quest_type* const q_ptr = &quest[quest_num];
186
187                 switch (q_ptr->type)
188                 {
189                 case QUEST_TYPE_KILL_NUMBER:
190                 {
191                         q_ptr->cur_num++;
192
193                         if (q_ptr->cur_num >= q_ptr->num_mon)
194                         {
195                                 complete_quest(player_ptr, quest_num);
196
197                                 q_ptr->cur_num = 0;
198                         }
199                         break;
200                 }
201                 case QUEST_TYPE_KILL_ALL:
202                 {
203                         if (!is_hostile(m_ptr)) break;
204
205                         if (count_all_hostile_monsters(floor_ptr) == 1)
206                         {
207                                 if (q_ptr->flags & QUEST_FLAG_SILENT)
208                                 {
209                                         q_ptr->status = QUEST_STATUS_FINISHED;
210                                 }
211                                 else
212                                 {
213                                         complete_quest(player_ptr, quest_num);
214                                 }
215                         }
216                         break;
217                 }
218                 case QUEST_TYPE_KILL_LEVEL:
219                 case QUEST_TYPE_RANDOM:
220                 {
221                         /* Only count valid monsters */
222                         if (q_ptr->r_idx != m_ptr->r_idx)
223                                 break;
224
225                         q_ptr->cur_num++;
226
227                         if (q_ptr->cur_num >= q_ptr->max_num)
228                         {
229                                 complete_quest(player_ptr, quest_num);
230
231                                 if (!(q_ptr->flags & QUEST_FLAG_PRESET))
232                                 {
233                                         create_stairs = TRUE;
234                                         floor_ptr->inside_quest = 0;
235                                 }
236
237                                 /* Finish the two main quests without rewarding */
238                                 if ((quest_num == QUEST_OBERON) || (quest_num == QUEST_SERPENT))
239                                 {
240                                         q_ptr->status = QUEST_STATUS_FINISHED;
241                                 }
242
243                                 if (q_ptr->type == QUEST_TYPE_RANDOM)
244                                 {
245                                         reward = TRUE;
246                                         q_ptr->status = QUEST_STATUS_FINISHED;
247                                 }
248                         }
249                         break;
250                 }
251                 case QUEST_TYPE_KILL_ANY_LEVEL:
252                 {
253                         q_ptr->cur_num++;
254                         if (q_ptr->cur_num >= q_ptr->max_num)
255                         {
256                                 complete_quest(player_ptr, quest_num);
257                                 q_ptr->cur_num = 0;
258                         }
259                         break;
260                 }
261                 case QUEST_TYPE_TOWER:
262                 {
263                         if (!is_hostile(m_ptr)) break;
264
265                         if (count_all_hostile_monsters(floor_ptr) == 1)
266                         {
267                                 q_ptr->status = QUEST_STATUS_STAGE_COMPLETED;
268
269                                 if ((quest[QUEST_TOWER1].status == QUEST_STATUS_STAGE_COMPLETED) &&
270                                         (quest[QUEST_TOWER2].status == QUEST_STATUS_STAGE_COMPLETED) &&
271                                         (quest[QUEST_TOWER3].status == QUEST_STATUS_STAGE_COMPLETED))
272                                 {
273
274                                         complete_quest(player_ptr, QUEST_TOWER1);
275                                 }
276                         }
277                         break;
278                 }
279                 }
280         }
281
282         /* Create a magical staircase */
283         if (create_stairs)
284         {
285                 POSITION ny, nx;
286
287                 /* Stagger around */
288                 while (cave_perma_bold(floor_ptr, y, x) || floor_ptr->grid_array[y][x].o_idx || (floor_ptr->grid_array[y][x].info & CAVE_OBJECT))
289                 {
290                         /* Pick a location */
291                         scatter(floor_ptr, &ny, &nx, y, x, 1, 0);
292
293                         /* Stagger */
294                         y = ny; x = nx;
295                 }
296
297                 /* Explain the staircase */
298                 msg_print(_("魔法の階段が現れた...", "A magical staircase appears..."));
299
300                 /* Create stairs down */
301                 cave_set_feat(floor_ptr, y, x, feat_down_stair);
302
303                 /* Remember to update everything */
304                 player_ptr->update |= (PU_FLOW);
305         }
306
307         /*
308          * Drop quest reward
309          */
310         if (reward)
311         {
312                 int i;
313
314                 for (i = 0; i < (floor_ptr->dun_level / 15) + 1; i++)
315                 {
316                         o_ptr = &forge;
317                         object_wipe(o_ptr);
318
319                         /* Make a great object */
320                         make_object(player_ptr, o_ptr, AM_GOOD | AM_GREAT);
321                         (void)drop_near(player_ptr, o_ptr, -1, y, x);
322                 }
323         }
324 }
325
326 /*!
327  * @brief 特定のアーティファクトを入手した際のクエスト達成処理 /
328  * Check for "Quest" completion when a quest monster is killed or charmed.
329  * @param player_ptr プレーヤーへの参照ポインタ
330  * @param o_ptr 入手したオブジェクトの構造体参照ポインタ
331  * @return なし
332  */
333 void check_find_art_quest_completion(player_type *player_ptr, object_type *o_ptr)
334 {
335         QUEST_IDX i;
336         /* Check if completed a quest */
337         for (i = 0; i < max_q_idx; i++)
338         {
339                 if ((quest[i].type == QUEST_TYPE_FIND_ARTIFACT) &&
340                         (quest[i].status == QUEST_STATUS_TAKEN) &&
341                         (quest[i].k_idx == o_ptr->name1))
342                 {
343                         complete_quest(player_ptr, i);
344                 }
345         }
346 }
347
348
349 /*!
350  * @brief クエストの導入メッセージを表示する / Discover quest
351  * @param q_idx 開始されたクエストのID
352  */
353 void quest_discovery(QUEST_IDX q_idx)
354 {
355         quest_type *q_ptr = &quest[q_idx];
356         monster_race *r_ptr = &r_info[q_ptr->r_idx];
357         MONSTER_NUMBER q_num = q_ptr->max_num;
358         GAME_TEXT name[MAX_NLEN];
359
360         if (!q_idx) return;
361
362         strcpy(name, (r_name + r_ptr->name));
363
364         msg_print(find_quest[rand_range(0, 4)]);
365         msg_print(NULL);
366
367         if (q_num == 1)
368         {
369                 if ((r_ptr->flags1 & RF1_UNIQUE) && (0 == r_ptr->max_num))
370                 {
371                         msg_print(_("この階は以前は誰かによって守られていたようだ…。", "It seems that this level was protected by someone before..."));
372                         /* The unique is already dead */
373                         quest[q_idx].status = QUEST_STATUS_FINISHED;
374                         q_ptr->complev = 0;
375                         update_playtime();
376                         q_ptr->comptime = current_world_ptr->play_time;
377                 }
378                 else
379                 {
380                         msg_format(_("注意せよ!この階は%sによって守られている!", "Beware, this level is protected by %s!"), name);
381                 }
382         }
383         else
384         {
385 #ifndef JP
386                 plural_aux(name);
387 #endif
388                 msg_format(_("注意しろ!この階は%d体の%sによって守られている!", "Be warned, this level is guarded by %d %s!"), q_num, name);
389
390         }
391 }
392
393
394 /*!
395  * @brief 新しく入ったダンジョンの階層に固定されている一般のクエストを探し出しIDを返す。
396  * / Hack -- Check if a level is a "quest" level
397  * @param player_ptr プレーヤーへの参照ポインタ
398  * @param level 検索対象になる階
399  * @return クエストIDを返す。該当がない場合0を返す。
400  */
401 QUEST_IDX quest_number(player_type *player_ptr, DEPTH level)
402 {
403         QUEST_IDX i;
404
405         floor_type *floor_ptr = player_ptr->current_floor_ptr;
406         if (floor_ptr->inside_quest)
407                 return (floor_ptr->inside_quest);
408
409         for (i = 0; i < max_q_idx; i++)
410         {
411                 if (quest[i].status != QUEST_STATUS_TAKEN) continue;
412
413                 if ((quest[i].type == QUEST_TYPE_KILL_LEVEL) &&
414                         !(quest[i].flags & QUEST_FLAG_PRESET) &&
415                         (quest[i].level == level) &&
416                         (quest[i].dungeon == player_ptr->dungeon_idx))
417                         return (i);
418         }
419
420         /* Check for random quest */
421         return random_quest_number(player_ptr, level);
422 }
423
424 /*!
425  * @brief 新しく入ったダンジョンの階層に固定されているランダムクエストを探し出しIDを返す。
426  * @param player_ptr プレーヤーへの参照ポインタ
427  * @param level 検索対象になる階
428  * @return クエストIDを返す。該当がない場合0を返す。
429  */
430 QUEST_IDX random_quest_number(player_type *player_ptr, DEPTH level)
431 {
432         QUEST_IDX i;
433
434         if (player_ptr->dungeon_idx != DUNGEON_ANGBAND) return 0;
435
436         for (i = MIN_RANDOM_QUEST; i < MAX_RANDOM_QUEST + 1; i++)
437         {
438                 if ((quest[i].type == QUEST_TYPE_RANDOM) &&
439                         (quest[i].status == QUEST_STATUS_TAKEN) &&
440                         (quest[i].level == level) &&
441                         (quest[i].dungeon == DUNGEON_ANGBAND))
442                 {
443                         return i;
444                 }
445         }
446
447         return 0;
448 }
449
450 /*!
451  * @brief クエスト階層から離脱する際の処理
452  * @param player_ptr プレーヤーへの参照ポインタ
453  * @return なし
454  */
455 void leave_quest_check(player_type *player_ptr)
456 {
457         leaving_quest = player_ptr->current_floor_ptr->inside_quest;
458         if (!leaving_quest) return;
459
460         quest_type* const q_ptr = &quest[leaving_quest];
461         bool is_one_time_quest = ((q_ptr->flags & QUEST_FLAG_ONCE) || (q_ptr->type == QUEST_TYPE_RANDOM)) &&
462                 (q_ptr->status == QUEST_STATUS_TAKEN);
463         if (is_one_time_quest) return;
464
465         q_ptr->status = QUEST_STATUS_FAILED;
466         q_ptr->complev = player_ptr->lev;
467         update_playtime();
468         q_ptr->comptime = current_world_ptr->play_time;
469
470         /* Additional settings */
471         switch (q_ptr->type)
472         {
473         case QUEST_TYPE_TOWER:
474                 quest[QUEST_TOWER1].status = QUEST_STATUS_FAILED;
475                 quest[QUEST_TOWER1].complev = player_ptr->lev;
476                 break;
477         case QUEST_TYPE_FIND_ARTIFACT:
478                 a_info[q_ptr->k_idx].gen_flags &= ~(TRG_QUESTITEM);
479                 break;
480         case QUEST_TYPE_RANDOM:
481                 r_info[q_ptr->r_idx].flags1 &= ~(RF1_QUESTOR);
482
483                 /* Floor of random quest will be blocked */
484                 prepare_change_floor_mode(player_ptr, CFM_NO_RETURN);
485                 break;
486         }
487
488         /* Record finishing a quest */
489         if (q_ptr->type == QUEST_TYPE_RANDOM)
490         {
491                 if (record_rand_quest) exe_write_diary(player_ptr, NIKKI_RAND_QUEST_F, leaving_quest, NULL);
492         }
493         else
494         {
495                 if (record_fix_quest) exe_write_diary(player_ptr, NIKKI_FIX_QUEST_F, leaving_quest, NULL);
496         }
497 }
498
499
500 /*!
501  * @brief 「塔」クエストの各階層から離脱する際の処理
502  * @return なし
503  */
504 void leave_tower_check(player_type *player_ptr)
505 {
506         leaving_quest = player_ptr->current_floor_ptr->inside_quest;
507         /* Check for Tower Quest */
508         if (leaving_quest &&
509                 (quest[leaving_quest].type == QUEST_TYPE_TOWER) &&
510                 (quest[QUEST_TOWER1].status != QUEST_STATUS_COMPLETED))
511         {
512                 if (quest[leaving_quest].type == QUEST_TYPE_TOWER)
513                 {
514                         quest[QUEST_TOWER1].status = QUEST_STATUS_FAILED;
515                         quest[QUEST_TOWER1].complev = player_ptr->lev;
516                         update_playtime();
517                         quest[QUEST_TOWER1].comptime = current_world_ptr->play_time;
518                 }
519         }
520 }
521
522
523 /*!
524  * @brief クエスト入り口にプレイヤーが乗った際の処理 / Do building commands
525  * @param player_ptr プレーヤーへの参照ポインタ
526  * @return なし
527  */
528 void do_cmd_quest(player_type *player_ptr)
529 {
530         if (player_ptr->wild_mode) return;
531
532         take_turn(player_ptr, 100);
533
534         if (!cave_have_flag_bold(player_ptr->current_floor_ptr, player_ptr->y, player_ptr->x, FF_QUEST_ENTER))
535         {
536                 msg_print(_("ここにはクエストの入口はない。", "You see no quest level here."));
537                 return;
538         }
539         else
540         {
541                 msg_print(_("ここにはクエストへの入口があります。", "There is an entry of a quest."));
542                 if (!get_check(_("クエストに入りますか?", "Do you enter? "))) return;
543                 if ((player_ptr->pseikaku == SEIKAKU_COMBAT) || (player_ptr->inventory_list[INVEN_BOW].name1 == ART_CRIMSON))
544                         msg_print(_("『とにかく入ってみようぜぇ。』", ""));
545                 else if (player_ptr->pseikaku == SEIKAKU_CHARGEMAN) msg_print("『全滅してやるぞ!』");
546
547                 /* Player enters a new quest */
548                 player_ptr->oldpy = 0;
549                 player_ptr->oldpx = 0;
550
551                 leave_quest_check(player_ptr);
552
553                 if (quest[player_ptr->current_floor_ptr->inside_quest].type != QUEST_TYPE_RANDOM) player_ptr->current_floor_ptr->dun_level = 1;
554                 player_ptr->current_floor_ptr->inside_quest = player_ptr->current_floor_ptr->grid_array[player_ptr->y][player_ptr->x].special;
555
556                 player_ptr->leaving = TRUE;
557         }
558 }
559