OSDN Git Service

[Refactor] #37353 xtra2.c のクエスト関連処理を quest.c/h へ分離。 / Separate quest process in xtra2...
[hengbandforosx/hengbandosx.git] / src / xtra2.c
1 /*!
2  * @file xtra2.c
3  * @brief 雑多なその他の処理2 / effects of various "objects"
4  * @date 2014/02/06
5  * @author
6  * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke\n
7  * This software may be copied and distributed for educational, research, and\n
8  * not for profit purposes provided that this copyright and statement are\n
9  * included in all such copies.\n
10  * 2014 Deskull rearranged comment for Doxygen.
11  */
12
13
14 #include "angband.h"
15 #include "cmd-pet.h"
16 #include "object-curse.h"
17 #include "monster.h"
18 #include "monsterrace-hook.h"
19 #include "objectkind-hook.h"
20 #include "sort.h"
21 #include "projection.h"
22 #include "spells-summon.h"
23 #include "patron.h"
24 #include "mutation.h"
25 #include "floor-events.h"
26
27 #define REWARD_CHANCE 10
28
29
30 /*!
31  * @brief プレイヤーの経験値について整合性のためのチェックと調整を行う /
32  * Advance experience levels and print experience
33  * @return なし
34  */
35 void check_experience(void)
36 {
37         bool level_reward = FALSE;
38         bool level_mutation = FALSE;
39         bool level_inc_stat = FALSE;
40         bool android = (p_ptr->prace == RACE_ANDROID ? TRUE : FALSE);
41         PLAYER_LEVEL old_lev = p_ptr->lev;
42
43         /* Hack -- lower limit */
44         if (p_ptr->exp < 0) p_ptr->exp = 0;
45         if (p_ptr->max_exp < 0) p_ptr->max_exp = 0;
46         if (p_ptr->max_max_exp < 0) p_ptr->max_max_exp = 0;
47
48         /* Hack -- upper limit */
49         if (p_ptr->exp > PY_MAX_EXP) p_ptr->exp = PY_MAX_EXP;
50         if (p_ptr->max_exp > PY_MAX_EXP) p_ptr->max_exp = PY_MAX_EXP;
51         if (p_ptr->max_max_exp > PY_MAX_EXP) p_ptr->max_max_exp = PY_MAX_EXP;
52
53         /* Hack -- maintain "max" experience */
54         if (p_ptr->exp > p_ptr->max_exp) p_ptr->max_exp = p_ptr->exp;
55
56         /* Hack -- maintain "max max" experience */
57         if (p_ptr->max_exp > p_ptr->max_max_exp) p_ptr->max_max_exp = p_ptr->max_exp;
58
59         /* Redraw experience */
60         p_ptr->redraw |= (PR_EXP);
61         handle_stuff();
62
63
64         /* Lose levels while possible */
65         while ((p_ptr->lev > 1) &&
66                (p_ptr->exp < ((android ? player_exp_a : player_exp)[p_ptr->lev - 2] * p_ptr->expfact / 100L)))
67         {
68                 /* Lose a level */
69                 p_ptr->lev--;
70                 p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS);
71                 p_ptr->redraw |= (PR_LEV | PR_TITLE);
72                 p_ptr->window |= (PW_PLAYER);
73                 handle_stuff();
74         }
75
76
77         /* Gain levels while possible */
78         while ((p_ptr->lev < PY_MAX_LEVEL) &&
79                (p_ptr->exp >= ((android ? player_exp_a : player_exp)[p_ptr->lev-1] * p_ptr->expfact / 100L)))
80         {
81                 /* Gain a level */
82                 p_ptr->lev++;
83
84                 /* Save the highest level */
85                 if (p_ptr->lev > p_ptr->max_plv)
86                 {
87                         p_ptr->max_plv = p_ptr->lev;
88
89                         if ((p_ptr->pclass == CLASS_CHAOS_WARRIOR) ||
90                             (p_ptr->muta2 & MUT2_CHAOS_GIFT))
91                         {
92                                 level_reward = TRUE;
93                         }
94                         if (p_ptr->prace == RACE_BEASTMAN)
95                         {
96                                 if (one_in_(5)) level_mutation = TRUE;
97                         }
98                         level_inc_stat = TRUE;
99
100                         do_cmd_write_nikki(NIKKI_LEVELUP, p_ptr->lev, NULL);
101                 }
102
103                 sound(SOUND_LEVEL);
104
105                 msg_format(_("レベル %d にようこそ。", "Welcome to level %d."), p_ptr->lev);
106
107                 p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS);
108                 p_ptr->redraw |= (PR_LEV | PR_TITLE | PR_EXP);
109                 p_ptr->window |= (PW_PLAYER | PW_SPELL | PW_INVEN);
110
111                 /* HPとMPの上昇量を表示 */
112                 level_up = 1;
113                 handle_stuff();
114
115                 level_up = 0;
116
117                 if (level_inc_stat)
118                 {
119                         if(!(p_ptr->max_plv % 10))
120                         {
121                                 int choice;
122                                 screen_save();
123                                 while(1)
124                                 {
125                                         int n;
126                                         char tmp[32];
127
128                                         cnv_stat(p_ptr->stat_max[0], tmp);
129                                         prt(format(_("        a) 腕力 (現在値 %s)", "        a) Str (cur %s)"), tmp), 2, 14);
130                                         cnv_stat(p_ptr->stat_max[1], tmp);
131                                         prt(format(_("        b) 知能 (現在値 %s)", "        a) Int (cur %s)"), tmp), 3, 14);
132                                         cnv_stat(p_ptr->stat_max[2], tmp);
133                                         prt(format(_("        c) 賢さ (現在値 %s)", "        a) Wis (cur %s)"), tmp), 4, 14);
134                                         cnv_stat(p_ptr->stat_max[3], tmp);
135                                         prt(format(_("        d) 器用 (現在値 %s)", "        a) Dex (cur %s)"), tmp), 5, 14);
136                                         cnv_stat(p_ptr->stat_max[4], tmp);
137                                         prt(format(_("        e) 耐久 (現在値 %s)", "        a) Con (cur %s)"), tmp), 6, 14);
138                                         cnv_stat(p_ptr->stat_max[5], tmp);
139                                         prt(format(_("        f) 魅力 (現在値 %s)", "        a) Chr (cur %s)"), tmp), 7, 14);
140
141                                         prt("", 8, 14);
142                                         prt(_("        どの能力値を上げますか?", "        Which stat do you want to raise?"), 1, 14);
143
144                                         while(1)
145                                         {
146                                                 choice = inkey();
147                                                 if ((choice >= 'a') && (choice <= 'f')) break;
148                                         }
149                                         for(n = 0; n < A_MAX; n++)
150                                                 if (n != choice - 'a')
151                                                         prt("",n+2,14);
152                                         if (get_check(_("よろしいですか?", "Are you sure? "))) break;
153                                 }
154                                 do_inc_stat(choice - 'a');
155                                 screen_load();
156                         }
157                         else if(!(p_ptr->max_plv % 2))
158                                 do_inc_stat(randint0(6));
159                 }
160
161                 if (level_mutation)
162                 {
163                         msg_print(_("あなたは変わった気がする...", "You feel different..."));
164                         (void)gain_random_mutation(0);
165                         level_mutation = FALSE;
166                 }
167
168                 /*
169                  * 報酬でレベルが上ると再帰的に check_experience() が
170                  * 呼ばれるので順番を最後にする。
171                  */
172                 if (level_reward)
173                 {
174                         gain_level_reward(0);
175                         level_reward = FALSE;
176                 }
177
178                 p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS);
179                 p_ptr->redraw |= (PR_LEV | PR_TITLE);
180                 p_ptr->window |= (PW_PLAYER | PW_SPELL);
181                 handle_stuff();
182         }
183
184         /* Load an autopick preference file */
185         if (old_lev != p_ptr->lev) autopick_load_pref(FALSE);
186 }
187
188
189
190 /*!
191  * @brief モンスターを撃破した際の述語メッセージを返す /
192  * Return monster death string
193  * @param r_ptr 撃破されたモンスターの種族情報を持つ構造体の参照ポインタ
194  * @return 撃破されたモンスターの述語
195  */
196 concptr extract_note_dies(MONRACE_IDX r_idx)
197 {
198         monster_race *r_ptr = &r_info[r_idx];
199         /* Some monsters get "destroyed" */
200         if (!monster_living(r_idx))
201         {
202                 int i;
203
204                 for (i = 0; i < 4; i++)
205                 {
206                         if (r_ptr->blow[i].method == RBM_EXPLODE)
207                         {
208                                 return _("は爆発して粉々になった。", " explodes into tiny shreds.");
209                         }
210                 }
211                 return _("を倒した。", " is destroyed.");
212         }
213
214         /* Assume a default death */
215         return _("は死んだ。", " dies.");
216 }
217
218
219 /*!
220  * @brief モンスターに与えたダメージの修正処理 /
221  * Modify the physical damage done to the monster.
222  * @param m_ptr ダメージを受けるモンスターの構造体参照ポインタ
223  * @param dam ダメージ基本値
224  * @param is_psy_spear 攻撃手段が光の剣ならばTRUE
225  * @return 修正を行った結果のダメージ量
226  * @details
227  * <pre>
228  * (for example when it's invulnerable or shielded)
229  * ToDo: Accept a damage-type to calculate the modified damage from
230  * things like fire, frost, lightning, poison, ... attacks.
231  * "type" is not yet used and should be 0.
232  * </pre>
233  */
234 HIT_POINT mon_damage_mod(monster_type *m_ptr, HIT_POINT dam, bool is_psy_spear)
235 {
236         monster_race    *r_ptr = &r_info[m_ptr->r_idx];
237
238         if ((r_ptr->flagsr & RFR_RES_ALL) && dam > 0)
239         {
240                 dam /= 100;
241                 if ((dam == 0) && one_in_(3)) dam = 1;
242         }
243
244         if (MON_INVULNER(m_ptr))
245         {
246                 if (is_psy_spear)
247                 {
248                         if (!p_ptr->blind && is_seen(m_ptr))
249                         {
250                                 msg_print(_("バリアを切り裂いた!", "The barrier is penetrated!"));
251                         }
252                 }
253                 else if (!one_in_(PENETRATE_INVULNERABILITY))
254                 {
255                         return (0);
256                 }
257         }
258         return (dam);
259 }
260
261
262
263
264 /*!
265  * @brief 現在のコンソール表示の縦横を返す。 /
266  * Get term size and calculate screen size
267  * @param wid_p コンソールの表示幅文字数を返す
268  * @param hgt_p コンソールの表示行数を返す
269  * @return なし
270  */
271 void get_screen_size(TERM_LEN *wid_p, TERM_LEN *hgt_p)
272 {
273         Term_get_size(wid_p, hgt_p);
274         *hgt_p -= ROW_MAP + 2;
275         *wid_p -= COL_MAP + 2;
276         if (use_bigtile) *wid_p /= 2;
277 }
278
279
280 /*!
281  * @brief コンソール上におけるマップ表示の左上位置を返す /
282  * Calculates current boundaries Called below and from "do_cmd_locate()".
283  * @return なし
284  */
285 void panel_bounds_center(void)
286 {
287         TERM_LEN wid, hgt;
288
289         get_screen_size(&wid, &hgt);
290
291         panel_row_max = panel_row_min + hgt - 1;
292         panel_row_prt = panel_row_min - 1;
293         panel_col_max = panel_col_min + wid - 1;
294         panel_col_prt = panel_col_min - 13;
295 }
296
297
298 /*!
299  * @brief コンソールのリサイズに合わせてマップを再描画する /
300  * Map resizing whenever the main term changes size
301  * @return なし
302  */
303 void resize_map(void)
304 {
305         /* Only if the dungeon exists */
306         if (!character_dungeon) return;
307         
308         /* Mega-Hack -- no panel yet */
309         panel_row_max = 0;
310         panel_col_max = 0;
311
312         /* Reset the panels */
313         panel_row_min = cur_hgt;
314         panel_col_min = cur_wid;
315                                 
316         verify_panel();
317
318         p_ptr->update |= (PU_TORCH | PU_BONUS | PU_HP | PU_MANA | PU_SPELLS);
319         p_ptr->update |= (PU_UN_VIEW | PU_UN_LITE);
320         p_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE);
321         p_ptr->update |= (PU_MONSTERS);
322         p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
323
324         handle_stuff();
325         Term_redraw();
326
327         /*
328          * Waiting command;
329          * Place the cursor on the player
330          */
331         if (can_save) move_cursor_relative(p_ptr->y, p_ptr->x);
332
333         Term_fresh();
334 }
335
336 /*!
337  * @brief コンソールを再描画する /
338  * Redraw a term when it is resized
339  * @return なし
340  */
341 void redraw_window(void)
342 {
343         /* Only if the dungeon exists */
344         if (!character_dungeon) return;
345
346         p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_SPELL | PW_PLAYER);
347         p_ptr->window |= (PW_MESSAGE | PW_OVERHEAD | PW_DUNGEON | PW_MONSTER | PW_OBJECT);
348
349         handle_stuff();
350         Term_redraw();
351 }
352
353
354 /*!
355  * @brief フォーカスを当てるべきマップ描画の基準座標を指定する(サブルーチン)
356  * @param dy 変更先のフロアY座標
357  * @param dx 変更先のフロアX座標
358  * Handle a request to change the current panel
359  * Return TRUE if the panel was changed.
360  * Also used in do_cmd_locate
361  * @return 実際に再描画が必要だった場合TRUEを返す
362  */
363 bool change_panel(POSITION dy, POSITION dx)
364 {
365         POSITION y, x;
366         TERM_LEN wid, hgt;
367
368         get_screen_size(&wid, &hgt);
369
370         /* Apply the motion */
371         y = panel_row_min + dy * hgt / 2;
372         x = panel_col_min + dx * wid / 2;
373
374         /* Verify the row */
375         if (y > cur_hgt - hgt) y = cur_hgt - hgt;
376         if (y < 0) y = 0;
377
378         /* Verify the col */
379         if (x > cur_wid - wid) x = cur_wid - wid;
380         if (x < 0) x = 0;
381
382         /* Handle "changes" */
383         if ((y != panel_row_min) || (x != panel_col_min))
384         {
385                 /* Save the new panel info */
386                 panel_row_min = y;
387                 panel_col_min = x;
388
389                 /* Recalculate the boundaries */
390                 panel_bounds_center();
391
392                 p_ptr->update |= (PU_MONSTERS);
393                 p_ptr->redraw |= (PR_MAP);
394                 handle_stuff();
395
396                 /* Success */
397                 return (TRUE);
398         }
399
400         /* No change */
401         return (FALSE);
402 }
403
404 /*!
405  * @brief フォーカスを当てるべきマップ描画の基準座標を指定する
406  * @param y 変更先のフロアY座標
407  * @param x 変更先のフロアX座標
408  * @details
409  * Handle a request to change the current panel
410  * Return TRUE if the panel was changed.
411  * Also used in do_cmd_locate
412  * @return 実際に再描画が必要だった場合TRUEを返す
413  */
414 static bool change_panel_xy(POSITION y, POSITION x)
415 {
416         POSITION dy = 0, dx = 0;
417         TERM_LEN wid, hgt;
418
419         get_screen_size(&wid, &hgt);
420
421         if (y < panel_row_min) dy = -1;
422         if (y > panel_row_max) dy = 1;
423         if (x < panel_col_min) dx = -1;
424         if (x > panel_col_max) dx = 1;
425
426         if (!dy && !dx) return (FALSE);
427
428         return change_panel(dy, dx);
429 }
430
431
432 /*!
433  * @brief マップ描画のフォーカスを当てるべき座標を更新する
434  * @details
435  * Given an row (y) and col (x), this routine detects when a move
436  * off the screen has occurred and figures new borders. -RAK-
437  * "Update" forces a "full update" to take place.
438  * The map is reprinted if necessary, and "TRUE" is returned.
439  * @return 実際に再描画が必要だった場合TRUEを返す
440  */
441 void verify_panel(void)
442 {
443         POSITION y = p_ptr->y;
444         POSITION x = p_ptr->x;
445         TERM_LEN wid, hgt;
446
447         int prow_min;
448         int pcol_min;
449         int max_prow_min;
450         int max_pcol_min;
451
452         get_screen_size(&wid, &hgt);
453
454         max_prow_min = cur_hgt - hgt;
455         max_pcol_min = cur_wid - wid;
456
457         /* Bounds checking */
458         if (max_prow_min < 0) max_prow_min = 0;
459         if (max_pcol_min < 0) max_pcol_min = 0;
460
461                 /* Center on player */
462         if (center_player && (center_running || !running))
463         {
464                 /* Center vertically */
465                 prow_min = y - hgt / 2;
466                 if (prow_min < 0) prow_min = 0;
467                 else if (prow_min > max_prow_min) prow_min = max_prow_min;
468
469                 /* Center horizontally */
470                 pcol_min = x - wid / 2;
471                 if (pcol_min < 0) pcol_min = 0;
472                 else if (pcol_min > max_pcol_min) pcol_min = max_pcol_min;
473         }
474         else
475         {
476                 prow_min = panel_row_min;
477                 pcol_min = panel_col_min;
478
479                 /* Scroll screen when 2 grids from top/bottom edge */
480                 if (y > panel_row_max - 2)
481                 {
482                         while (y > prow_min + hgt-1 - 2)
483                         {
484                                 prow_min += (hgt / 2);
485                         }
486                 }
487
488                 if (y < panel_row_min + 2)
489                 {
490                         while (y < prow_min + 2)
491                         {
492                                 prow_min -= (hgt / 2);
493                         }
494                 }
495
496                 if (prow_min > max_prow_min) prow_min = max_prow_min;
497                 if (prow_min < 0) prow_min = 0;
498
499                 /* Scroll screen when 4 grids from left/right edge */
500                 if (x > panel_col_max - 4)
501                 {
502                         while (x > pcol_min + wid-1 - 4)
503                         {
504                                 pcol_min += (wid / 2);
505                         }
506                 }
507                 
508                 if (x < panel_col_min + 4)
509                 {
510                         while (x < pcol_min + 4)
511                         {
512                                 pcol_min -= (wid / 2);
513                         }
514                 }
515
516                 if (pcol_min > max_pcol_min) pcol_min = max_pcol_min;
517                 if (pcol_min < 0) pcol_min = 0;
518         }
519
520         /* Check for "no change" */
521         if ((prow_min == panel_row_min) && (pcol_min == panel_col_min)) return;
522
523         /* Save the new panel info */
524         panel_row_min = prow_min;
525         panel_col_min = pcol_min;
526
527         /* Hack -- optional disturb on "panel change" */
528         if (disturb_panel && !center_player) disturb(FALSE, FALSE);
529
530         /* Recalculate the boundaries */
531         panel_bounds_center();
532
533         p_ptr->update |= (PU_MONSTERS);
534         p_ptr->redraw |= (PR_MAP);
535         p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
536 }
537
538
539 /*
540  * Monster health description
541  */
542 concptr look_mon_desc(monster_type *m_ptr, BIT_FLAGS mode)
543 {
544         monster_race *ap_r_ptr = &r_info[m_ptr->ap_r_idx];
545         bool living;
546         int perc;
547         concptr desc;
548         concptr attitude;
549         concptr clone;
550
551         /* Determine if the monster is "living" */
552         living = monster_living(m_ptr->ap_r_idx);
553
554         /* Calculate a health "percentage" */
555         perc = m_ptr->maxhp > 0 ? 100L * m_ptr->hp / m_ptr->maxhp : 0;
556
557         /* Healthy monsters */
558         if (m_ptr->hp >= m_ptr->maxhp)
559         {
560                 desc = living ? _("無傷", "unhurt") : _("無ダメージ", "undamaged");
561         }
562
563         else if (perc >= 60)
564         {
565                 desc = living ? _("軽傷", "somewhat wounded") : _("小ダメージ", "somewhat damaged");
566         }
567
568         else if (perc >= 25)
569         {
570                 desc = living ? _("負傷", "wounded") : _("中ダメージ", "damaged");
571         }
572
573         else if (perc >= 10)
574         {
575                 desc = living ? _("重傷", "badly wounded") : _("大ダメージ", "badly damaged");
576         }
577
578         else 
579         {
580                 desc = living ? _("半死半生", "almost dead") : _("倒れかけ", "almost destroyed");
581         }
582
583         /* Need attitude information? */
584         if (!(mode & 0x01))
585         {
586                 /* Full information is not needed */
587                 attitude = "";
588         }
589         else if (is_pet(m_ptr))
590         {
591                 attitude = _(", ペット", ", pet");
592         }
593         else if (is_friendly(m_ptr))
594         {
595                 attitude = _(", 友好的", ", friendly");
596         }
597         else
598         {
599                 attitude = _("", "");
600         }
601
602         /* Clone monster? */
603         if (m_ptr->smart & SM_CLONED)
604         {
605                 clone = ", clone";
606         }
607         else
608         {
609                 clone = "";
610         }
611
612         /* Display monster's level --- idea borrowed from ToME */
613         if (ap_r_ptr->r_tkills && !(m_ptr->mflag2 & MFLAG2_KAGE))
614         {
615                 return format(_("レベル%d, %s%s%s", "Level %d, %s%s%s"), ap_r_ptr->level, desc, attitude, clone);
616         }
617         else 
618         {
619                 return format(_("レベル???, %s%s%s", "Level ???, %s%s%s"), desc, attitude, clone);
620         }
621
622 }
623
624
625
626 /*** Targeting Code ***/
627
628
629 /*
630  * Determine is a monster makes a reasonable target
631  *
632  * The concept of "targeting" was stolen from "Morgul" (?)
633  *
634  * The player can target any location, or any "target-able" monster.
635  *
636  * Currently, a monster is "target_able" if it is visible, and if
637  * the player can hit it with a projection, and the player is not
638  * hallucinating.  This allows use of "use closest target" macros.
639  *
640  * Future versions may restrict the ability to target "trappers"
641  * and "mimics", but the semantics is a little bit weird.
642  */
643 bool target_able(MONSTER_IDX m_idx)
644 {
645         monster_type *m_ptr = &m_list[m_idx];
646
647         /* Monster must be alive */
648         if (!m_ptr->r_idx) return (FALSE);
649
650         /* Hack -- no targeting hallucinations */
651         if (p_ptr->image) return (FALSE);
652
653         /* Monster must be visible */
654         if (!m_ptr->ml) return (FALSE);
655
656         if (p_ptr->riding && (p_ptr->riding == m_idx)) return (TRUE);
657
658         /* Monster must be projectable */
659         if (!projectable(p_ptr->y, p_ptr->x, m_ptr->fy, m_ptr->fx)) return (FALSE);
660
661         /* Hack -- Never target trappers */
662         /* if (CLEAR_ATTR && (CLEAR_CHAR)) return (FALSE); */
663
664         /* Assume okay */
665         return (TRUE);
666 }
667
668
669
670
671 /*
672  * Update (if necessary) and verify (if possible) the target.
673  *
674  * We return TRUE if the target is "okay" and FALSE otherwise.
675  */
676 bool target_okay(void)
677 {
678         /* Accept stationary targets */
679         if (target_who < 0) return (TRUE);
680
681         /* Check moving targets */
682         if (target_who > 0)
683         {
684                 /* Accept reasonable targets */
685                 if (target_able(target_who))
686                 {
687                         monster_type *m_ptr = &m_list[target_who];
688
689                         /* Acquire monster location */
690                         target_row = m_ptr->fy;
691                         target_col = m_ptr->fx;
692
693                         /* Good target */
694                         return (TRUE);
695                 }
696         }
697
698         /* Assume no target */
699         return (FALSE);
700 }
701
702
703 /*
704  * Sorting hook -- comp function -- by "distance to player"
705  *
706  * We use "u" and "v" to point to arrays of "x" and "y" positions,
707  * and sort the arrays by double-distance to the player.
708  */
709 static bool ang_sort_comp_distance(vptr u, vptr v, int a, int b)
710 {
711         POSITION *x = (POSITION*)(u);
712         POSITION *y = (POSITION*)(v);
713
714         POSITION da, db, kx, ky;
715
716         /* Absolute distance components */
717         kx = x[a]; kx -= p_ptr->x; kx = ABS(kx);
718         ky = y[a]; ky -= p_ptr->y; ky = ABS(ky);
719
720         /* Approximate Double Distance to the first point */
721         da = ((kx > ky) ? (kx + kx + ky) : (ky + ky + kx));
722
723         /* Absolute distance components */
724         kx = x[b]; kx -= p_ptr->x; kx = ABS(kx);
725         ky = y[b]; ky -= p_ptr->y; ky = ABS(ky);
726
727         /* Approximate Double Distance to the first point */
728         db = ((kx > ky) ? (kx + kx + ky) : (ky + ky + kx));
729
730         /* Compare the distances */
731         return (da <= db);
732 }
733
734
735 /*
736  * Sorting hook -- comp function -- by importance level of grids
737  *
738  * We use "u" and "v" to point to arrays of "x" and "y" positions,
739  * and sort the arrays by level of monster
740  */
741 static bool ang_sort_comp_importance(vptr u, vptr v, int a, int b)
742 {
743         POSITION *x = (POSITION*)(u);
744         POSITION *y = (POSITION*)(v);
745         cave_type *ca_ptr = &cave[y[a]][x[a]];
746         cave_type *cb_ptr = &cave[y[b]][x[b]];
747         monster_type *ma_ptr = &m_list[ca_ptr->m_idx];
748         monster_type *mb_ptr = &m_list[cb_ptr->m_idx];
749         monster_race *ap_ra_ptr, *ap_rb_ptr;
750
751         /* The player grid */
752         if (y[a] == p_ptr->y && x[a] == p_ptr->x) return TRUE;
753         if (y[b] == p_ptr->y && x[b] == p_ptr->x) return FALSE;
754
755         /* Extract monster race */
756         if (ca_ptr->m_idx && ma_ptr->ml) ap_ra_ptr = &r_info[ma_ptr->ap_r_idx];
757         else ap_ra_ptr = NULL;
758         if (cb_ptr->m_idx && mb_ptr->ml) ap_rb_ptr = &r_info[mb_ptr->ap_r_idx];
759         else ap_rb_ptr = NULL;
760
761         if (ap_ra_ptr && !ap_rb_ptr) return TRUE;
762         if (!ap_ra_ptr && ap_rb_ptr) return FALSE;
763
764         /* Compare two monsters */
765         if (ap_ra_ptr && ap_rb_ptr)
766         {
767                 /* Unique monsters first */
768                 if ((ap_ra_ptr->flags1 & RF1_UNIQUE) && !(ap_rb_ptr->flags1 & RF1_UNIQUE)) return TRUE;
769                 if (!(ap_ra_ptr->flags1 & RF1_UNIQUE) && (ap_rb_ptr->flags1 & RF1_UNIQUE)) return FALSE;
770
771                 /* Shadowers first (あやしい影) */
772                 if ((ma_ptr->mflag2 & MFLAG2_KAGE) && !(mb_ptr->mflag2 & MFLAG2_KAGE)) return TRUE;
773                 if (!(ma_ptr->mflag2 & MFLAG2_KAGE) && (mb_ptr->mflag2 & MFLAG2_KAGE)) return FALSE;
774
775                 /* Unknown monsters first */
776                 if (!ap_ra_ptr->r_tkills && ap_rb_ptr->r_tkills) return TRUE;
777                 if (ap_ra_ptr->r_tkills && !ap_rb_ptr->r_tkills) return FALSE;
778
779                 /* Higher level monsters first (if known) */
780                 if (ap_ra_ptr->r_tkills && ap_rb_ptr->r_tkills)
781                 {
782                         if (ap_ra_ptr->level > ap_rb_ptr->level) return TRUE;
783                         if (ap_ra_ptr->level < ap_rb_ptr->level) return FALSE;
784                 }
785
786                 /* Sort by index if all conditions are same */
787                 if (ma_ptr->ap_r_idx > mb_ptr->ap_r_idx) return TRUE;
788                 if (ma_ptr->ap_r_idx < mb_ptr->ap_r_idx) return FALSE;
789         }
790
791         /* An object get higher priority */
792         if (cave[y[a]][x[a]].o_idx && !cave[y[b]][x[b]].o_idx) return TRUE;
793         if (!cave[y[a]][x[a]].o_idx && cave[y[b]][x[b]].o_idx) return FALSE;
794
795         /* Priority from the terrain */
796         if (f_info[ca_ptr->feat].priority > f_info[cb_ptr->feat].priority) return TRUE;
797         if (f_info[ca_ptr->feat].priority < f_info[cb_ptr->feat].priority) return FALSE;
798
799         /* If all conditions are same, compare distance */
800         return ang_sort_comp_distance(u, v, a, b);
801 }
802
803
804 /*
805  * Sorting hook -- swap function -- by "distance to player"
806  *
807  * We use "u" and "v" to point to arrays of "x" and "y" positions,
808  * and sort the arrays by distance to the player.
809  */
810 static void ang_sort_swap_distance(vptr u, vptr v, int a, int b)
811 {
812         POSITION *x = (POSITION*)(u);
813         POSITION *y = (POSITION*)(v);
814
815         POSITION temp;
816
817         /* Swap "x" */
818         temp = x[a];
819         x[a] = x[b];
820         x[b] = temp;
821
822         /* Swap "y" */
823         temp = y[a];
824         y[a] = y[b];
825         y[b] = temp;
826 }
827
828
829
830 /*
831  * Hack -- help "select" a location (see below)
832  */
833 static POSITION_IDX target_pick(POSITION y1, POSITION x1, POSITION dy, POSITION dx)
834 {
835         POSITION_IDX i, v;
836         POSITION x2, y2, x3, y3, x4, y4;
837         POSITION_IDX b_i = -1, b_v = 9999;
838
839
840         /* Scan the locations */
841         for (i = 0; i < temp_n; i++)
842         {
843                 /* Point 2 */
844                 x2 = temp_x[i];
845                 y2 = temp_y[i];
846
847                 /* Directed distance */
848                 x3 = (x2 - x1);
849                 y3 = (y2 - y1);
850
851                 /* Verify quadrant */
852                 if (dx && (x3 * dx <= 0)) continue;
853                 if (dy && (y3 * dy <= 0)) continue;
854
855                 /* Absolute distance */
856                 x4 = ABS(x3);
857                 y4 = ABS(y3);
858
859                 /* Verify quadrant */
860                 if (dy && !dx && (x4 > y4)) continue;
861                 if (dx && !dy && (y4 > x4)) continue;
862
863                 /* Approximate Double Distance */
864                 v = ((x4 > y4) ? (x4 + x4 + y4) : (y4 + y4 + x4));
865
866                 /* Penalize location */
867
868                 /* Track best */
869                 if ((b_i >= 0) && (v >= b_v)) continue;
870
871                 /* Track best */
872                 b_i = i; b_v = v;
873         }
874         return (b_i);
875 }
876
877
878 /*
879  * Hack -- determine if a given location is "interesting"
880  */
881 static bool target_set_accept(POSITION y, POSITION x)
882 {
883         cave_type *c_ptr;
884         OBJECT_IDX this_o_idx, next_o_idx = 0;
885
886         /* Bounds */
887         if (!(in_bounds(y, x))) return (FALSE);
888
889         /* Player grid is always interesting */
890         if (player_bold(y, x)) return (TRUE);
891
892         /* Handle hallucination */
893         if (p_ptr->image) return (FALSE);
894
895         /* Examine the grid */
896         c_ptr = &cave[y][x];
897
898         /* Visible monsters */
899         if (c_ptr->m_idx)
900         {
901                 monster_type *m_ptr = &m_list[c_ptr->m_idx];
902
903                 /* Visible monsters */
904                 if (m_ptr->ml) return (TRUE);
905         }
906
907         /* Scan all objects in the grid */
908         for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
909         {
910                 object_type *o_ptr;
911                 o_ptr = &o_list[this_o_idx];
912
913                 /* Acquire next object */
914                 next_o_idx = o_ptr->next_o_idx;
915
916                 /* Memorized object */
917                 if (o_ptr->marked & OM_FOUND) return (TRUE);
918         }
919
920         /* Interesting memorized features */
921         if (c_ptr->info & (CAVE_MARK))
922         {
923                 /* Notice object features */
924                 if (c_ptr->info & CAVE_OBJECT) return (TRUE);
925
926                 /* Feature code (applying "mimic" field) */
927                 if (have_flag(f_info[get_feat_mimic(c_ptr)].flags, FF_NOTICE)) return TRUE;
928         }
929
930         return (FALSE);
931 }
932
933
934 /*
935  * Prepare the "temp" array for "target_set"
936  *
937  * Return the number of target_able monsters in the set.
938  */
939 static void target_set_prepare(BIT_FLAGS mode)
940 {
941         POSITION y, x;
942         POSITION min_hgt, max_hgt, min_wid, max_wid;
943
944         if (mode & TARGET_KILL)
945         {
946                 /* Inner range */
947                 min_hgt = MAX((p_ptr->y - MAX_RANGE), 0);
948                 max_hgt = MIN((p_ptr->y + MAX_RANGE), cur_hgt - 1);
949                 min_wid = MAX((p_ptr->x - MAX_RANGE), 0);
950                 max_wid = MIN((p_ptr->x + MAX_RANGE), cur_wid - 1);
951         }
952         else /* not targetting */
953         {
954                 /* Inner panel */
955                 min_hgt = panel_row_min;
956                 max_hgt = panel_row_max;
957                 min_wid = panel_col_min;
958                 max_wid = panel_col_max;
959         }
960
961         /* Reset "temp" array */
962         temp_n = 0;
963
964         /* Scan the current panel */
965         for (y = min_hgt; y <= max_hgt; y++)
966         {
967                 for (x = min_wid; x <= max_wid; x++)
968                 {
969                         cave_type *c_ptr;
970
971                         /* Require "interesting" contents */
972                         if (!target_set_accept(y, x)) continue;
973
974                         c_ptr = &cave[y][x];
975
976                         /* Require target_able monsters for "TARGET_KILL" */
977                         if ((mode & (TARGET_KILL)) && !target_able(c_ptr->m_idx)) continue;
978
979                         if ((mode & (TARGET_KILL)) && !target_pet && is_pet(&m_list[c_ptr->m_idx])) continue;
980
981                         /* Save the location */
982                         temp_x[temp_n] = x;
983                         temp_y[temp_n] = y;
984                         temp_n++;
985                 }
986         }
987
988         /* Set the sort hooks */
989         if (mode & (TARGET_KILL))
990         {
991                 /* Target the nearest monster for shooting */
992                 ang_sort_comp = ang_sort_comp_distance;
993                 ang_sort_swap = ang_sort_swap_distance;
994         }
995         else
996         {
997                 /* Look important grids first in Look command */
998                 ang_sort_comp = ang_sort_comp_importance;
999                 ang_sort_swap = ang_sort_swap_distance;
1000         }
1001
1002         /* Sort the positions */
1003         ang_sort(temp_x, temp_y, temp_n);
1004
1005         if (p_ptr->riding && target_pet && (temp_n > 1) && (mode & (TARGET_KILL)))
1006         {
1007                 POSITION tmp;
1008
1009                 tmp = temp_y[0];
1010                 temp_y[0] = temp_y[1];
1011                 temp_y[1] = tmp;
1012                 tmp = temp_x[0];
1013                 temp_x[0] = temp_x[1];
1014                 temp_x[1] = tmp;
1015         }
1016 }
1017
1018 void target_set_prepare_look(void){
1019         target_set_prepare(TARGET_LOOK);
1020 }
1021
1022
1023 /*
1024  * Evaluate number of kill needed to gain level
1025  */
1026 static void evaluate_monster_exp(char *buf, monster_type *m_ptr)
1027 {
1028         monster_race *ap_r_ptr = &r_info[m_ptr->ap_r_idx];
1029         u32b num;
1030         s32b exp_mon, exp_adv;
1031         u32b exp_mon_frac, exp_adv_frac;
1032
1033         if ((p_ptr->lev >= PY_MAX_LEVEL) || (p_ptr->prace == RACE_ANDROID))
1034         {
1035                 sprintf(buf,"**");
1036                 return;
1037         }
1038         else if (!ap_r_ptr->r_tkills || (m_ptr->mflag2 & MFLAG2_KAGE))
1039         {
1040                 if (!p_ptr->wizard)
1041                 {
1042                         sprintf(buf,"??");
1043                         return;
1044                 }
1045         }
1046
1047
1048         /* The monster's experience point (assuming average monster speed) */
1049         exp_mon = ap_r_ptr->mexp * ap_r_ptr->level;
1050         exp_mon_frac = 0;
1051         s64b_div(&exp_mon, &exp_mon_frac, 0, (p_ptr->max_plv + 2));
1052
1053
1054         /* Total experience value for next level */
1055         exp_adv = player_exp[p_ptr->lev -1] * p_ptr->expfact;
1056         exp_adv_frac = 0;
1057         s64b_div(&exp_adv, &exp_adv_frac, 0, 100);
1058
1059         /* Experience value need to get */
1060         s64b_sub(&exp_adv, &exp_adv_frac, p_ptr->exp, p_ptr->exp_frac);
1061
1062
1063         /* You need to kill at least one monster to get any experience */
1064         s64b_add(&exp_adv, &exp_adv_frac, exp_mon, exp_mon_frac);
1065         s64b_sub(&exp_adv, &exp_adv_frac, 0, 1);
1066
1067         /* Extract number of monsters needed */
1068         s64b_div(&exp_adv, &exp_adv_frac, exp_mon, exp_mon_frac);
1069
1070         /* If 999 or more monsters needed, only display "999". */
1071         num = MIN(999, exp_adv_frac);
1072
1073         /* Display the number */
1074         sprintf(buf,"%03ld", (long int)num);
1075 }
1076
1077
1078 bool show_gold_on_floor = FALSE;
1079
1080 /*
1081  * Examine a grid, return a keypress.
1082  *
1083  * The "mode" argument contains the "TARGET_LOOK" bit flag, which
1084  * indicates that the "space" key should scan through the contents
1085  * of the grid, instead of simply returning immediately.  This lets
1086  * the "look" command get complete information, without making the
1087  * "target" command annoying.
1088  *
1089  * The "info" argument contains the "commands" which should be shown
1090  * inside the "[xxx]" text.  This string must never be empty, or grids
1091  * containing monsters will be displayed with an extra comma.
1092  *
1093  * Note that if a monster is in the grid, we update both the monster
1094  * recall info and the health bar info to track that monster.
1095  *
1096  * Eventually, we may allow multiple objects per grid, or objects
1097  * and terrain features in the same grid. 
1098  *
1099  * This function must handle blindness/hallucination.
1100  */
1101 static char target_set_aux(POSITION y, POSITION x, BIT_FLAGS mode, concptr info)
1102 {
1103         cave_type *c_ptr = &cave[y][x];
1104         OBJECT_IDX this_o_idx, next_o_idx = 0;
1105         concptr s1 = "", s2 = "", s3 = "", x_info = "";
1106         bool boring = TRUE;
1107         FEAT_IDX feat;
1108         feature_type *f_ptr;
1109         char query = '\001';
1110         char out_val[MAX_NLEN+80];
1111         OBJECT_IDX floor_list[23];
1112         ITEM_NUMBER floor_num = 0;
1113
1114         /* Scan all objects in the grid */
1115         if (easy_floor)
1116         {
1117                 floor_num = scan_floor(floor_list, y, x, 0x02);
1118
1119                 if (floor_num)
1120                 {
1121                         x_info = _("x物 ", "x,");
1122                 }
1123         }
1124
1125         /* Hack -- under the player */
1126         if (player_bold(y, x))
1127         {
1128 #ifdef JP
1129                 s1 = "あなたは";
1130                 s2 = "の上";
1131                 s3 = "にいる";
1132 #else
1133                 s1 = "You are ";
1134                 s2 = "on ";
1135 #endif
1136         }
1137         else
1138         {
1139                 s1 = _("ターゲット:", "Target:");
1140         }
1141
1142         /* Hack -- hallucination */
1143         if (p_ptr->image)
1144         {
1145                 concptr name = _("何か奇妙な物", "something strange");
1146
1147                 /* Display a message */
1148 #ifdef JP
1149                 sprintf(out_val, "%s%s%s%s [%s]", s1, name, s2, s3, info);
1150 #else
1151                 sprintf(out_val, "%s%s%s%s [%s]", s1, s2, s3, name, info);
1152 #endif
1153
1154                 prt(out_val, 0, 0);
1155                 move_cursor_relative(y, x);
1156                 query = inkey();
1157
1158                 /* Stop on everything but "return" */
1159                 if ((query != '\r') && (query != '\n')) return query;
1160
1161                 /* Repeat forever */
1162                 return 0;
1163         }
1164
1165
1166         /* Actual monsters */
1167         if (c_ptr->m_idx && m_list[c_ptr->m_idx].ml)
1168         {
1169                 monster_type *m_ptr = &m_list[c_ptr->m_idx];
1170                 monster_race *ap_r_ptr = &r_info[m_ptr->ap_r_idx];
1171                 GAME_TEXT m_name[MAX_NLEN];
1172                 bool recall = FALSE;
1173
1174                 /* Not boring */
1175                 boring = FALSE;
1176
1177                 monster_desc(m_name, m_ptr, MD_INDEF_VISIBLE);
1178                 monster_race_track(m_ptr->ap_r_idx);
1179                 health_track(c_ptr->m_idx);
1180                 handle_stuff();
1181
1182                 /* Interact */
1183                 while (1)
1184                 {
1185                         char acount[10];
1186
1187                         /* Recall */
1188                         if (recall)
1189                         {
1190                                 screen_save();
1191
1192                                 /* Recall on screen */
1193                                 screen_roff(m_ptr->ap_r_idx, 0);
1194
1195                                 /* Hack -- Complete the prompt (again) */
1196                                 Term_addstr(-1, TERM_WHITE, format(_("  [r思 %s%s]", "  [r,%s%s]"), x_info, info));
1197
1198                                 /* Command */
1199                                 query = inkey();
1200
1201                                 screen_load();
1202
1203                                 /* Normal commands */
1204                                 if (query != 'r') break;
1205
1206                                 /* Toggle recall */
1207                                 recall = FALSE;
1208
1209                                 /* Cleare recall text and repeat */
1210                                 continue;
1211                         }
1212
1213                         /*** Normal ***/
1214
1215                         /* Describe, and prompt for recall */
1216                         evaluate_monster_exp(acount, m_ptr);
1217
1218 #ifdef JP
1219                         sprintf(out_val, "[%s]%s%s(%s)%s%s [r思 %s%s]", acount, s1, m_name, look_mon_desc(m_ptr, 0x01), s2, s3, x_info, info);
1220 #else
1221                         sprintf(out_val, "[%s]%s%s%s%s(%s) [r, %s%s]", acount, s1, s2, s3, m_name, look_mon_desc(m_ptr, 0x01), x_info, info);
1222 #endif
1223
1224                         prt(out_val, 0, 0);
1225
1226                         /* Place cursor */
1227                         move_cursor_relative(y, x);
1228
1229                         /* Command */
1230                         query = inkey();
1231
1232                         /* Normal commands */
1233                         if (query != 'r') break;
1234
1235                         /* Toggle recall */
1236                         recall = TRUE;
1237                 }
1238
1239                 /* Always stop at "normal" keys */
1240                 if ((query != '\r') && (query != '\n') && (query != ' ') && (query != 'x')) return query;
1241
1242                 /* Sometimes stop at "space" key */
1243                 if ((query == ' ') && !(mode & (TARGET_LOOK))) return query;
1244
1245                 /* Change the intro */
1246                 s1 = _("それは", "It is ");
1247
1248                 /* Hack -- take account of gender */
1249                 if (ap_r_ptr->flags1 & (RF1_FEMALE)) s1 = _("彼女は", "She is ");
1250                 else if (ap_r_ptr->flags1 & (RF1_MALE)) s1 = _("彼は", "He is ");
1251
1252                 /* Use a preposition */
1253 #ifdef JP
1254                 s2 = "を";
1255                 s3 = "持っている";
1256 #else
1257                 s2 = "carrying ";
1258 #endif
1259
1260
1261                 /* Scan all objects being carried */
1262                 for (this_o_idx = m_ptr->hold_o_idx; this_o_idx; this_o_idx = next_o_idx)
1263                 {
1264                         GAME_TEXT o_name[MAX_NLEN];
1265
1266                         object_type *o_ptr;
1267                         o_ptr = &o_list[this_o_idx];
1268
1269                         /* Acquire next object */
1270                         next_o_idx = o_ptr->next_o_idx;
1271
1272                         /* Obtain an object description */
1273                         object_desc(o_name, o_ptr, 0);
1274
1275 #ifdef JP
1276                         sprintf(out_val, "%s%s%s%s[%s]", s1, o_name, s2, s3, info);
1277 #else
1278                         sprintf(out_val, "%s%s%s%s [%s]", s1, s2, s3, o_name, info);
1279 #endif
1280
1281                         prt(out_val, 0, 0);
1282                         move_cursor_relative(y, x);
1283                         query = inkey();
1284
1285                         /* Always stop at "normal" keys */
1286                         if ((query != '\r') && (query != '\n') && (query != ' ') && (query != 'x')) return query;
1287
1288                         /* Sometimes stop at "space" key */
1289                         if ((query == ' ') && !(mode & (TARGET_LOOK))) return query;
1290
1291                         /* Change the intro */
1292                         s2 = _("をまた", "also carrying ");
1293                 }
1294
1295                 /* Use a preposition */
1296 #ifdef JP
1297                 s2 = "の上";
1298                 s3 = "にいる";
1299 #else
1300                 s2 = "on ";
1301 #endif
1302         }
1303
1304         if (floor_num)
1305         {
1306                 int min_width = 0;
1307
1308                 while (1)
1309                 {
1310                         if (floor_num == 1)
1311                         {
1312                                 GAME_TEXT o_name[MAX_NLEN];
1313
1314                                 object_type *o_ptr;
1315                                 o_ptr = &o_list[floor_list[0]];
1316
1317                                 object_desc(o_name, o_ptr, 0);
1318
1319 #ifdef JP
1320                                 sprintf(out_val, "%s%s%s%s[%s]", s1, o_name, s2, s3, info);
1321 #else
1322                                 sprintf(out_val, "%s%s%s%s [%s]", s1, s2, s3, o_name, info);
1323 #endif
1324
1325                                 prt(out_val, 0, 0);
1326                                 move_cursor_relative(y, x);
1327
1328                                 /* Command */
1329                                 query = inkey();
1330
1331                                 /* End this grid */
1332                                 return query;
1333                         }
1334
1335                         /* Provide one cushion before item listing  */
1336                         if (boring)
1337                         {
1338                                 /* Display rough information about items */
1339 #ifdef JP
1340                                 sprintf(out_val, "%s %d個のアイテム%s%s ['x'で一覧, %s]", s1, (int)floor_num, s2, s3, info);
1341 #else
1342                                 sprintf(out_val, "%s%s%sa pile of %d items [x,%s]", s1, s2, s3, (int)floor_num, info);
1343 #endif
1344
1345                                 prt(out_val, 0, 0);
1346                                 move_cursor_relative(y, x);
1347
1348                                 /* Command */
1349                                 query = inkey();
1350
1351                                 /* No request for listing */
1352                                 if (query != 'x' && query != ' ') return query;
1353                         }
1354
1355
1356                         /** Display list of items **/
1357
1358                         /* Continue scrolling list if requested */
1359                         while (1)
1360                         {
1361                                 int i;
1362                                 OBJECT_IDX o_idx;
1363                                 screen_save();
1364
1365                                 /* Display */
1366                                 show_gold_on_floor = TRUE;
1367                                 (void)show_floor(0, y, x, &min_width);
1368                                 show_gold_on_floor = FALSE;
1369
1370                                 /* Prompt */
1371 #ifdef JP
1372                                 sprintf(out_val, "%s %d個のアイテム%s%s [Enterで次へ, %s]", s1, (int)floor_num, s2, s3, info);
1373 #else
1374                                 sprintf(out_val, "%s%s%sa pile of %d items [Enter,%s]", s1, s2, s3, (int)floor_num, info);
1375 #endif
1376                                 prt(out_val, 0, 0);
1377
1378                                 query = inkey();
1379                                 screen_load();
1380
1381                                 /* Exit unless 'Enter' */
1382                                 if (query != '\n' && query != '\r')
1383                                 {
1384                                         return query;
1385                                 }
1386
1387                                 /* Get the object being moved. */
1388                                 o_idx = c_ptr->o_idx;
1389  
1390                                 /* Only rotate a pile of two or more objects. */
1391                                 if (!(o_idx && o_list[o_idx].next_o_idx)) continue;
1392
1393                                 /* Remove the first object from the list. */
1394                                 excise_object_idx(o_idx);
1395
1396                                 /* Find end of the list. */
1397                                 i = c_ptr->o_idx;
1398                                 while (o_list[i].next_o_idx)
1399                                         i = o_list[i].next_o_idx;
1400
1401                                 /* Add after the last object. */
1402                                 o_list[i].next_o_idx = o_idx;
1403
1404                                 /* Loop and re-display the list */
1405                         }
1406                 }
1407
1408                 /* NOTREACHED */
1409         }
1410
1411         /* Scan all objects in the grid */
1412         for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
1413         {
1414                 object_type *o_ptr;
1415                 o_ptr = &o_list[this_o_idx];
1416
1417                 /* Acquire next object */
1418                 next_o_idx = o_ptr->next_o_idx;
1419
1420                 if (o_ptr->marked & OM_FOUND)
1421                 {
1422                         GAME_TEXT o_name[MAX_NLEN];
1423
1424                         /* Not boring */
1425                         boring = FALSE;
1426
1427                         /* Obtain an object description */
1428                         object_desc(o_name, o_ptr, 0);
1429
1430 #ifdef JP
1431                         sprintf(out_val, "%s%s%s%s[%s]", s1, o_name, s2, s3, info);
1432 #else
1433                         sprintf(out_val, "%s%s%s%s [%s]", s1, s2, s3, o_name, info);
1434 #endif
1435
1436                         prt(out_val, 0, 0);
1437                         move_cursor_relative(y, x);
1438                         query = inkey();
1439
1440                         /* Always stop at "normal" keys */
1441                         if ((query != '\r') && (query != '\n') && (query != ' ') && (query != 'x')) return query;
1442
1443                         /* Sometimes stop at "space" key */
1444                         if ((query == ' ') && !(mode & TARGET_LOOK)) return query;
1445
1446                         /* Change the intro */
1447                         s1 = _("それは", "It is ");
1448
1449                         /* Plurals */
1450                         if (o_ptr->number != 1) s1 = _("それらは", "They are ");
1451
1452                         /* Preposition */
1453 #ifdef JP
1454                         s2 = "の上";
1455                         s3 = "に見える";
1456 #else
1457                         s2 = "on ";
1458 #endif
1459
1460                 }
1461         }
1462
1463
1464         /* Feature code (applying "mimic" field) */
1465         feat = get_feat_mimic(c_ptr);
1466
1467         /* Require knowledge about grid, or ability to see grid */
1468         if (!(c_ptr->info & CAVE_MARK) && !player_can_see_bold(y, x))
1469         {
1470                 /* Forget feature */
1471                 feat = feat_none;
1472         }
1473
1474         f_ptr = &f_info[feat];
1475
1476         /* Terrain feature if needed */
1477         if (boring || have_flag(f_ptr->flags, FF_REMEMBER))
1478         {
1479                 concptr name;
1480
1481                 /* Hack -- special handling for quest entrances */
1482                 if (have_flag(f_ptr->flags, FF_QUEST_ENTER))
1483                 {
1484                         /* Set the quest number temporary */
1485                         IDX old_quest = p_ptr->inside_quest;
1486                         int j;
1487
1488                         /* Clear the text */
1489                         for (j = 0; j < 10; j++) quest_text[j][0] = '\0';
1490                         quest_text_line = 0;
1491
1492                         p_ptr->inside_quest = c_ptr->special;
1493
1494                         /* Get the quest text */
1495                         init_flags = INIT_NAME_ONLY;
1496
1497                         process_dungeon_file("q_info.txt", 0, 0, 0, 0);
1498
1499                         name = format(_("クエスト「%s」(%d階相当)", "the entrance to the quest '%s'(level %d)"), 
1500                                                 quest[c_ptr->special].name, quest[c_ptr->special].level);
1501
1502                         /* Reset the old quest number */
1503                         p_ptr->inside_quest = old_quest;
1504                 }
1505
1506                 /* Hack -- special handling for building doors */
1507                 else if (have_flag(f_ptr->flags, FF_BLDG) && !p_ptr->inside_arena)
1508                 {
1509                         name = building[f_ptr->subtype].name;
1510                 }
1511                 else if (have_flag(f_ptr->flags, FF_ENTRANCE))
1512                 {
1513                         name = format(_("%s(%d階相当)", "%s(level %d)"), d_text + d_info[c_ptr->special].text, d_info[c_ptr->special].mindepth);
1514                 }
1515                 else if (have_flag(f_ptr->flags, FF_TOWN))
1516                 {
1517                         name = town[c_ptr->special].name;
1518                 }
1519                 else if (p_ptr->wild_mode && (feat == feat_floor))
1520                 {
1521                         name = _("道", "road");
1522                 }
1523                 else
1524                 {
1525                         name = f_name + f_ptr->name;
1526                 }
1527
1528
1529                 /* Pick a prefix */
1530                 if (*s2 &&
1531                     ((!have_flag(f_ptr->flags, FF_MOVE) && !have_flag(f_ptr->flags, FF_CAN_FLY)) ||
1532                      (!have_flag(f_ptr->flags, FF_LOS) && !have_flag(f_ptr->flags, FF_TREE)) ||
1533                      have_flag(f_ptr->flags, FF_TOWN)))
1534                 {
1535                         s2 = _("の中", "in ");
1536                 }
1537
1538                 /* Hack -- special introduction for store & building doors -KMW- */
1539                 if (have_flag(f_ptr->flags, FF_STORE) ||
1540                     have_flag(f_ptr->flags, FF_QUEST_ENTER) ||
1541                     (have_flag(f_ptr->flags, FF_BLDG) && !p_ptr->inside_arena) ||
1542                     have_flag(f_ptr->flags, FF_ENTRANCE))
1543                 {
1544                         s2 = _("の入口", "");
1545                 }
1546 #ifndef JP
1547                 else if (have_flag(f_ptr->flags, FF_FLOOR) ||
1548                          have_flag(f_ptr->flags, FF_TOWN) ||
1549                          have_flag(f_ptr->flags, FF_SHALLOW) ||
1550                          have_flag(f_ptr->flags, FF_DEEP))
1551                 {
1552                         s3 ="";
1553                 }
1554                 else
1555                 {
1556                         /* Pick proper indefinite article */
1557                         s3 = (is_a_vowel(name[0])) ? "an " : "a ";
1558                 }
1559 #endif
1560
1561                 /* Display a message */
1562                 if (p_ptr->wizard)
1563                 {
1564                         char f_idx_str[32];
1565                         if (c_ptr->mimic) sprintf(f_idx_str, "%d/%d", c_ptr->feat, c_ptr->mimic);
1566                         else sprintf(f_idx_str, "%d", c_ptr->feat);
1567 #ifdef JP
1568                         sprintf(out_val, "%s%s%s%s[%s] %x %s %d %d %d (%d,%d) %d", s1, name, s2, s3, info, (unsigned int)c_ptr->info, f_idx_str, c_ptr->dist, c_ptr->cost, c_ptr->when, (int)y, (int)x, travel.cost[y][x]);
1569 #else
1570                         sprintf(out_val, "%s%s%s%s [%s] %x %s %d %d %d (%d,%d)", s1, s2, s3, name, info, c_ptr->info, f_idx_str, c_ptr->dist, c_ptr->cost, c_ptr->when, (int)y, (int)x);
1571 #endif
1572                 }
1573                 else
1574 #ifdef JP
1575                         sprintf(out_val, "%s%s%s%s[%s]", s1, name, s2, s3, info);
1576 #else
1577                         sprintf(out_val, "%s%s%s%s [%s]", s1, s2, s3, name, info);
1578 #endif
1579
1580                 prt(out_val, 0, 0);
1581                 move_cursor_relative(y, x);
1582                 query = inkey();
1583
1584                 /* Always stop at "normal" keys */
1585                 if ((query != '\r') && (query != '\n') && (query != ' ')) return query;
1586         }
1587
1588         /* Stop on everything but "return" */
1589         if ((query != '\r') && (query != '\n')) return query;
1590
1591         /* Repeat forever */
1592         return 0;
1593 }
1594
1595
1596 /*
1597  * Handle "target" and "look".
1598  *
1599  * Note that this code can be called from "get_aim_dir()".
1600  *
1601  * All locations must be on the current panel.  Consider the use of
1602  * "panel_bounds()" to allow "off-panel" targets, perhaps by using
1603  * some form of "scrolling" the map around the cursor.  
1604  * That is, consider the possibility of "auto-scrolling" the screen
1605  * while the cursor moves around.  This may require changes in the
1606  * "update_monster()" code to allow "visibility" even if off panel, and
1607  * may require dynamic recalculation of the "temp" grid set.
1608  *
1609  * Hack -- targeting/observing an "outer border grid" may induce
1610  * problems, so this is not currently allowed.
1611  *
1612  * The player can use the direction keys to move among "interesting"
1613  * grids in a heuristic manner, or the "space", "+", and "-" keys to
1614  * move through the "interesting" grids in a sequential manner, or
1615  * can enter "location" mode, and use the direction keys to move one
1616  * grid at a time in any direction.  The "t" (set target) command will
1617  * only target a monster (as opposed to a location) if the monster is
1618  * target_able and the "interesting" mode is being used.
1619  *
1620  * The current grid is described using the "look" method above, and
1621  * a new command may be entered at any time, but note that if the
1622  * "TARGET_LOOK" bit flag is set (or if we are in "location" mode,
1623  * where "space" has no obvious meaning) then "space" will scan
1624  * through the description of the current grid until done, instead
1625  * of immediately jumping to the next "interesting" grid.  This
1626  * allows the "target" command to retain its old semantics.
1627  *
1628  * The "*", "+", and "-" keys may always be used to jump immediately
1629  * to the next (or previous) interesting grid, in the proper mode.
1630  *
1631  * The "return" key may always be used to scan through a complete
1632  * grid description (forever).
1633  *
1634  * This command will cancel any old target, even if used from
1635  * inside the "look" command.
1636  */
1637 bool target_set(BIT_FLAGS mode)
1638 {
1639         int i, d, m, t, bd;
1640         POSITION y = p_ptr->y;
1641         POSITION x = p_ptr->x;
1642
1643         bool done = FALSE;
1644         bool flag = TRUE;
1645         char query;
1646         char info[80];
1647         char same_key;
1648         cave_type *c_ptr;
1649         TERM_LEN wid, hgt;
1650         
1651         get_screen_size(&wid, &hgt);
1652
1653         /* Cancel target */
1654         target_who = 0;
1655
1656         if (rogue_like_commands)
1657         {
1658                 same_key = 'x';
1659         }
1660         else
1661         {
1662                 same_key = 'l';
1663         }
1664
1665         /* Prepare the "temp" array */
1666         target_set_prepare(mode);
1667
1668         /* Start near the player */
1669         m = 0;
1670
1671         /* Interact */
1672         while (!done)
1673         {
1674                 /* Interesting grids */
1675                 if (flag && temp_n)
1676                 {
1677                         y = temp_y[m];
1678                         x = temp_x[m];
1679
1680                         /* Set forcus */
1681                         change_panel_xy(y, x);
1682
1683                         if (!(mode & TARGET_LOOK)) prt_path(y, x);
1684
1685                         /* Access */
1686                         c_ptr = &cave[y][x];
1687
1688                         /* Allow target */
1689                         if (target_able(c_ptr->m_idx))
1690                         {
1691                                 strcpy(info, _("q止 t決 p自 o現 +次 -前", "q,t,p,o,+,-,<dir>"));
1692                         }
1693
1694                         /* Dis-allow target */
1695                         else
1696                         {
1697                                 strcpy(info, _("q止 p自 o現 +次 -前", "q,p,o,+,-,<dir>"));
1698                         }
1699
1700                         if (cheat_sight)
1701                         {
1702                                 char cheatinfo[30];
1703                                 sprintf(cheatinfo, " LOS:%d, PROJECTABLE:%d",
1704                                         los(p_ptr->y, p_ptr->x, y, x), projectable(p_ptr->y, p_ptr->x, y, x));
1705                                 strcat(info, cheatinfo);
1706                         }
1707                         
1708                         /* Describe and Prompt */
1709                         while (TRUE){
1710                                 query = target_set_aux(y, x, mode, info);
1711                                 if(query)break;
1712                         }
1713
1714                         /* Assume no "direction" */
1715                         d = 0;
1716
1717                         if (use_menu)
1718                         {
1719                                 if (query == '\r') query = 't';
1720                         }  
1721
1722                         /* Analyze */
1723                         switch (query)
1724                         {
1725                                 case ESCAPE:
1726                                 case 'q':
1727                                 {
1728                                         done = TRUE;
1729                                         break;
1730                                 }
1731
1732                                 case 't':
1733                                 case '.':
1734                                 case '5':
1735                                 case '0':
1736                                 {
1737                                         if (target_able(c_ptr->m_idx))
1738                                         {
1739                                                 health_track(c_ptr->m_idx);
1740                                                 target_who = c_ptr->m_idx;
1741                                                 target_row = y;
1742                                                 target_col = x;
1743                                                 done = TRUE;
1744                                         }
1745                                         else
1746                                         {
1747                                                 bell();
1748                                         }
1749                                         break;
1750                                 }
1751
1752                                 case ' ':
1753                                 case '*':
1754                                 case '+':
1755                                 {
1756                                         if (++m == temp_n)
1757                                         {
1758                                                 m = 0;
1759                                                 if (!expand_list) done = TRUE;
1760                                         }
1761                                         break;
1762                                 }
1763
1764                                 case '-':
1765                                 {
1766                                         if (m-- == 0)
1767                                         {
1768                                                 m = temp_n - 1;
1769                                                 if (!expand_list) done = TRUE;
1770                                         }
1771                                         break;
1772                                 }
1773
1774                                 case 'p':
1775                                 {
1776                                         /* Recenter the map around the player */
1777                                         verify_panel();
1778                                         p_ptr->update |= (PU_MONSTERS);
1779                                         p_ptr->redraw |= (PR_MAP);
1780                                         p_ptr->window |= (PW_OVERHEAD);
1781                                         handle_stuff();
1782
1783                                         /* Recalculate interesting grids */
1784                                         target_set_prepare(mode);
1785
1786                                         y = p_ptr->y;
1787                                         x = p_ptr->x;
1788                                 }
1789
1790                                 case 'o':
1791                                 {
1792                                         flag = FALSE;
1793                                         break;
1794                                 }
1795
1796                                 case 'm':
1797                                 {
1798                                         break;
1799                                 }
1800
1801                                 default:
1802                                 {
1803                                         if(query == same_key)
1804                                         {
1805                                                 if (++m == temp_n)
1806                                                 {
1807                                                         m = 0;
1808                                                         if (!expand_list) done = TRUE;
1809                                                 }
1810                                         }
1811                                         else
1812                                         {
1813                                                 /* Extract the action (if any) */
1814                                                 d = get_keymap_dir(query);
1815
1816                                                 if (!d) bell();
1817                                                 break;
1818                                         }
1819                                 }
1820                         }
1821                         /* Hack -- move around */
1822                         if (d)
1823                         {
1824                                 /* Modified to scroll to monster */
1825                                 POSITION y2 = panel_row_min;
1826                                 POSITION x2 = panel_col_min;
1827
1828                                 /* Find a new monster */
1829                                 i = target_pick(temp_y[m], temp_x[m], ddy[d], ddx[d]);
1830
1831                                 /* Request to target past last interesting grid */
1832                                 while (flag && (i < 0))
1833                                 {
1834                                         /* Note the change */
1835                                         if (change_panel(ddy[d], ddx[d]))
1836                                         {
1837                                                 int v = temp_y[m];
1838                                                 int u = temp_x[m];
1839
1840                                                 /* Recalculate interesting grids */
1841                                                 target_set_prepare(mode);
1842
1843                                                 /* Look at interesting grids */
1844                                                 flag = TRUE;
1845
1846                                                 /* Find a new monster */
1847                                                 i = target_pick(v, u, ddy[d], ddx[d]);
1848
1849                                                 /* Use that grid */
1850                                                 if (i >= 0) m = i;
1851                                         }
1852
1853                                         /* Nothing interesting */
1854                                         else
1855                                         {
1856                                                 POSITION dx = ddx[d];
1857                                                 POSITION dy = ddy[d];
1858
1859                                                 /* Restore previous position */
1860                                                 panel_row_min = y2;
1861                                                 panel_col_min = x2;
1862                                                 panel_bounds_center();
1863
1864                                                 p_ptr->update |= (PU_MONSTERS);
1865                                                 p_ptr->redraw |= (PR_MAP);
1866                                                 p_ptr->window |= (PW_OVERHEAD);
1867                                                 handle_stuff();
1868
1869                                                 /* Recalculate interesting grids */
1870                                                 target_set_prepare(mode);
1871
1872                                                 /* Look at boring grids */
1873                                                 flag = FALSE;
1874
1875                                                 /* Move */
1876                                                 x += dx;
1877                                                 y += dy;
1878
1879                                                 /* Do not move horizontally if unnecessary */
1880                                                 if (((x < panel_col_min + wid / 2) && (dx > 0)) ||
1881                                                          ((x > panel_col_min + wid / 2) && (dx < 0)))
1882                                                 {
1883                                                         dx = 0;
1884                                                 }
1885
1886                                                 /* Do not move vertically if unnecessary */
1887                                                 if (((y < panel_row_min + hgt / 2) && (dy > 0)) ||
1888                                                          ((y > panel_row_min + hgt / 2) && (dy < 0)))
1889                                                 {
1890                                                         dy = 0;
1891                                                 }
1892
1893                                                 /* Apply the motion */
1894                                                 if ((y >= panel_row_min+hgt) || (y < panel_row_min) ||
1895                                                     (x >= panel_col_min+wid) || (x < panel_col_min))
1896                                                 {
1897                                                         if (change_panel(dy, dx)) target_set_prepare(mode);
1898                                                 }
1899
1900                                                 /* Slide into legality */
1901                                                 if (x >= cur_wid-1) x = cur_wid - 2;
1902                                                 else if (x <= 0) x = 1;
1903
1904                                                 /* Slide into legality */
1905                                                 if (y >= cur_hgt-1) y = cur_hgt- 2;
1906                                                 else if (y <= 0) y = 1;
1907                                         }
1908                                 }
1909
1910                                 /* Use that grid */
1911                                 m = i;
1912                         }
1913                 }
1914
1915                 /* Arbitrary grids */
1916                 else
1917                 {
1918                         bool move_fast = FALSE;
1919
1920                         if (!(mode & TARGET_LOOK)) prt_path(y, x);
1921
1922                         /* Access */
1923                         c_ptr = &cave[y][x];
1924
1925                         /* Default prompt */
1926                         strcpy(info, _("q止 t決 p自 m近 +次 -前", "q,t,p,m,+,-,<dir>"));
1927
1928                         if (cheat_sight)
1929                         {
1930                                 char cheatinfo[30];
1931                                 sprintf(cheatinfo, " LOS:%d, PROJECTABLE:%d",
1932                                         los(p_ptr->y, p_ptr->x, y, x),
1933                                         projectable(p_ptr->y, p_ptr->x, y, x));
1934                                 strcat(info, cheatinfo);
1935                         }
1936
1937                         /* Describe and Prompt (enable "TARGET_LOOK") */
1938                         while ((query = target_set_aux(y, x, mode | TARGET_LOOK, info)) == 0);
1939
1940                         /* Assume no direction */
1941                         d = 0;
1942
1943                         if (use_menu)
1944                         {
1945                                 if (query == '\r') query = 't';
1946                         }  
1947
1948                         /* Analyze the keypress */
1949                         switch (query)
1950                         {
1951                                 case ESCAPE:
1952                                 case 'q':
1953                                 {
1954                                         done = TRUE;
1955                                         break;
1956                                 }
1957
1958                                 case 't':
1959                                 case '.':
1960                                 case '5':
1961                                 case '0':
1962                                 {
1963                                         target_who = -1;
1964                                         target_row = y;
1965                                         target_col = x;
1966                                         done = TRUE;
1967                                         break;
1968                                 }
1969
1970                                 case 'p':
1971                                 {
1972                                         /* Recenter the map around the player */
1973                                         verify_panel();
1974                                         p_ptr->update |= (PU_MONSTERS);
1975                                         p_ptr->redraw |= (PR_MAP);
1976                                         p_ptr->window |= (PW_OVERHEAD);
1977                                         handle_stuff();
1978
1979                                         /* Recalculate interesting grids */
1980                                         target_set_prepare(mode);
1981
1982                                         y = p_ptr->y;
1983                                         x = p_ptr->x;
1984                                 }
1985
1986                                 case 'o':
1987                                 {
1988                                         break;
1989                                 }
1990
1991                                 case ' ':
1992                                 case '*':
1993                                 case '+':
1994                                 case '-':
1995                                 case 'm':
1996                                 {
1997                                         flag = TRUE;
1998
1999                                         m = 0;
2000                                         bd = 999;
2001
2002                                         /* Pick a nearby monster */
2003                                         for (i = 0; i < temp_n; i++)
2004                                         {
2005                                                 t = distance(y, x, temp_y[i], temp_x[i]);
2006
2007                                                 /* Pick closest */
2008                                                 if (t < bd)
2009                                                 {
2010                                                         m = i;
2011                                                         bd = t;
2012                                                 }
2013                                         }
2014
2015                                         /* Nothing interesting */
2016                                         if (bd == 999) flag = FALSE;
2017
2018                                         break;
2019                                 }
2020
2021                                 default:
2022                                 {
2023                                         /* Extract the action (if any) */
2024                                         d = get_keymap_dir(query);
2025
2026                                         /* XTRA HACK MOVEFAST */
2027                                         if (isupper(query)) move_fast = TRUE;
2028
2029                                         if (!d) bell();
2030                                         break;
2031                                 }
2032                         }
2033
2034                         /* Handle "direction" */
2035                         if (d)
2036                         {
2037                                 POSITION dx = ddx[d];
2038                                 POSITION dy = ddy[d];
2039
2040                                 /* XTRA HACK MOVEFAST */
2041                                 if (move_fast)
2042                                 {
2043                                         int mag = MIN(wid / 2, hgt / 2);
2044                                         x += dx * mag;
2045                                         y += dy * mag;
2046                                 }
2047                                 else
2048                                 {
2049                                         x += dx;
2050                                         y += dy;
2051                                 }
2052
2053                                 /* Do not move horizontally if unnecessary */
2054                                 if (((x < panel_col_min + wid / 2) && (dx > 0)) ||
2055                                          ((x > panel_col_min + wid / 2) && (dx < 0)))
2056                                 {
2057                                         dx = 0;
2058                                 }
2059
2060                                 /* Do not move vertically if unnecessary */
2061                                 if (((y < panel_row_min + hgt / 2) && (dy > 0)) ||
2062                                          ((y > panel_row_min + hgt / 2) && (dy < 0)))
2063                                 {
2064                                         dy = 0;
2065                                 }
2066
2067                                 /* Apply the motion */
2068                                 if ((y >= panel_row_min + hgt) || (y < panel_row_min) ||
2069                                          (x >= panel_col_min + wid) || (x < panel_col_min))
2070                                 {
2071                                         if (change_panel(dy, dx)) target_set_prepare(mode);
2072                                 }
2073
2074                                 /* Slide into legality */
2075                                 if (x >= cur_wid-1) x = cur_wid - 2;
2076                                 else if (x <= 0) x = 1;
2077
2078                                 /* Slide into legality */
2079                                 if (y >= cur_hgt-1) y = cur_hgt- 2;
2080                                 else if (y <= 0) y = 1;
2081                         }
2082                 }
2083         }
2084
2085         /* Forget */
2086         temp_n = 0;
2087
2088         /* Clear the top line */
2089         prt("", 0, 0);
2090
2091         /* Recenter the map around the player */
2092         verify_panel();
2093         p_ptr->update |= (PU_MONSTERS);
2094         p_ptr->redraw |= (PR_MAP);
2095         p_ptr->window |= (PW_OVERHEAD);
2096         handle_stuff();
2097
2098         /* Failure to set target */
2099         if (!target_who) return (FALSE);
2100
2101         /* Success */
2102         return (TRUE);
2103 }
2104
2105
2106 /*
2107  * Get an "aiming direction" from the user.
2108  *
2109  * The "dir" is loaded with 1,2,3,4,6,7,8,9 for "actual direction", and
2110  * "0" for "current target", and "-1" for "entry aborted".
2111  *
2112  * Note that "Force Target", if set, will pre-empt user interaction,
2113  * if there is a usable target already set.
2114  *
2115  * Note that confusion over-rides any (explicit?) user choice.
2116  */
2117 bool get_aim_dir(DIRECTION *dp)
2118 {
2119         DIRECTION dir;
2120         char    command;
2121         concptr p;
2122         COMMAND_CODE code;
2123
2124         (*dp) = 0;
2125
2126         /* Global direction */
2127         dir = command_dir;
2128
2129         /* Hack -- auto-target if requested */
2130         if (use_old_target && target_okay()) dir = 5;
2131
2132         if (repeat_pull(&code))
2133         {
2134                 /* Confusion? */
2135
2136                 /* Verify */
2137                 if (!(code == 5 && !target_okay()))
2138                 {
2139 /*                      return (TRUE); */
2140                         dir = (DIRECTION)code;
2141                 }
2142         }
2143         *dp = (DIRECTION)code;
2144
2145         /* Ask until satisfied */
2146         while (!dir)
2147         {
2148                 /* Choose a prompt */
2149                 if (!target_okay())
2150                 {
2151                         p = _("方向 ('*'でターゲット選択, ESCで中断)? ", "Direction ('*' to choose a target, Escape to cancel)? ");
2152                 }
2153                 else
2154                 {
2155                         p = _("方向 ('5'でターゲットへ, '*'でターゲット再選択, ESCで中断)? ", "Direction ('5' for target, '*' to re-target, Escape to cancel)? ");
2156                 }
2157
2158                 /* Get a command (or Cancel) */
2159                 if (!get_com(p, &command, TRUE)) break;
2160
2161                 if (use_menu)
2162                 {
2163                         if (command == '\r') command = 't';
2164                 }  
2165
2166                 /* Convert various keys to "standard" keys */
2167                 switch (command)
2168                 {
2169                         /* Use current target */
2170                         case 'T':
2171                         case 't':
2172                         case '.':
2173                         case '5':
2174                         case '0':
2175                         {
2176                                 dir = 5;
2177                                 break;
2178                         }
2179
2180                         /* Set new target */
2181                         case '*':
2182                         case ' ':
2183                         case '\r':
2184                         {
2185                                 if (target_set(TARGET_KILL)) dir = 5;
2186                                 break;
2187                         }
2188
2189                         default:
2190                         {
2191                                 /* Extract the action (if any) */
2192                                 dir = get_keymap_dir(command);
2193
2194                                 break;
2195                         }
2196                 }
2197
2198                 /* Verify requested targets */
2199                 if ((dir == 5) && !target_okay()) dir = 0;
2200
2201                 /* Error */
2202                 if (!dir) bell();
2203         }
2204
2205         /* No direction */
2206         if (!dir)
2207         {
2208                 project_length = 0; /* reset to default */
2209                 return (FALSE);
2210         }
2211
2212         /* Save the direction */
2213         command_dir = dir;
2214
2215         /* Check for confusion */
2216         if (p_ptr->confused)
2217         {
2218                 /* Random direction */
2219                 dir = ddd[randint0(8)];
2220         }
2221
2222         /* Notice confusion */
2223         if (command_dir != dir)
2224         {
2225                 /* Warn the user */
2226                 msg_print(_("あなたは混乱している。", "You are confused."));
2227         }
2228
2229         /* Save direction */
2230         (*dp) = dir;
2231
2232 /*      repeat_push(dir); */
2233         repeat_push((COMMAND_CODE)command_dir);
2234
2235         /* A "valid" direction was entered */
2236         return (TRUE);
2237 }
2238
2239
2240 bool get_direction(DIRECTION *dp, bool allow_under, bool with_steed)
2241 {
2242         DIRECTION dir;
2243         concptr prompt;
2244         COMMAND_CODE code;
2245
2246         (*dp) = 0;
2247
2248         /* Global direction */
2249         dir = command_dir;
2250
2251         if (repeat_pull(&code))
2252         {
2253                 dir = (DIRECTION)code;
2254                 /*              return (TRUE); */
2255         }
2256         *dp = (DIRECTION)code;
2257
2258         if (allow_under)
2259         {
2260                 prompt = _("方向 ('.'足元, ESCで中断)? ", "Direction ('.' at feet, Escape to cancel)? ");
2261         }
2262         else
2263         {
2264                 prompt = _("方向 (ESCで中断)? ", "Direction (Escape to cancel)? ");
2265         }
2266
2267         /* Get a direction */
2268         while (!dir)
2269         {
2270                 char ch;
2271
2272                 /* Get a command (or Cancel) */
2273                 if (!get_com(prompt, &ch, TRUE)) break;
2274
2275                 /* Look down */
2276                 if ((allow_under) && ((ch == '5') || (ch == '-') || (ch == '.')))
2277                 {
2278                         dir = 5;
2279                 }
2280                 else
2281                 {
2282                         /* Look up the direction */
2283                         dir = get_keymap_dir(ch);
2284
2285                         if (!dir) bell();
2286                 }
2287         }
2288
2289         /* Prevent weirdness */
2290         if ((dir == 5) && (!allow_under)) dir = 0;
2291
2292         /* Aborted */
2293         if (!dir) return (FALSE);
2294
2295         /* Save desired direction */
2296         command_dir = dir;
2297
2298         /* Apply "confusion" */
2299         if (p_ptr->confused)
2300         {
2301                 /* Standard confusion */
2302                 if (randint0(100) < 75)
2303                 {
2304                         /* Random direction */
2305                         dir = ddd[randint0(8)];
2306                 }
2307         }
2308         else if (p_ptr->riding && with_steed)
2309         {
2310                 monster_type *m_ptr = &m_list[p_ptr->riding];
2311                 monster_race *r_ptr = &r_info[m_ptr->r_idx];
2312
2313                 if (MON_CONFUSED(m_ptr))
2314                 {
2315                         /* Standard confusion */
2316                         if (randint0(100) < 75)
2317                         {
2318                                 /* Random direction */
2319                                 dir = ddd[randint0(8)];
2320                         }
2321                 }
2322                 else if ((r_ptr->flags1 & RF1_RAND_50) && (r_ptr->flags1 & RF1_RAND_25) && (randint0(100) < 50))
2323                 {
2324                         /* Random direction */
2325                         dir = ddd[randint0(8)];
2326                 }
2327                 else if ((r_ptr->flags1 & RF1_RAND_50) && (randint0(100) < 25))
2328                 {
2329                         /* Random direction */
2330                         dir = ddd[randint0(8)];
2331                 }
2332         }
2333
2334         /* Notice confusion */
2335         if (command_dir != dir)
2336         {
2337                 if (p_ptr->confused)
2338                 {
2339                         /* Warn the user */
2340                         msg_print(_("あなたは混乱している。", "You are confused."));
2341                 }
2342                 else
2343                 {
2344                         GAME_TEXT m_name[MAX_NLEN];
2345                         monster_type *m_ptr = &m_list[p_ptr->riding];
2346
2347                         monster_desc(m_name, m_ptr, 0);
2348                         if (MON_CONFUSED(m_ptr))
2349                         {
2350                                 msg_format(_("%sは混乱している。", "%^s is confusing."), m_name);
2351                         }
2352                         else
2353                         {
2354                                 msg_format(_("%sは思い通りに動いてくれない。", "You cannot control %s."), m_name);
2355                         }
2356                 }
2357         }
2358
2359         /* Save direction */
2360         (*dp) = dir;
2361
2362         /*      repeat_push(dir); */
2363         repeat_push((COMMAND_CODE)command_dir);
2364
2365         /* Success */
2366         return (TRUE);
2367 }
2368
2369 /*
2370  * @brief 進行方向を指定する(騎乗対象の混乱の影響を受ける) / Request a "movement" direction (1,2,3,4,6,7,8,9) from the user,
2371  * and place it into "command_dir", unless we already have one.
2372  *
2373  * This function should be used for all "repeatable" commands, such as
2374  * run, walk, open, close, bash, disarm, spike, tunnel, etc, as well
2375  * as all commands which must reference a grid adjacent to the player,
2376  * and which may not reference the grid under the player.  Note that,
2377  * for example, it is no longer possible to "disarm" or "open" chests
2378  * in the same grid as the player.
2379  *
2380  * Direction "5" is illegal and will (cleanly) abort the command.
2381  *
2382  * This function tracks and uses the "global direction", and uses
2383  * that as the "desired direction", to which "confusion" is applied.
2384  */
2385 bool get_rep_dir(DIRECTION *dp, bool under)
2386 {
2387         DIRECTION dir;
2388         concptr prompt;
2389         COMMAND_CODE code;
2390
2391         (*dp) = 0;
2392
2393         /* Global direction */
2394         dir = command_dir;
2395
2396         if (repeat_pull(&code))
2397         {
2398                 dir = (DIRECTION)code;
2399 /*              return (TRUE); */
2400         }
2401         *dp = (DIRECTION)code;
2402
2403         if (under)
2404         {
2405                 prompt = _("方向 ('.'足元, ESCで中断)? ", "Direction ('.' at feet, Escape to cancel)? ");
2406         }
2407         else
2408         {
2409                 prompt = _("方向 (ESCで中断)? ", "Direction (Escape to cancel)? ");
2410         }
2411         
2412         /* Get a direction */
2413         while (!dir)
2414         {
2415                 char ch;
2416
2417                 /* Get a command (or Cancel) */
2418                 if (!get_com(prompt, &ch, TRUE)) break;
2419
2420                 /* Look down */
2421                 if ((under) && ((ch == '5') || (ch == '-') || (ch == '.')))
2422                 {
2423                         dir = 5;
2424                 }
2425                 else
2426                 {
2427                         /* Look up the direction */
2428                         dir = get_keymap_dir(ch);
2429
2430                         if (!dir) bell();
2431                 }
2432         }
2433
2434         /* Prevent weirdness */
2435         if ((dir == 5) && (!under)) dir = 0;
2436
2437         /* Aborted */
2438         if (!dir) return (FALSE);
2439
2440         /* Save desired direction */
2441         command_dir = dir;
2442
2443         /* Apply "confusion" */
2444         if (p_ptr->confused)
2445         {
2446                 /* Standard confusion */
2447                 if (randint0(100) < 75)
2448                 {
2449                         /* Random direction */
2450                         dir = ddd[randint0(8)];
2451                 }
2452         }
2453         else if (p_ptr->riding)
2454         {
2455                 monster_type *m_ptr = &m_list[p_ptr->riding];
2456                 monster_race *r_ptr = &r_info[m_ptr->r_idx];
2457
2458                 if (MON_CONFUSED(m_ptr))
2459                 {
2460                         /* Standard confusion */
2461                         if (randint0(100) < 75)
2462                         {
2463                                 /* Random direction */
2464                                 dir = ddd[randint0(8)];
2465                         }
2466                 }
2467                 else if ((r_ptr->flags1 & RF1_RAND_50) && (r_ptr->flags1 & RF1_RAND_25) && (randint0(100) < 50))
2468                 {
2469                         /* Random direction */
2470                         dir = ddd[randint0(8)];
2471                 }
2472                 else if ((r_ptr->flags1 & RF1_RAND_50) && (randint0(100) < 25))
2473                 {
2474                         /* Random direction */
2475                         dir = ddd[randint0(8)];
2476                 }
2477         }
2478
2479         /* Notice confusion */
2480         if (command_dir != dir)
2481         {
2482                 if (p_ptr->confused)
2483                 {
2484                         /* Warn the user */
2485                         msg_print(_("あなたは混乱している。", "You are confused."));
2486                 }
2487                 else
2488                 {
2489                         GAME_TEXT m_name[MAX_NLEN];
2490                         monster_type *m_ptr = &m_list[p_ptr->riding];
2491
2492                         monster_desc(m_name, m_ptr, 0);
2493                         if (MON_CONFUSED(m_ptr))
2494                         {
2495                                 msg_format(_("%sは混乱している。", "%^s is confusing."), m_name);
2496                         }
2497                         else
2498                         {
2499                                 msg_format(_("%sは思い通りに動いてくれない。", "You cannot control %s."), m_name);
2500                         }
2501                 }
2502         }
2503
2504         /* Save direction */
2505         (*dp) = dir;
2506
2507 /*      repeat_push(dir); */
2508         repeat_push((COMMAND_CODE)command_dir);
2509
2510         /* Success */
2511         return (TRUE);
2512 }
2513
2514
2515 /*
2516  * XAngband: determine if a given location is "interesting"
2517  * based on target_set_accept function.
2518  */
2519 static bool tgt_pt_accept(POSITION y, POSITION x)
2520 {
2521         cave_type *c_ptr;
2522
2523         /* Bounds */
2524         if (!(in_bounds(y, x))) return (FALSE);
2525
2526         /* Player grid is always interesting */
2527         if ((y == p_ptr->y) && (x == p_ptr->x)) return (TRUE);
2528
2529         /* Handle hallucination */
2530         if (p_ptr->image) return (FALSE);
2531
2532         /* Examine the grid */
2533         c_ptr = &cave[y][x];
2534
2535         /* Interesting memorized features */
2536         if (c_ptr->info & (CAVE_MARK))
2537         {
2538                 /* Notice stairs */
2539                 if (cave_have_flag_grid(c_ptr, FF_LESS)) return (TRUE);
2540                 if (cave_have_flag_grid(c_ptr, FF_MORE)) return (TRUE);
2541
2542                 /* Notice quest features */
2543                 if (cave_have_flag_grid(c_ptr, FF_QUEST_ENTER)) return (TRUE);
2544                 if (cave_have_flag_grid(c_ptr, FF_QUEST_EXIT)) return (TRUE);
2545         }
2546
2547         return (FALSE);
2548 }
2549
2550
2551 /*
2552  * XAngband: Prepare the "temp" array for "tget_pt"
2553  * based on target_set_prepare funciton.
2554  */
2555 static void tgt_pt_prepare(void)
2556 {
2557         POSITION y, x;
2558
2559         /* Reset "temp" array */
2560         temp_n = 0;
2561
2562         if (!expand_list) return;
2563
2564         /* Scan the current panel */
2565         for (y = 1; y < cur_hgt; y++)
2566         {
2567                 for (x = 1; x < cur_wid; x++)
2568                 {
2569                         /* Require "interesting" contents */
2570                         if (!tgt_pt_accept(y, x)) continue;
2571
2572                         /* Save the location */
2573                         temp_x[temp_n] = x;
2574                         temp_y[temp_n] = y;
2575                         temp_n++;
2576                 }
2577         }
2578
2579         /* Target the nearest monster for shooting */
2580         ang_sort_comp = ang_sort_comp_distance;
2581         ang_sort_swap = ang_sort_swap_distance;
2582
2583         /* Sort the positions */
2584         ang_sort(temp_x, temp_y, temp_n);
2585 }
2586
2587 /*
2588  * old -- from PsiAngband.
2589  */
2590 bool tgt_pt(POSITION *x_ptr, POSITION *y_ptr)
2591 {
2592         char ch = 0;
2593         int d, n = 0;
2594         POSITION x, y;
2595         bool success = FALSE;
2596
2597         TERM_LEN wid, hgt;
2598
2599         get_screen_size(&wid, &hgt);
2600
2601         x = p_ptr->x;
2602         y = p_ptr->y;
2603
2604         if (expand_list) 
2605         {
2606                 tgt_pt_prepare();
2607         }
2608
2609         msg_print(_("場所を選んでスペースキーを押して下さい。", "Select a point and press space."));
2610         msg_flag = FALSE; /* prevents "-more-" message. */
2611
2612         while ((ch != ESCAPE) && !success)
2613         {
2614                 bool move_fast = FALSE;
2615
2616                 move_cursor_relative(y, x);
2617                 ch = inkey();
2618                 switch (ch)
2619                 {
2620                 case ESCAPE:
2621                         break;
2622                 case ' ':
2623                 case 't':
2624                 case '.':
2625                 case '5':
2626                 case '0':
2627                         /* illegal place */
2628                         if (player_bold(y, x)) ch = 0;
2629
2630                         /* okay place */
2631                         else success = TRUE;
2632
2633                         break;
2634
2635                 /* XAngband: Move cursor to stairs */
2636                 case '>':
2637                 case '<':
2638                         if (expand_list && temp_n)
2639                         {
2640                                 int dx, dy;
2641                                 int cx = (panel_col_min + panel_col_max) / 2;
2642                                 int cy = (panel_row_min + panel_row_max) / 2;
2643
2644                                 n++;
2645
2646                                 /* Skip stairs which have defferent distance */
2647                                 for (; n < temp_n; ++ n)
2648                                 {
2649                                         cave_type *c_ptr = &cave[temp_y[n]][temp_x[n]];
2650
2651                                         if (cave_have_flag_grid(c_ptr, FF_STAIRS) &&
2652                                             cave_have_flag_grid(c_ptr, ch == '>' ? FF_MORE : FF_LESS))
2653                                         {
2654                                                 /* Found */
2655                                                 break;
2656                                         }
2657                                 }
2658
2659                                 if (n == temp_n)        /* Loop out taget list */
2660                                 {
2661                                         n = 0;
2662                                         y = p_ptr->y;
2663                                         x = p_ptr->x;
2664                                         verify_panel(); /* Move cursor to player */
2665
2666                                         p_ptr->update |= (PU_MONSTERS);
2667
2668                                         p_ptr->redraw |= (PR_MAP);
2669
2670                                         p_ptr->window |= (PW_OVERHEAD);
2671                                         handle_stuff();
2672                                 }
2673                                 else    /* move cursor to next stair and change panel */
2674                                 {
2675                                         y = temp_y[n];
2676                                         x = temp_x[n];
2677
2678                                         dy = 2 * (y - cy) / hgt;
2679                                         dx = 2 * (x - cx) / wid;
2680                                         if (dy || dx) change_panel(dy, dx);
2681                                 }
2682                         }
2683                         break;
2684
2685                 default:
2686                         /* Look up the direction */
2687                         d = get_keymap_dir(ch);
2688
2689                         /* XTRA HACK MOVEFAST */
2690                         if (isupper(ch)) move_fast = TRUE;
2691
2692                         /* Handle "direction" */
2693                         if (d)
2694                         {
2695                                 int dx = ddx[d];
2696                                 int dy = ddy[d];
2697
2698                                 /* XTRA HACK MOVEFAST */
2699                                 if (move_fast)
2700                                 {
2701                                         int mag = MIN(wid / 2, hgt / 2);
2702                                         x += dx * mag;
2703                                         y += dy * mag;
2704                                 }
2705                                 else
2706                                 {
2707                                         x += dx;
2708                                         y += dy;
2709                                 }
2710
2711                                 /* Do not move horizontally if unnecessary */
2712                                 if (((x < panel_col_min + wid / 2) && (dx > 0)) ||
2713                                          ((x > panel_col_min + wid / 2) && (dx < 0)))
2714                                 {
2715                                         dx = 0;
2716                                 }
2717
2718                                 /* Do not move vertically if unnecessary */
2719                                 if (((y < panel_row_min + hgt / 2) && (dy > 0)) ||
2720                                          ((y > panel_row_min + hgt / 2) && (dy < 0)))
2721                                 {
2722                                         dy = 0;
2723                                 }
2724
2725                                 /* Apply the motion */
2726                                 if ((y >= panel_row_min + hgt) || (y < panel_row_min) ||
2727                                          (x >= panel_col_min + wid) || (x < panel_col_min))
2728                                 {
2729                                         /* if (change_panel(dy, dx)) target_set_prepare(mode); */
2730                                         change_panel(dy, dx);
2731                                 }
2732
2733                                 /* Slide into legality */
2734                                 if (x >= cur_wid-1) x = cur_wid - 2;
2735                                 else if (x <= 0) x = 1;
2736
2737                                 /* Slide into legality */
2738                                 if (y >= cur_hgt-1) y = cur_hgt- 2;
2739                                 else if (y <= 0) y = 1;
2740
2741                         }
2742                         break;
2743                 }
2744         }
2745
2746         /* Clear the top line */
2747         prt("", 0, 0);
2748
2749         /* Recenter the map around the player */
2750         verify_panel();
2751
2752         p_ptr->update |= (PU_MONSTERS);
2753
2754         p_ptr->redraw |= (PR_MAP);
2755
2756         p_ptr->window |= (PW_OVERHEAD);
2757         handle_stuff();
2758
2759         *x_ptr = x;
2760         *y_ptr = y;
2761         return success;
2762 }
2763
2764
2765 bool get_hack_dir(DIRECTION *dp)
2766 {
2767         DIRECTION dir;
2768         concptr    p;
2769         char    command;
2770
2771         (*dp) = 0;
2772
2773         /* Global direction */
2774         dir = 0;
2775
2776         /* (No auto-targeting) */
2777
2778         /* Ask until satisfied */
2779         while (!dir)
2780         {
2781                 /* Choose a prompt */
2782                 if (!target_okay())
2783                 {
2784                         p = _("方向 ('*'でターゲット選択, ESCで中断)? ", "Direction ('*' to choose a target, Escape to cancel)? ");
2785                 }
2786                 else
2787                 {
2788                         p = _("方向 ('5'でターゲットへ, '*'でターゲット再選択, ESCで中断)? ", "Direction ('5' for target, '*' to re-target, Escape to cancel)? ");
2789                 }
2790
2791                 /* Get a command (or Cancel) */
2792                 if (!get_com(p, &command, TRUE)) break;
2793
2794                 if (use_menu)
2795                 {
2796                         if (command == '\r') command = 't';
2797                 }  
2798
2799                 /* Convert various keys to "standard" keys */
2800                 switch (command)
2801                 {
2802                         /* Use current target */
2803                         case 'T':
2804                         case 't':
2805                         case '.':
2806                         case '5':
2807                         case '0':
2808                         {
2809                                 dir = 5;
2810                                 break;
2811                         }
2812
2813                         /* Set new target */
2814                         case '*':
2815                         case ' ':
2816                         case '\r':
2817                         {
2818                                 if (target_set(TARGET_KILL)) dir = 5;
2819                                 break;
2820                         }
2821
2822                         default:
2823                         {
2824                                 /* Look up the direction */
2825                                 dir = get_keymap_dir(command);
2826
2827                                 break;
2828                         }
2829                 }
2830
2831                 /* Verify requested targets */
2832                 if ((dir == 5) && !target_okay()) dir = 0;
2833
2834                 /* Error */
2835                 if (!dir) bell();
2836         }
2837
2838         /* No direction */
2839         if (!dir) return (FALSE);
2840
2841         /* Save the direction */
2842         command_dir = dir;
2843
2844         /* Check for confusion */
2845         if (p_ptr->confused)
2846         {
2847                 /* Random direction */
2848                 dir = ddd[randint0(8)];
2849         }
2850
2851         /* Notice confusion */
2852         if (command_dir != dir)
2853         {
2854                 /* Warn the user */
2855                 msg_print(_("あなたは混乱している。", "You are confused."));
2856         }
2857
2858         /* Save direction */
2859         (*dp) = dir;
2860
2861         /* A "valid" direction was entered */
2862         return (TRUE);
2863 }
2864
2865
2866 /*!
2867  * @brief 射撃武器の攻撃に必要な基本消費エネルギーを返す/Return bow energy
2868  * @param sval 射撃武器のアイテム副分類ID 
2869  * @return 消費する基本エネルギー
2870  */
2871 ENERGY bow_energy(OBJECT_SUBTYPE_VALUE sval)
2872 {
2873         ENERGY energy = 10000;
2874
2875         /* Analyze the launcher */
2876         switch (sval)
2877         {
2878                 /* Sling and ammo */
2879                 case SV_SLING:
2880                 {
2881                         energy = 8000;
2882                         break;
2883                 }
2884
2885                 /* Short Bow and Arrow */
2886                 case SV_SHORT_BOW:
2887                 {
2888                         energy = 10000;
2889                         break;
2890                 }
2891
2892                 /* Long Bow and Arrow */
2893                 case SV_LONG_BOW:
2894                 {
2895                         energy = 10000;
2896                         break;
2897                 }
2898
2899                 /* Bow of irresponsiblity and Arrow */
2900                 case SV_NAMAKE_BOW:
2901                 {
2902                         energy = 7777;
2903                         break;
2904                 }
2905
2906                 /* Light Crossbow and Bolt */
2907                 case SV_LIGHT_XBOW:
2908                 {
2909                         energy = 12000;
2910                         break;
2911                 }
2912
2913                 /* Heavy Crossbow and Bolt */
2914                 case SV_HEAVY_XBOW:
2915                 {
2916                         energy = 13333;
2917                         break;
2918                 }
2919         }
2920
2921         return (energy);
2922 }
2923
2924
2925 /*
2926  * Return bow tmul
2927  */
2928 int bow_tmul(OBJECT_SUBTYPE_VALUE sval)
2929 {
2930         int tmul = 0;
2931
2932         /* Analyze the launcher */
2933         switch (sval)
2934         {
2935                 /* Sling and ammo */
2936                 case SV_SLING:
2937                 {
2938                         tmul = 2;
2939                         break;
2940                 }
2941
2942                 /* Short Bow and Arrow */
2943                 case SV_SHORT_BOW:
2944                 {
2945                         tmul = 2;
2946                         break;
2947                 }
2948
2949                 /* Long Bow and Arrow */
2950                 case SV_LONG_BOW:
2951                 {
2952                         tmul = 3;
2953                         break;
2954                 }
2955
2956                 /* Bow of irresponsiblity and Arrow */
2957                 case SV_NAMAKE_BOW:
2958                 {
2959                         tmul = 3;
2960                         break;
2961                 }
2962
2963                 /* Light Crossbow and Bolt */
2964                 case SV_LIGHT_XBOW:
2965                 {
2966                         tmul = 3;
2967                         break;
2968                 }
2969
2970                 /* Heavy Crossbow and Bolt */
2971                 case SV_HEAVY_XBOW:
2972                 {
2973                         tmul = 4;
2974                         break;
2975                 }
2976         }
2977
2978         return (tmul);
2979 }
2980
2981
2982 /*
2983  * Display a rumor and apply its effects
2984  */
2985
2986 IDX rumor_num(char *zz, IDX max_idx)
2987 {
2988         if (strcmp(zz, "*") == 0) return randint1(max_idx - 1);
2989         return (IDX)atoi(zz);
2990 }
2991
2992 concptr rumor_bind_name(char *base, concptr fullname)
2993 {
2994         char *s, *v;
2995
2996         s = strstr(base, "{Name}");
2997         if (s)
2998         {
2999                 s[0] = '\0';
3000                 v = format("%s%s%s", base, fullname, (s + 6));
3001         }
3002         else
3003         {
3004                 v = base;
3005         }
3006
3007         return v;
3008 }
3009
3010 void display_rumor(bool ex)
3011 {
3012         errr err;
3013         int section = 0;
3014         char Rumor[1024];
3015
3016         if (ex)
3017         {
3018                 if (randint0(3) == 0) section = 1;
3019         }
3020
3021         err = _(get_rnd_line_jonly("rumors_j.txt", section, Rumor, 10),
3022                         get_rnd_line("rumors.txt", section, Rumor));
3023         if (err) strcpy(Rumor, _("嘘の噂もある。", "Some rumors are wrong."));
3024
3025         err = TRUE;
3026
3027         if (strncmp(Rumor, "R:", 2) == 0)
3028         {
3029                 char *zz[4];
3030                 concptr rumor_msg = NULL;
3031                 concptr rumor_eff_format = NULL;
3032                 char fullname[1024] = "";
3033
3034                 if (tokenize(Rumor + 2, 3, zz, TOKENIZE_CHECKQUOTE) == 3)
3035                 {
3036                         if (strcmp(zz[0], "ARTIFACT") == 0)
3037                         {
3038                                 IDX a_idx, k_idx;
3039                                 object_type forge;
3040                                 object_type *q_ptr = &forge;
3041                                 artifact_type *a_ptr;
3042
3043                                 while (1)
3044                                 {
3045                                         a_idx = rumor_num(zz[1], max_a_idx);
3046
3047                                         a_ptr = &a_info[a_idx];
3048                                         if (a_ptr->name) break;
3049                                 }
3050
3051                                 k_idx = lookup_kind(a_ptr->tval, a_ptr->sval);
3052                                 object_prep(q_ptr, k_idx);
3053                                 q_ptr->name1 = a_idx;
3054                                 q_ptr->ident = IDENT_STORE;
3055                                 object_desc(fullname, q_ptr, OD_NAME_ONLY);
3056                         }
3057                         else if  (strcmp(zz[0], "MONSTER") == 0)
3058                         {
3059                                 MONRACE_IDX r_idx;
3060                                 monster_race *r_ptr;
3061
3062                                 while(1)
3063                                 {
3064                                         r_idx = rumor_num(zz[1], max_r_idx);
3065                                         r_ptr = &r_info[r_idx];
3066                                         if (r_ptr->name) break;
3067                                 }
3068
3069                                 strcpy(fullname, r_name + r_ptr->name);
3070
3071                                 /* Remember this monster */
3072                                 if (!r_ptr->r_sights)
3073                                 {
3074                                         r_ptr->r_sights++;
3075                                 }
3076                         }
3077                         else if (strcmp(zz[0], "DUNGEON") == 0)
3078                         {
3079                                 DUNGEON_IDX d_idx;
3080                                 dungeon_info_type *d_ptr;
3081
3082                                 while (1)
3083                                 {
3084                                         d_idx = rumor_num(zz[1], max_d_idx);
3085                                         d_ptr = &d_info[d_idx];
3086                                         if (d_ptr->name) break;
3087                                 }
3088
3089                                 strcpy(fullname, d_name + d_ptr->name);
3090
3091                                 if (!max_dlv[d_idx])
3092                                 {
3093                                         max_dlv[d_idx] = d_ptr->mindepth;
3094                                         rumor_eff_format = _("%sに帰還できるようになった。", "You can recall to %s.");
3095                                 }
3096                         }
3097                         else if  (strcmp(zz[0], "TOWN") == 0)
3098                         {
3099                                 IDX t_idx;
3100                                 s32b visit;
3101
3102                                 while(1)
3103                                 {
3104                                         t_idx = rumor_num(zz[1], NO_TOWN);
3105                                         if (town[t_idx].name) break;
3106                                 }
3107
3108                                 strcpy(fullname, town[t_idx].name);
3109
3110                                 visit = (1L << (t_idx - 1));
3111                                 if ((t_idx != SECRET_TOWN) && !(p_ptr->visit & visit))
3112                                 {
3113                                         p_ptr->visit |= visit;
3114                                         rumor_eff_format = _("%sに行ったことがある気がする。", "You feel you have been to %s.");
3115                                 }
3116                         }
3117
3118                         rumor_msg = rumor_bind_name(zz[2], fullname);
3119                         msg_print(rumor_msg);
3120                         if (rumor_eff_format)
3121                         {
3122                                 msg_print(NULL);
3123                                 msg_format(rumor_eff_format, fullname);
3124                         }
3125                         err = FALSE;
3126                 }
3127         /* error */
3128         if (err) msg_print(_("この情報は間違っている。", "This information is wrong."));
3129         }
3130                         else
3131         {
3132                 msg_format("%s", Rumor);
3133         }
3134 }