OSDN Git Service

[Refactor] #40014 Separated monster-describer.c/h from monster2.c/h
[hengbandforosx/hengbandosx.git] / src / knowledge / knowledge-features.c
1 /*!
2  * @brief 地形に関する情報を表示する
3  * @date 2020/04/24
4  * @author Hourier
5  */
6
7 #include "knowledge/knowledge-features.h"
8 #include "core/show-file.h"
9 #include "dungeon/dungeon.h"
10 #include "io-dump/dump-util.h"
11 #include "knowledge/lighting-level-table.h"
12 #include "term/term-color-types.h"
13 #include "view/display-main-window.h" // 暫定、後で消す.
14 #include "world/world.h"
15
16  /*
17   * Build a list of feature indexes in the given group. Return the number
18   * of features in the group.
19   *
20   * mode & 0x01 : check for non-empty group
21   */
22 static FEAT_IDX collect_features(FEAT_IDX *feat_idx, BIT_FLAGS8 mode)
23 {
24         FEAT_IDX feat_cnt = 0;
25         for (FEAT_IDX i = 0; i < max_f_idx; i++)
26         {
27                 feature_type *f_ptr = &f_info[i];
28                 if (!f_ptr->name) continue;
29                 if (f_ptr->mimic != i) continue;
30
31                 feat_idx[feat_cnt++] = i;
32                 if (mode & 0x01) break;
33         }
34
35         feat_idx[feat_cnt] = -1;
36         return feat_cnt;
37 }
38
39
40 /*
41  * Display the features in a group.
42  */
43 static void display_feature_list(int col, int row, int per_page, FEAT_IDX *feat_idx,
44         FEAT_IDX feat_cur, FEAT_IDX feat_top, bool visual_only, int lighting_level)
45 {
46         int lit_col[F_LIT_MAX], i;
47         int f_idx_col = use_bigtile ? 62 : 64;
48
49         lit_col[F_LIT_STANDARD] = use_bigtile ? (71 - F_LIT_MAX) : 71;
50         for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
51                 lit_col[i] = lit_col[F_LIT_STANDARD] + 2 + (i - F_LIT_NS_BEGIN) * 2 + (use_bigtile ? i : 0);
52
53         for (i = 0; i < per_page && (feat_idx[feat_top + i] >= 0); i++)
54         {
55                 TERM_COLOR attr;
56                 FEAT_IDX f_idx = feat_idx[feat_top + i];
57                 feature_type *f_ptr = &f_info[f_idx];
58                 int row_i = row + i;
59                 attr = ((i + feat_top == feat_cur) ? TERM_L_BLUE : TERM_WHITE);
60                 c_prt(attr, f_name + f_ptr->name, row_i, col);
61                 if (per_page == 1)
62                 {
63                         c_prt(attr, format("(%s)", lighting_level_str[lighting_level]), row_i, col + 1 + strlen(f_name + f_ptr->name));
64                         c_prt(attr, format("%02x/%02x", f_ptr->x_attr[lighting_level], f_ptr->x_char[lighting_level]), row_i, f_idx_col - ((current_world_ptr->wizard || visual_only) ? 6 : 2));
65                 }
66                 if (current_world_ptr->wizard || visual_only)
67                 {
68                         c_prt(attr, format("%d", f_idx), row_i, f_idx_col);
69                 }
70
71                 Term_queue_bigchar(lit_col[F_LIT_STANDARD], row_i, f_ptr->x_attr[F_LIT_STANDARD], f_ptr->x_char[F_LIT_STANDARD], 0, 0);
72                 Term_putch(lit_col[F_LIT_NS_BEGIN], row_i, TERM_SLATE, '(');
73                 for (int j = F_LIT_NS_BEGIN + 1; j < F_LIT_MAX; j++)
74                 {
75                         Term_putch(lit_col[j], row_i, TERM_SLATE, '/');
76                 }
77
78                 Term_putch(lit_col[F_LIT_MAX - 1] + (use_bigtile ? 3 : 2), row_i, TERM_SLATE, ')');
79                 for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
80                 {
81                         Term_queue_bigchar(lit_col[j] + 1, row_i, f_ptr->x_attr[j], f_ptr->x_char[j], 0, 0);
82                 }
83         }
84
85         for (; i < per_page; i++)
86         {
87                 Term_erase(col, row + i, 255);
88         }
89 }
90
91
92 /*
93  * Interact with feature visuals.
94  */
95 void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, IDX direct_f_idx, IDX *lighting_level)
96 {
97         TERM_COLOR attr_old[F_LIT_MAX];
98         (void)C_WIPE(attr_old, F_LIT_MAX, TERM_COLOR);
99         SYMBOL_CODE char_old[F_LIT_MAX];
100         (void)C_WIPE(char_old, F_LIT_MAX, SYMBOL_CODE);
101
102         TERM_LEN wid, hgt;
103         Term_get_size(&wid, &hgt);
104
105         FEAT_IDX *feat_idx;
106         C_MAKE(feat_idx, max_f_idx, FEAT_IDX);
107
108         concptr feature_group_text[] = { "terrains", NULL };
109         int len;
110         int max = 0;
111         int grp_cnt = 0;
112         int feat_cnt;
113         FEAT_IDX grp_idx[100];
114         TERM_COLOR attr_top = 0;
115         bool visual_list = FALSE;
116         byte char_left = 0;
117         TERM_LEN browser_rows = hgt - 8;
118         if (direct_f_idx < 0)
119         {
120                 for (FEAT_IDX i = 0; feature_group_text[i] != NULL; i++)
121                 {
122                         len = strlen(feature_group_text[i]);
123                         if (len > max) max = len;
124
125                         if (collect_features(feat_idx, 0x01))
126                         {
127                                 grp_idx[grp_cnt++] = i;
128                         }
129                 }
130
131                 feat_cnt = 0;
132         }
133         else
134         {
135                 feature_type *f_ptr = &f_info[direct_f_idx];
136
137                 feat_idx[0] = direct_f_idx;
138                 feat_cnt = 1;
139                 feat_idx[1] = -1;
140
141                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
142                         &attr_top, &char_left, &f_ptr->x_attr[*lighting_level], &f_ptr->x_char[*lighting_level], need_redraw);
143
144                 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
145                 {
146                         attr_old[i] = f_ptr->x_attr[i];
147                         char_old[i] = f_ptr->x_char[i];
148                 }
149         }
150
151         grp_idx[grp_cnt] = -1;
152
153         FEAT_IDX old_grp_cur = -1;
154         FEAT_IDX grp_cur = 0;
155         FEAT_IDX grp_top = 0;
156         FEAT_IDX feat_cur = 0;
157         FEAT_IDX feat_top = 0;
158         TERM_LEN column = 0;
159         bool flag = FALSE;
160         bool redraw = TRUE;
161         TERM_COLOR *cur_attr_ptr;
162         SYMBOL_CODE *cur_char_ptr;
163         while (!flag)
164         {
165                 char ch;
166                 feature_type *f_ptr;
167
168                 if (redraw)
169                 {
170                         clear_from(0);
171
172                         prt(_("表示 - 地形", "Visuals - features"), 2, 0);
173                         if (direct_f_idx < 0) prt(_("グループ", "Group"), 4, 0);
174                         prt(_("名前", "Name"), 4, max + 3);
175                         if (use_bigtile)
176                         {
177                                 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 62);
178                                 prt(_("文字 ( l/ d)", "Sym ( l/ d)"), 4, 66);
179                         }
180                         else
181                         {
182                                 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 64);
183                                 prt(_("文字 (l/d)", "Sym (l/d)"), 4, 68);
184                         }
185
186                         for (FEAT_IDX i = 0; i < 78; i++)
187                         {
188                                 Term_putch(i, 5, TERM_WHITE, '=');
189                         }
190
191                         if (direct_f_idx < 0)
192                         {
193                                 for (FEAT_IDX i = 0; i < browser_rows; i++)
194                                 {
195                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
196                                 }
197                         }
198
199                         redraw = FALSE;
200                 }
201
202                 if (direct_f_idx < 0)
203                 {
204                         if (grp_cur < grp_top) grp_top = grp_cur;
205                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
206
207                         display_group_list(0, 6, max, browser_rows, grp_idx, feature_group_text, grp_cur, grp_top);
208                         if (old_grp_cur != grp_cur)
209                         {
210                                 old_grp_cur = grp_cur;
211                                 feat_cnt = collect_features(feat_idx, 0x00);
212                         }
213
214                         while (feat_cur < feat_top)
215                                 feat_top = MAX(0, feat_top - browser_rows / 2);
216                         while (feat_cur >= feat_top + browser_rows)
217                                 feat_top = MIN(feat_cnt - browser_rows, feat_top + browser_rows / 2);
218                 }
219
220                 if (!visual_list)
221                 {
222                         display_feature_list(max + 3, 6, browser_rows, feat_idx, feat_cur, feat_top, visual_only, F_LIT_STANDARD);
223                 }
224                 else
225                 {
226                         feat_top = feat_cur;
227                         display_feature_list(max + 3, 6, 1, feat_idx, feat_cur, feat_top, visual_only, *lighting_level);
228                         display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
229                 }
230
231                 prt(format(_("<方向>%s, 'd'で標準光源効果%s, ESC", "<dir>%s, 'd' for default lighting%s, ESC"),
232                         visual_list ? _(", ENTERで決定, 'a'で対象明度変更", ", ENTER to accept, 'a' for lighting level") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
233                         (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
234                         hgt - 1, 0);
235
236                 f_ptr = &f_info[feat_idx[feat_cur]];
237                 cur_attr_ptr = &f_ptr->x_attr[*lighting_level];
238                 cur_char_ptr = &f_ptr->x_char[*lighting_level];
239
240                 if (visual_list)
241                 {
242                         place_visual_list_cursor(max + 3, 7, *cur_attr_ptr, *cur_char_ptr, attr_top, char_left);
243                 }
244                 else if (!column)
245                 {
246                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
247                 }
248                 else
249                 {
250                         Term_gotoxy(max + 3, 6 + (feat_cur - feat_top));
251                 }
252
253                 ch = inkey();
254                 if (visual_list && ((ch == 'A') || (ch == 'a')))
255                 {
256                         int prev_lighting_level = *lighting_level;
257
258                         if (ch == 'A')
259                         {
260                                 if (*lighting_level <= 0) *lighting_level = F_LIT_MAX - 1;
261                                 else (*lighting_level)--;
262                         }
263                         else
264                         {
265                                 if (*lighting_level >= F_LIT_MAX - 1) *lighting_level = 0;
266                                 else (*lighting_level)++;
267                         }
268
269                         if (f_ptr->x_attr[prev_lighting_level] != f_ptr->x_attr[*lighting_level])
270                                 attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
271
272                         if (f_ptr->x_char[prev_lighting_level] != f_ptr->x_char[*lighting_level])
273                                 char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
274
275                         continue;
276                 }
277                 else if ((ch == 'D') || (ch == 'd'))
278                 {
279                         TERM_COLOR prev_x_attr = f_ptr->x_attr[*lighting_level];
280                         byte prev_x_char = f_ptr->x_char[*lighting_level];
281
282                         apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
283
284                         if (visual_list)
285                         {
286                                 if (prev_x_attr != f_ptr->x_attr[*lighting_level])
287                                         attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
288
289                                 if (prev_x_char != f_ptr->x_char[*lighting_level])
290                                         char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
291                         }
292                         else *need_redraw = TRUE;
293
294                         continue;
295                 }
296                 else if (visual_mode_command(ch, &visual_list, browser_rows - 1, wid - (max + 3), &attr_top, &char_left, cur_attr_ptr, cur_char_ptr, need_redraw))
297                 {
298                         switch (ch)
299                         {
300                         case ESCAPE:
301                                 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
302                                 {
303                                         f_ptr->x_attr[i] = attr_old[i];
304                                         f_ptr->x_char[i] = char_old[i];
305                                 }
306
307                                 /* Fall through */
308                         case '\n':
309                         case '\r':
310                                 if (direct_f_idx >= 0) flag = TRUE;
311                                 else *lighting_level = F_LIT_STANDARD;
312                                 break;
313                         case 'V':
314                         case 'v':
315                                 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
316                                 {
317                                         attr_old[i] = f_ptr->x_attr[i];
318                                         char_old[i] = f_ptr->x_char[i];
319                                 }
320                                 *lighting_level = F_LIT_STANDARD;
321                                 break;
322
323                         case 'C':
324                         case 'c':
325                                 if (!visual_list)
326                                 {
327                                         for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
328                                         {
329                                                 attr_idx_feat[i] = f_ptr->x_attr[i];
330                                                 char_idx_feat[i] = f_ptr->x_char[i];
331                                         }
332                                 }
333                                 break;
334
335                         case 'P':
336                         case 'p':
337                                 if (!visual_list)
338                                 {
339                                         for (FEAT_IDX i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
340                                         {
341                                                 if (attr_idx_feat[i] || (!(char_idx_feat[i] & 0x80) && char_idx_feat[i])) f_ptr->x_attr[i] = attr_idx_feat[i];
342                                                 if (char_idx_feat[i]) f_ptr->x_char[i] = char_idx_feat[i];
343                                         }
344                                 }
345                                 break;
346                         }
347                         continue;
348                 }
349
350                 switch (ch)
351                 {
352                 case ESCAPE:
353                 {
354                         flag = TRUE;
355                         break;
356                 }
357
358                 default:
359                 {
360                         browser_cursor(ch, &column, &grp_cur, grp_cnt, &feat_cur, feat_cnt);
361                         break;
362                 }
363                 }
364         }
365
366         C_KILL(feat_idx, max_f_idx, FEAT_IDX);
367 }
368
369
370 /*
371  * Dungeon
372  */
373 void do_cmd_knowledge_dungeon(player_type *creature_ptr)
374 {
375         FILE *fff = NULL;
376         GAME_TEXT file_name[FILE_NAME_SIZE];
377         if (!open_temporary_file(&fff, file_name)) return;
378
379         for (int i = 1; i < current_world_ptr->max_d_idx; i++)
380         {
381                 bool seiha = FALSE;
382
383                 if (!d_info[i].maxdepth) continue;
384                 if (!max_dlv[i]) continue;
385                 if (d_info[i].final_guardian)
386                 {
387                         if (!r_info[d_info[i].final_guardian].max_num) seiha = TRUE;
388                 }
389                 else if (max_dlv[i] == d_info[i].maxdepth) seiha = TRUE;
390
391                 fprintf(fff, _("%c%-12s :  %3d 階\n", "%c%-16s :  level %3d\n"), seiha ? '!' : ' ', d_name + d_info[i].name, (int)max_dlv[i]);
392         }
393
394         my_fclose(fff);
395         (void)show_file(creature_ptr, TRUE, file_name, _("今までに入ったダンジョン", "Dungeon"), 0, 0);
396         fd_kill(file_name);
397 }