OSDN Git Service

9508d4e696eb59a3620c21b3e96367f280a9937f
[hengband/hengband.git] / src / view / display-sub-windows.c
1 #include "view/display-sub-windows.h"
2 #include "floor/floor.h"
3 #include "game-option/option-flags.h"
4 #include "game-option/special-options.h"
5 #include "grid/grid.h"
6 #include "inventory/player-inventory.h"
7 #include "io/input-key-processor.h"
8 #include "io/targeting.h"
9 #include "monster-race/monster-race.h"
10 #include "monster-race/race-flags1.h"
11 #include "monster/monster-flag-types.h"
12 #include "monster/monster-info.h"
13 #include "spell/spells3.h"
14 #include "system/monster-type-definition.h"
15 #include "term/gameterm.h"
16 #include "term/term-color-types.h"
17 #include "view/display-main-window.h" // todo 相互依存している、後で何とかする.
18 #include "view/display-messages.h"
19 #include "view/display-lore.h"
20 #include "view/display-player.h"
21 #include "view/main-window-util.h"
22 #include "view/object-describer.h"
23 #include "world/world.h"
24
25 /*!
26  * @brief サブウィンドウに所持品一覧を表示する / Hack -- display inventory in sub-windows
27  * @param player_ptr プレーヤーへの参照ポインタ
28  * @return なし
29  */
30 void fix_inventory(player_type *player_ptr, tval_type item_tester_tval)
31 {
32     for (int j = 0; j < 8; j++) {
33         term *old = Term;
34         if (!angband_term[j])
35             continue;
36
37         if (!(window_flag[j] & (PW_INVEN)))
38             continue;
39
40         Term_activate(angband_term[j]);
41         display_inventory(player_ptr, item_tester_tval);
42         Term_fresh();
43         Term_activate(old);
44     }
45 }
46
47 /*!
48  * @brief モンスターの現在数を一行で表現する / Print monster info in line
49  * @param x 表示列
50  * @param y 表示行
51  * @param m_ptr 思い出を表示するモンスター情報の参照ポインタ
52  * @param n_same モンスターの数の現在数
53  * @details
54  * <pre>
55  * nnn X LV name
56  *  nnn : number or unique(U) or wanted unique(W)
57  *  X   : symbol of monster
58  *  LV  : monster lv if known
59  *  name: name of monster
60  * @return なし
61  * </pre>
62  */
63 static void print_monster_line(TERM_LEN x, TERM_LEN y, monster_type *m_ptr, int n_same)
64 {
65     char buf[256];
66     MONRACE_IDX r_idx = m_ptr->ap_r_idx;
67     monster_race *r_ptr = &r_info[r_idx];
68
69     Term_gotoxy(x, y);
70     if (!r_ptr)
71         return;
72     if (r_ptr->flags1 & RF1_UNIQUE) {
73         bool is_bounty = FALSE;
74         for (int i = 0; i < MAX_BOUNTY; i++) {
75             if (current_world_ptr->bounty_r_idx[i] == r_idx) {
76                 is_bounty = TRUE;
77                 break;
78             }
79         }
80
81         Term_addstr(-1, TERM_WHITE, is_bounty ? "  W" : "  U");
82     } else {
83         sprintf(buf, "%3d", n_same);
84         Term_addstr(-1, TERM_WHITE, buf);
85     }
86
87     Term_addstr(-1, TERM_WHITE, " ");
88     Term_add_bigch(r_ptr->x_attr, r_ptr->x_char);
89
90     if (r_ptr->r_tkills && !(m_ptr->mflag2 & MFLAG2_KAGE)) {
91         sprintf(buf, " %2d", (int)r_ptr->level);
92     } else {
93         strcpy(buf, " ??");
94     }
95
96     Term_addstr(-1, TERM_WHITE, buf);
97
98     sprintf(buf, " %s ", r_name + r_ptr->name);
99     Term_addstr(-1, TERM_WHITE, buf);
100 }
101
102 /*!
103  * @brief モンスターの出現リストを表示する / Print monster info in line
104  * @param x 表示列
105  * @param y 表示行
106  * @param max_lines 最大何行描画するか
107  */
108 void print_monster_list(floor_type *floor_ptr, TERM_LEN x, TERM_LEN y, TERM_LEN max_lines)
109 {
110     TERM_LEN line = y;
111     monster_type *last_mons = NULL;
112     monster_type *m_ptr = NULL;
113     int n_same = 0;
114     int i;
115     for (i = 0; i < tmp_pos.n; i++) {
116         grid_type *g_ptr = &floor_ptr->grid_array[tmp_pos.y[i]][tmp_pos.x[i]];
117         if (!g_ptr->m_idx || !floor_ptr->m_list[g_ptr->m_idx].ml)
118             continue;
119         m_ptr = &floor_ptr->m_list[g_ptr->m_idx];
120         if (is_pet(m_ptr))
121             continue; // pet
122         if (!m_ptr->r_idx)
123             continue; // dead?
124
125         //ソート済みなので同じモンスターは連続する.これを利用して同じモンスターをカウント,まとめて表示する.
126         //先頭モンスター
127         if (!last_mons) {
128             last_mons = m_ptr;
129             n_same = 1;
130             continue;
131         }
132
133         // same race?
134         if (last_mons->ap_r_idx == m_ptr->ap_r_idx) {
135             n_same++;
136             continue; //表示処理を次に回す
137         }
138
139         // print last mons info
140         print_monster_line(x, line++, last_mons, n_same);
141         n_same = 1;
142         last_mons = m_ptr;
143         if (line - y - 1 == max_lines)
144             break;
145     }
146
147     if (line - y - 1 == max_lines && i != tmp_pos.n) {
148         Term_gotoxy(x, line);
149         Term_addstr(-1, TERM_WHITE, "-- and more --");
150     } else {
151         if (last_mons)
152             print_monster_line(x, line++, last_mons, n_same);
153     }
154 }
155
156 /*!
157  * @brief 出現中モンスターのリストをサブウィンドウに表示する / Hack -- display monster list in sub-windows
158  * @param player_ptr プレーヤーへの参照ポインタ
159  * @return なし
160  */
161 void fix_monster_list(player_type *player_ptr)
162 {
163     for (int j = 0; j < 8; j++) {
164         term *old = Term;
165         if (!angband_term[j])
166             continue;
167         if (!(window_flag[j] & (PW_MONSTER_LIST)))
168             continue;
169
170         Term_activate(angband_term[j]);
171         int w, h;
172         Term_get_size(&w, &h);
173         Term_clear();
174         target_set_prepare_look(player_ptr);
175         print_monster_list(player_ptr->current_floor_ptr, 0, 0, h);
176         Term_fresh();
177         Term_activate(old);
178     }
179 }
180
181 /*!
182  * @brief 現在の装備品をサブウィンドウに表示する /
183  * Hack -- display equipment in sub-windows
184  * @param player_ptr プレーヤーへの参照ポインタ
185  * @return なし
186  */
187 void fix_equip(player_type *player_ptr, tval_type item_tester_tval)
188 {
189     for (int j = 0; j < 8; j++) {
190         term *old = Term;
191         if (!angband_term[j])
192             continue;
193         if (!(window_flag[j] & (PW_EQUIP)))
194             continue;
195
196         Term_activate(angband_term[j]);
197         display_equipment(player_ptr, item_tester_tval);
198         Term_fresh();
199         Term_activate(old);
200     }
201 }
202
203 /*!
204  * @brief 現在の習得済魔法をサブウィンドウに表示する /
205  * @param player_ptr プレーヤーへの参照ポインタ
206  * Hack -- display spells in sub-windows
207  * @return なし
208  */
209 void fix_spell(player_type *player_ptr)
210 {
211     for (int j = 0; j < 8; j++) {
212         term *old = Term;
213         if (!angband_term[j])
214             continue;
215
216         if (!(window_flag[j] & (PW_SPELL)))
217             continue;
218
219         Term_activate(angband_term[j]);
220         display_spell_list(player_ptr);
221         Term_fresh();
222         Term_activate(old);
223     }
224 }
225
226 /*!
227  * @brief 現在のプレイヤーステータスをサブウィンドウに表示する /
228  * @param player_ptr プレーヤーへの参照ポインタ
229  * Hack -- display character in sub-windows
230  * @return なし
231  */
232 void fix_player(player_type *player_ptr)
233 {
234     for (int j = 0; j < 8; j++) {
235         term *old = Term;
236         if (!angband_term[j])
237             continue;
238
239         if (!(window_flag[j] & (PW_PLAYER)))
240             continue;
241
242         Term_activate(angband_term[j]);
243         update_playtime();
244         display_player(player_ptr, 0, map_name);
245         Term_fresh();
246         Term_activate(old);
247     }
248 }
249
250 /*!
251  * @brief ゲームメッセージ履歴をサブウィンドウに表示する /
252  * Hack -- display recent messages in sub-windows
253  * Adjust for width and split messages
254  * @return なし
255  */
256 void fix_message(void)
257 {
258     for (int j = 0; j < 8; j++) {
259         term *old = Term;
260         if (!angband_term[j])
261             continue;
262
263         if (!(window_flag[j] & (PW_MESSAGE)))
264             continue;
265
266         Term_activate(angband_term[j]);
267         TERM_LEN w, h;
268         Term_get_size(&w, &h);
269         for (int i = 0; i < h; i++) {
270             Term_putstr(0, (h - 1) - i, -1, (byte)((i < now_message) ? TERM_WHITE : TERM_SLATE), message_str((s16b)i));
271             TERM_LEN x, y;
272             Term_locate(&x, &y);
273             Term_erase(x, y, 255);
274         }
275
276         Term_fresh();
277         Term_activate(old);
278     }
279 }
280
281 /*!
282  * @brief 簡易マップをサブウィンドウに表示する /
283  * Hack -- display overhead view in sub-windows
284  * Adjust for width and split messages
285  * @param player_ptr プレーヤーへの参照ポインタ
286  * @return なし
287  * @details
288  * Note that the "player" symbol does NOT appear on the map.
289  */
290 void fix_overhead(player_type *player_ptr)
291 {
292     for (int j = 0; j < 8; j++) {
293         term *old = Term;
294         TERM_LEN wid, hgt;
295         if (!angband_term[j])
296             continue;
297
298         if (!(window_flag[j] & (PW_OVERHEAD)))
299             continue;
300
301         Term_activate(angband_term[j]);
302         Term_get_size(&wid, &hgt);
303         if (wid > COL_MAP + 2 && hgt > ROW_MAP + 2) {
304             int cy, cx;
305             display_map(player_ptr, &cy, &cx);
306             Term_fresh();
307         }
308
309         Term_activate(old);
310     }
311 }
312
313 static void display_dungeon(player_type *player_ptr)
314 {
315     TERM_COLOR ta = 0;
316     SYMBOL_CODE tc = '\0';
317
318     for (TERM_LEN x = player_ptr->x - Term->wid / 2 + 1; x <= player_ptr->x + Term->wid / 2; x++) {
319         for (TERM_LEN y = player_ptr->y - Term->hgt / 2 + 1; y <= player_ptr->y + Term->hgt / 2; y++) {
320             TERM_COLOR a;
321             SYMBOL_CODE c;
322             if (!in_bounds2(player_ptr->current_floor_ptr, y, x)) {
323                 feature_type *f_ptr = &f_info[feat_none];
324                 a = f_ptr->x_attr[F_LIT_STANDARD];
325                 c = f_ptr->x_char[F_LIT_STANDARD];
326                 Term_queue_char(x - player_ptr->x + Term->wid / 2 - 1, y - player_ptr->y + Term->hgt / 2 - 1, a, c, ta, tc);
327                 continue;
328             }
329
330             map_info(player_ptr, y, x, &a, &c, &ta, &tc);
331
332             if (!use_graphics) {
333                 if (current_world_ptr->timewalk_m_idx)
334                     a = TERM_DARK;
335                 else if (is_invuln(player_ptr) || player_ptr->timewalk)
336                     a = TERM_WHITE;
337                 else if (player_ptr->wraith_form)
338                     a = TERM_L_DARK;
339             }
340
341             Term_queue_char(x - player_ptr->x + Term->wid / 2 - 1, y - player_ptr->y + Term->hgt / 2 - 1, a, c, ta, tc);
342         }
343     }
344 }
345
346 /*!
347  * @brief ダンジョンの地形をサブウィンドウに表示する /
348  * Hack -- display dungeon view in sub-windows
349  * @param player_ptr プレーヤーへの参照ポインタ
350  * @return なし
351  */
352 void fix_dungeon(player_type *player_ptr)
353 {
354     for (int j = 0; j < 8; j++) {
355         term *old = Term;
356         if (!angband_term[j])
357             continue;
358
359         if (!(window_flag[j] & (PW_DUNGEON)))
360             continue;
361
362         Term_activate(angband_term[j]);
363         display_dungeon(player_ptr);
364         Term_fresh();
365         Term_activate(old);
366     }
367 }
368
369 /*!
370  * @brief モンスターの思い出をサブウィンドウに表示する /
371  * Hack -- display dungeon view in sub-windows
372  * @param player_ptr プレーヤーへの参照ポインタ
373  * @return なし
374  */
375 void fix_monster(player_type *player_ptr)
376 {
377     for (int j = 0; j < 8; j++) {
378         term *old = Term;
379         if (!angband_term[j])
380             continue;
381
382         if (!(window_flag[j] & (PW_MONSTER)))
383             continue;
384
385         Term_activate(angband_term[j]);
386         if (player_ptr->monster_race_idx)
387             display_roff(player_ptr);
388
389         Term_fresh();
390         Term_activate(old);
391     }
392 }
393
394 /*!
395  * @brief ベースアイテム情報をサブウィンドウに表示する /
396  * Hack -- display object recall in sub-windows
397  * @param player_ptr プレーヤーへの参照ポインタ
398  * @return なし
399  */
400 void fix_object(player_type *player_ptr)
401 {
402     for (int j = 0; j < 8; j++) {
403         term *old = Term;
404         if (!angband_term[j])
405             continue;
406
407         if (!(window_flag[j] & (PW_OBJECT)))
408             continue;
409
410         Term_activate(angband_term[j]);
411         if (player_ptr->object_kind_idx)
412             display_koff(player_ptr, player_ptr->object_kind_idx);
413
414         Term_fresh();
415         Term_activate(old);
416     }
417 }