OSDN Git Service

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