OSDN Git Service

[Refactor] #40571 Moved targeting.c/h from io/ to target/
[hengbandforosx/hengbandosx.git] / src / window / display-sub-windows.c
1 #include "window/display-sub-windows.h"
2 #include "core/window-redrawer.h"
3 #include "flavor/flavor-describer.h"
4 #include "floor/cave.h"
5 #include "game-option/option-flags.h"
6 #include "game-option/special-options.h"
7 #include "game-option/text-display-options.h"
8 #include "grid/feature.h"
9 #include "grid/grid.h"
10 #include "inventory/inventory-describer.h"
11 #include "inventory/inventory-slot-types.h"
12 #include "inventory/inventory-util.h"
13 #include "monster-race/monster-race.h"
14 #include "monster-race/race-flags1.h"
15 #include "monster/monster-flag-types.h"
16 #include "monster/monster-info.h"
17 #include "object/item-tester-hooker.h"
18 #include "object/object-info.h"
19 #include "spell-kind/magic-item-recharger.h"
20 #include "system/floor-type-definition.h"
21 #include "system/monster-type-definition.h"
22 #include "target/targeting.h"
23 #include "term/gameterm.h"
24 #include "term/screen-processor.h"
25 #include "term/term-color-types.h"
26 #include "view/display-lore.h"
27 #include "view/display-map.h"
28 #include "view/display-messages.h"
29 #include "view/display-player.h"
30 #include "view/object-describer.h"
31 #include "window/main-window-equipments.h"
32 #include "window/main-window-util.h"
33 #include "world/world.h"
34
35 /*!
36  * @brief サブウィンドウに所持品一覧を表示する / Hack -- display inventory in sub-windows
37  * @param player_ptr プレーヤーへの参照ポインタ
38  * @return なし
39  */
40 void fix_inventory(player_type *player_ptr, tval_type item_tester_tval)
41 {
42     for (int j = 0; j < 8; j++) {
43         term_type *old = Term;
44         if (!angband_term[j])
45             continue;
46
47         if (!(window_flag[j] & (PW_INVEN)))
48             continue;
49
50         term_activate(angband_term[j]);
51         display_inventory(player_ptr, item_tester_tval);
52         term_fresh();
53         term_activate(old);
54     }
55 }
56
57 /*!
58  * @brief モンスターの現在数を一行で表現する / Print monster info in line
59  * @param x 表示列
60  * @param y 表示行
61  * @param m_ptr 思い出を表示するモンスター情報の参照ポインタ
62  * @param n_same モンスターの数の現在数
63  * @details
64  * <pre>
65  * nnn X LV name
66  *  nnn : number or unique(U) or wanted unique(W)
67  *  X   : symbol of monster
68  *  LV  : monster lv if known
69  *  name: name of monster
70  * @return なし
71  * </pre>
72  */
73 static void print_monster_line(TERM_LEN x, TERM_LEN y, monster_type *m_ptr, int n_same)
74 {
75     char buf[256];
76     MONRACE_IDX r_idx = m_ptr->ap_r_idx;
77     monster_race *r_ptr = &r_info[r_idx];
78
79     term_gotoxy(x, y);
80     if (!r_ptr)
81         return;
82     if (r_ptr->flags1 & RF1_UNIQUE) {
83         bool is_bounty = FALSE;
84         for (int i = 0; i < MAX_BOUNTY; i++) {
85             if (current_world_ptr->bounty_r_idx[i] == r_idx) {
86                 is_bounty = TRUE;
87                 break;
88             }
89         }
90
91         term_addstr(-1, TERM_WHITE, is_bounty ? "  W" : "  U");
92     } else {
93         sprintf(buf, "%3d", n_same);
94         term_addstr(-1, TERM_WHITE, buf);
95     }
96
97     term_addstr(-1, TERM_WHITE, " ");
98     term_add_bigch(r_ptr->x_attr, r_ptr->x_char);
99
100     if (r_ptr->r_tkills && !(m_ptr->mflag2 & MFLAG2_KAGE)) {
101         sprintf(buf, " %2d", (int)r_ptr->level);
102     } else {
103         strcpy(buf, " ??");
104     }
105
106     term_addstr(-1, TERM_WHITE, buf);
107
108     sprintf(buf, " %s ", r_name + r_ptr->name);
109     term_addstr(-1, TERM_WHITE, buf);
110 }
111
112 /*!
113  * @brief モンスターの出現リストを表示する / Print monster info in line
114  * @param x 表示列
115  * @param y 表示行
116  * @param max_lines 最大何行描画するか
117  */
118 void print_monster_list(floor_type *floor_ptr, TERM_LEN x, TERM_LEN y, TERM_LEN max_lines)
119 {
120     TERM_LEN line = y;
121     monster_type *last_mons = NULL;
122     monster_type *m_ptr = NULL;
123     int n_same = 0;
124     int i;
125     for (i = 0; i < tmp_pos.n; i++) {
126         grid_type *g_ptr = &floor_ptr->grid_array[tmp_pos.y[i]][tmp_pos.x[i]];
127         if (!g_ptr->m_idx || !floor_ptr->m_list[g_ptr->m_idx].ml)
128             continue;
129         m_ptr = &floor_ptr->m_list[g_ptr->m_idx];
130         if (is_pet(m_ptr))
131             continue; // pet
132         if (!m_ptr->r_idx)
133             continue; // dead?
134
135         //ソート済みなので同じモンスターは連続する.これを利用して同じモンスターをカウント,まとめて表示する.
136         //先頭モンスター
137         if (!last_mons) {
138             last_mons = m_ptr;
139             n_same = 1;
140             continue;
141         }
142
143         // same race?
144         if (last_mons->ap_r_idx == m_ptr->ap_r_idx) {
145             n_same++;
146             continue; //表示処理を次に回す
147         }
148
149         // print last mons info
150         print_monster_line(x, line++, last_mons, n_same);
151         n_same = 1;
152         last_mons = m_ptr;
153         if (line - y - 1 == max_lines)
154             break;
155     }
156
157     if (line - y - 1 == max_lines && i != tmp_pos.n) {
158         term_gotoxy(x, line);
159         term_addstr(-1, TERM_WHITE, "-- and more --");
160     } else {
161         if (last_mons)
162             print_monster_line(x, line++, last_mons, n_same);
163     }
164 }
165
166 /*!
167  * @brief 出現中モンスターのリストをサブウィンドウに表示する / Hack -- display monster list in sub-windows
168  * @param player_ptr プレーヤーへの参照ポインタ
169  * @return なし
170  */
171 void fix_monster_list(player_type *player_ptr)
172 {
173     for (int j = 0; j < 8; j++) {
174         term_type *old = Term;
175         if (!angband_term[j])
176             continue;
177         if (!(window_flag[j] & (PW_MONSTER_LIST)))
178             continue;
179
180         term_activate(angband_term[j]);
181         int w, h;
182         term_get_size(&w, &h);
183         term_clear();
184         target_set_prepare_look(player_ptr);
185         print_monster_list(player_ptr->current_floor_ptr, 0, 0, h);
186         term_fresh();
187         term_activate(old);
188     }
189 }
190
191 /*!
192  * @brief 装備アイテム一覧を表示する /
193  * Choice window "shadow" of the "show_equip()" function
194  * @return なし
195  */
196 static void display_equipment(player_type *owner_ptr, tval_type tval)
197 {
198     if (!owner_ptr || !owner_ptr->inventory_list)
199         return;
200
201     TERM_LEN wid, hgt;
202     term_get_size(&wid, &hgt);
203
204     TERM_COLOR attr = TERM_WHITE;
205     char tmp_val[80];
206     GAME_TEXT o_name[MAX_NLEN];
207     for (int i = INVEN_RARM; i < INVEN_TOTAL; i++) {
208         object_type *o_ptr;
209         o_ptr = &owner_ptr->inventory_list[i];
210         tmp_val[0] = tmp_val[1] = tmp_val[2] = ' ';
211         if (select_ring_slot ? is_ring_slot(i) : item_tester_okay(owner_ptr, o_ptr, tval)) {
212             tmp_val[0] = index_to_label(i);
213             tmp_val[1] = ')';
214         }
215
216         term_putstr(0, i - INVEN_RARM, 3, TERM_WHITE, tmp_val);
217         if ((((i == INVEN_RARM) && owner_ptr->left_hand_weapon) || ((i == INVEN_LARM) && owner_ptr->right_hand_weapon)) && owner_ptr->two_handed_weapon) {
218             strcpy(o_name, _("(武器を両手持ち)", "(wielding with two-hands)"));
219             attr = TERM_WHITE;
220         } else {
221             describe_flavor(owner_ptr, o_name, o_ptr, 0);
222             attr = tval_to_attr[o_ptr->tval % 128];
223         }
224
225         int n = strlen(o_name);
226         if (o_ptr->timeout)
227             attr = TERM_L_DARK;
228
229         term_putstr(3, i - INVEN_RARM, n, attr, o_name);
230         term_erase(3 + n, i - INVEN_RARM, 255);
231         if (show_weights) {
232             int wgt = o_ptr->weight * o_ptr->number;
233             sprintf(tmp_val, _("%3d.%1d kg", "%3d.%1d lb"), _(lbtokg1(wgt), wgt / 10), _(lbtokg2(wgt), wgt % 10));
234             prt(tmp_val, i - INVEN_RARM, wid - (show_labels ? 28 : 9));
235         }
236
237         if (show_labels) {
238             term_putstr(wid - 20, i - INVEN_RARM, -1, TERM_WHITE, " <-- ");
239             prt(mention_use(owner_ptr, i), i - INVEN_RARM, wid - 15);
240         }
241     }
242
243     for (int i = INVEN_TOTAL - INVEN_RARM; i < hgt; i++)
244         term_erase(0, i, 255);
245 }
246
247 /*!
248  * @brief 現在の装備品をサブウィンドウに表示する /
249  * Hack -- display equipment in sub-windows
250  * @param player_ptr プレーヤーへの参照ポインタ
251  * @return なし
252  */
253 void fix_equip(player_type *player_ptr, tval_type item_tester_tval)
254 {
255     for (int j = 0; j < 8; j++) {
256         term_type *old = Term;
257         if (!angband_term[j])
258             continue;
259         if (!(window_flag[j] & (PW_EQUIP)))
260             continue;
261
262         term_activate(angband_term[j]);
263         display_equipment(player_ptr, item_tester_tval);
264         term_fresh();
265         term_activate(old);
266     }
267 }
268
269 /*!
270  * @brief 現在のプレイヤーステータスをサブウィンドウに表示する /
271  * @param player_ptr プレーヤーへの参照ポインタ
272  * Hack -- display character in sub-windows
273  * @return なし
274  */
275 void fix_player(player_type *player_ptr)
276 {
277     for (int j = 0; j < 8; j++) {
278         term_type *old = Term;
279         if (!angband_term[j])
280             continue;
281
282         if (!(window_flag[j] & (PW_PLAYER)))
283             continue;
284
285         term_activate(angband_term[j]);
286         update_playtime();
287         display_player(player_ptr, 0);
288         term_fresh();
289         term_activate(old);
290     }
291 }
292
293 /*!
294  * @brief ゲームメッセージ履歴をサブウィンドウに表示する /
295  * Hack -- display recent messages in sub-windows
296  * Adjust for width and split messages
297  * @return なし
298  */
299 void fix_message(void)
300 {
301     for (int j = 0; j < 8; j++) {
302         term_type *old = Term;
303         if (!angband_term[j])
304             continue;
305
306         if (!(window_flag[j] & (PW_MESSAGE)))
307             continue;
308
309         term_activate(angband_term[j]);
310         TERM_LEN w, h;
311         term_get_size(&w, &h);
312         for (int i = 0; i < h; i++) {
313             term_putstr(0, (h - 1) - i, -1, (byte)((i < now_message) ? TERM_WHITE : TERM_SLATE), message_str((s16b)i));
314             TERM_LEN x, y;
315             term_locate(&x, &y);
316             term_erase(x, y, 255);
317         }
318
319         term_fresh();
320         term_activate(old);
321     }
322 }
323
324 /*!
325  * @brief 簡易マップをサブウィンドウに表示する /
326  * Hack -- display overhead view in sub-windows
327  * Adjust for width and split messages
328  * @param player_ptr プレーヤーへの参照ポインタ
329  * @return なし
330  * @details
331  * Note that the "player" symbol does NOT appear on the map.
332  */
333 void fix_overhead(player_type *player_ptr)
334 {
335     for (int j = 0; j < 8; j++) {
336         term_type *old = Term;
337         TERM_LEN wid, hgt;
338         if (!angband_term[j])
339             continue;
340
341         if (!(window_flag[j] & (PW_OVERHEAD)))
342             continue;
343
344         term_activate(angband_term[j]);
345         term_get_size(&wid, &hgt);
346         if (wid > COL_MAP + 2 && hgt > ROW_MAP + 2) {
347             int cy, cx;
348             display_map(player_ptr, &cy, &cx);
349             term_fresh();
350         }
351
352         term_activate(old);
353     }
354 }
355
356 static void display_dungeon(player_type *player_ptr)
357 {
358     TERM_COLOR ta = 0;
359     SYMBOL_CODE tc = '\0';
360
361     for (TERM_LEN x = player_ptr->x - Term->wid / 2 + 1; x <= player_ptr->x + Term->wid / 2; x++) {
362         for (TERM_LEN y = player_ptr->y - Term->hgt / 2 + 1; y <= player_ptr->y + Term->hgt / 2; y++) {
363             TERM_COLOR a;
364             SYMBOL_CODE c;
365             if (!in_bounds2(player_ptr->current_floor_ptr, y, x)) {
366                 feature_type *f_ptr = &f_info[feat_none];
367                 a = f_ptr->x_attr[F_LIT_STANDARD];
368                 c = f_ptr->x_char[F_LIT_STANDARD];
369                 term_queue_char(x - player_ptr->x + Term->wid / 2 - 1, y - player_ptr->y + Term->hgt / 2 - 1, a, c, ta, tc);
370                 continue;
371             }
372
373             map_info(player_ptr, y, x, &a, &c, &ta, &tc);
374
375             if (!use_graphics) {
376                 if (current_world_ptr->timewalk_m_idx)
377                     a = TERM_DARK;
378                 else if (is_invuln(player_ptr) || player_ptr->timewalk)
379                     a = TERM_WHITE;
380                 else if (player_ptr->wraith_form)
381                     a = TERM_L_DARK;
382             }
383
384             term_queue_char(x - player_ptr->x + Term->wid / 2 - 1, y - player_ptr->y + Term->hgt / 2 - 1, a, c, ta, tc);
385         }
386     }
387 }
388
389 /*!
390  * @brief ダンジョンの地形をサブウィンドウに表示する /
391  * Hack -- display dungeon view in sub-windows
392  * @param player_ptr プレーヤーへの参照ポインタ
393  * @return なし
394  */
395 void fix_dungeon(player_type *player_ptr)
396 {
397     for (int j = 0; j < 8; j++) {
398         term_type *old = Term;
399         if (!angband_term[j])
400             continue;
401
402         if (!(window_flag[j] & (PW_DUNGEON)))
403             continue;
404
405         term_activate(angband_term[j]);
406         display_dungeon(player_ptr);
407         term_fresh();
408         term_activate(old);
409     }
410 }
411
412 /*!
413  * @brief モンスターの思い出をサブウィンドウに表示する /
414  * Hack -- display dungeon view in sub-windows
415  * @param player_ptr プレーヤーへの参照ポインタ
416  * @return なし
417  */
418 void fix_monster(player_type *player_ptr)
419 {
420     for (int j = 0; j < 8; j++) {
421         term_type *old = Term;
422         if (!angband_term[j])
423             continue;
424
425         if (!(window_flag[j] & (PW_MONSTER)))
426             continue;
427
428         term_activate(angband_term[j]);
429         if (player_ptr->monster_race_idx)
430             display_roff(player_ptr);
431
432         term_fresh();
433         term_activate(old);
434     }
435 }
436
437 /*!
438  * @brief ベースアイテム情報をサブウィンドウに表示する /
439  * Hack -- display object recall in sub-windows
440  * @param player_ptr プレーヤーへの参照ポインタ
441  * @return なし
442  */
443 void fix_object(player_type *player_ptr)
444 {
445     for (int j = 0; j < 8; j++) {
446         term_type *old = Term;
447         if (!angband_term[j])
448             continue;
449
450         if (!(window_flag[j] & (PW_OBJECT)))
451             continue;
452
453         term_activate(angband_term[j]);
454         if (player_ptr->object_kind_idx)
455             display_koff(player_ptr, player_ptr->object_kind_idx);
456
457         term_fresh();
458         term_activate(old);
459     }
460 }
461
462 /*!
463  * @brief サブウィンドウに所持品、装備品リストの表示を行う /
464  * Flip "inven" and "equip" in any sub-windows
465  * @return なし
466  */
467 void toggle_inventory_equipment(player_type *owner_ptr)
468 {
469     for (int j = 0; j < 8; j++) {
470         if (!angband_term[j])
471             continue;
472
473         if (window_flag[j] & (PW_INVEN)) {
474             window_flag[j] &= ~(PW_INVEN);
475             window_flag[j] |= (PW_EQUIP);
476             owner_ptr->window |= (PW_EQUIP);
477             continue;
478         }
479
480         if (window_flag[j] & PW_EQUIP) {
481             window_flag[j] &= ~(PW_EQUIP);
482             window_flag[j] |= PW_INVEN;
483             owner_ptr->window |= PW_INVEN;
484         }
485     }
486 }