OSDN Git Service

[Refactor] #38862 Moved view-mainwindow.c/h to display-main-window.c/h
[hengband/hengband.git] / src / knowledge / knowledge-items.c
1 /*!
2  * @brief 既知のアイテムとアーティファクトを表示する
3  * @date 2020/04/23
4  * @author Hourier
5  */
6
7 #include "angband.h"
8 #include "knowledge-items.h"
9 #include "cmd/dump-util.h"
10 #include "artifact.h"
11 #include "sort.h"
12 #include "object-flavor.h"
13 #include "object-hook.h"
14 #include "object/object-kind.h"
15 #include "core/show-file.h"
16 #include "cmd/object-group-table.h"
17 #include "world.h"
18 #include "gameterm.h"
19 #include "core.h" // 暫定、後で消す.
20 #include "view/display-main-window.h" // 暫定、後で消す.
21
22 /*
23  * todo okay = 既知のアーティファクト? と思われるが確証がない
24  * 分かりやすい変数名へ変更求む&万が一未知である旨の配列なら負論理なのでゴソッと差し替えるべき
25  * Check the status of "artifacts"
26  * @param player_ptr プレーヤーへの参照ポインタ
27  * @return なし
28  */
29 void do_cmd_knowledge_artifacts(player_type *player_ptr)
30 {
31         FILE *fff = NULL;
32         GAME_TEXT file_name[FILE_NAME_SIZE];
33         if (!open_temporary_file(&fff, file_name)) return;
34
35         ARTIFACT_IDX *who;
36         C_MAKE(who, max_a_idx, ARTIFACT_IDX);
37         bool *okay;
38         C_MAKE(okay, max_a_idx, bool);
39
40         for (ARTIFACT_IDX k = 0; k < max_a_idx; k++)
41         {
42                 artifact_type *a_ptr = &a_info[k];
43                 okay[k] = FALSE;
44                 if (!a_ptr->name) continue;
45                 if (!a_ptr->cur_num) continue;
46
47                 okay[k] = TRUE;
48         }
49
50         for (POSITION y = 0; y < player_ptr->current_floor_ptr->height; y++)
51         {
52                 for (POSITION x = 0; x < player_ptr->current_floor_ptr->width; x++)
53                 {
54                         grid_type *g_ptr = &player_ptr->current_floor_ptr->grid_array[y][x];
55                         OBJECT_IDX this_o_idx, next_o_idx = 0;
56                         for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
57                         {
58                                 object_type *o_ptr;
59                                 o_ptr = &player_ptr->current_floor_ptr->o_list[this_o_idx];
60                                 next_o_idx = o_ptr->next_o_idx;
61                                 if (!object_is_fixed_artifact(o_ptr)) continue;
62                                 if (object_is_known(o_ptr)) continue;
63
64                                 okay[o_ptr->name1] = FALSE;
65                         }
66                 }
67         }
68
69         for (ARTIFACT_IDX i = 0; i < INVEN_TOTAL; i++)
70         {
71                 object_type *o_ptr = &player_ptr->inventory_list[i];
72                 if (!o_ptr->k_idx) continue;
73                 if (!object_is_fixed_artifact(o_ptr)) continue;
74                 if (object_is_known(o_ptr)) continue;
75
76                 okay[o_ptr->name1] = FALSE;
77         }
78
79         int n = 0;
80         for (ARTIFACT_IDX k = 0; k < max_a_idx; k++)
81         {
82                 if (okay[k]) who[n++] = k;
83         }
84
85         u16b why = 3;
86         ang_sort(who, &why, n, ang_sort_art_comp, ang_sort_art_swap);
87         for (ARTIFACT_IDX k = 0; k < n; k++)
88         {
89                 artifact_type *a_ptr = &a_info[who[k]];
90                 GAME_TEXT base_name[MAX_NLEN];
91                 strcpy(base_name, _("未知の伝説のアイテム", "Unknown Artifact"));
92                 ARTIFACT_IDX z = lookup_kind(a_ptr->tval, a_ptr->sval);
93                 if (z)
94                 {
95                         object_type forge;
96                         object_type *q_ptr;
97                         q_ptr = &forge;
98                         object_prep(q_ptr, z);
99                         q_ptr->name1 = (byte)who[k];
100                         q_ptr->ident |= IDENT_STORE;
101                         object_desc(player_ptr, base_name, q_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
102                 }
103
104                 fprintf(fff, _("     %s\n", "     The %s\n"), base_name);
105         }
106
107         C_KILL(who, max_a_idx, ARTIFACT_IDX);
108         C_KILL(okay, max_a_idx, bool);
109         my_fclose(fff);
110         (void)show_file(player_ptr, TRUE, file_name, _("既知の伝説のアイテム", "Artifacts Seen"), 0, 0);
111         fd_kill(file_name);
112 }
113
114
115 /*
116  * Build a list of object indexes in the given group. Return the number
117  * of objects in the group.
118  *
119  * mode & 0x01 : check for non-empty group
120  * mode & 0x02 : visual operation only
121  */
122 static KIND_OBJECT_IDX collect_objects(int grp_cur, KIND_OBJECT_IDX object_idx[], BIT_FLAGS8 mode)
123 {
124         KIND_OBJECT_IDX object_cnt = 0;
125         byte group_tval = object_group_tval[grp_cur];
126         for (KIND_OBJECT_IDX i = 0; i < max_k_idx; i++)
127         {
128                 object_kind *k_ptr = &k_info[i];
129                 if (!k_ptr->name) continue;
130
131                 if (!(mode & 0x02))
132                 {
133                         if (!current_world_ptr->wizard)
134                         {
135                                 if (!k_ptr->flavor) continue;
136                                 if (!k_ptr->aware) continue;
137                         }
138
139                         int k = 0;
140                         for (int j = 0; j < 4; j++)
141                                 k += k_ptr->chance[j];
142                         if (!k) continue;
143                 }
144
145                 if (TV_LIFE_BOOK == group_tval)
146                 {
147                         if (TV_LIFE_BOOK <= k_ptr->tval && k_ptr->tval <= TV_HEX_BOOK)
148                         {
149                                 object_idx[object_cnt++] = i;
150                         }
151                         else
152                                 continue;
153                 }
154                 else if (k_ptr->tval == group_tval)
155                 {
156                         object_idx[object_cnt++] = i;
157                 }
158                 else
159                         continue;
160
161                 if (mode & 0x01) break;
162         }
163
164         object_idx[object_cnt] = -1;
165         return object_cnt;
166 }
167
168
169 /*
170  * Display the objects in a group.
171  */
172 static void display_object_list(int col, int row, int per_page, IDX object_idx[],
173         int object_cur, int object_top, bool visual_only)
174 {
175         int i;
176         for (i = 0; i < per_page && (object_idx[object_top + i] >= 0); i++)
177         {
178                 GAME_TEXT o_name[MAX_NLEN];
179                 TERM_COLOR a;
180                 SYMBOL_CODE c;
181                 object_kind *flavor_k_ptr;
182                 KIND_OBJECT_IDX k_idx = object_idx[object_top + i];
183                 object_kind *k_ptr = &k_info[k_idx];
184                 TERM_COLOR attr = ((k_ptr->aware || visual_only) ? TERM_WHITE : TERM_SLATE);
185                 byte cursor = ((k_ptr->aware || visual_only) ? TERM_L_BLUE : TERM_BLUE);
186                 if (!visual_only && k_ptr->flavor)
187                 {
188                         flavor_k_ptr = &k_info[k_ptr->flavor];
189                 }
190                 else
191                 {
192                         flavor_k_ptr = k_ptr;
193                 }
194
195                 attr = ((i + object_top == object_cur) ? cursor : attr);
196                 if (!k_ptr->flavor || (!visual_only && k_ptr->aware))
197                 {
198                         strip_name(o_name, k_idx);
199                 }
200                 else
201                 {
202                         strcpy(o_name, k_name + flavor_k_ptr->flavor_name);
203                 }
204
205                 c_prt(attr, o_name, row + i, col);
206                 if (per_page == 1)
207                 {
208                         c_prt(attr, format("%02x/%02x", flavor_k_ptr->x_attr, flavor_k_ptr->x_char), row + i, (current_world_ptr->wizard || visual_only) ? 64 : 68);
209                 }
210
211                 if (current_world_ptr->wizard || visual_only)
212                 {
213                         c_prt(attr, format("%d", k_idx), row + i, 70);
214                 }
215
216                 a = flavor_k_ptr->x_attr;
217                 c = flavor_k_ptr->x_char;
218
219                 Term_queue_bigchar(use_bigtile ? 76 : 77, row + i, a, c, 0, 0);
220         }
221
222         for (; i < per_page; i++)
223         {
224                 Term_erase(col, row + i, 255);
225         }
226 }
227
228
229 /*
230  * Describe fake object
231  */
232 static void desc_obj_fake(player_type *creature_ptr, KIND_OBJECT_IDX k_idx)
233 {
234         object_type *o_ptr;
235         object_type object_type_body;
236         o_ptr = &object_type_body;
237         object_wipe(o_ptr);
238         object_prep(o_ptr, k_idx);
239
240         o_ptr->ident |= IDENT_KNOWN;
241         handle_stuff(creature_ptr);
242
243         if (screen_object(creature_ptr, o_ptr, SCROBJ_FAKE_OBJECT | SCROBJ_FORCE_DETAIL)) return;
244
245         msg_print(_("特に変わったところはないようだ。", "You see nothing special."));
246         msg_print(NULL);
247 }
248
249
250 /*
251  * Display known objects
252  */
253 void do_cmd_knowledge_objects(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_k_idx)
254 {
255         IDX object_old, object_top;
256         IDX grp_idx[100];
257         int object_cnt;
258         OBJECT_IDX *object_idx;
259
260         bool visual_list = FALSE;
261         TERM_COLOR attr_top = 0;
262         byte char_left = 0;
263         byte mode;
264
265         TERM_LEN wid, hgt;
266         Term_get_size(&wid, &hgt);
267
268         int browser_rows = hgt - 8;
269         C_MAKE(object_idx, max_k_idx, KIND_OBJECT_IDX);
270
271         int len;
272         int max = 0;
273         int grp_cnt = 0;
274         if (direct_k_idx < 0)
275         {
276                 mode = visual_only ? 0x03 : 0x01;
277                 for (IDX i = 0; object_group_text[i] != NULL; i++)
278                 {
279                         len = strlen(object_group_text[i]);
280                         if (len > max) max = len;
281
282                         if (collect_objects(i, object_idx, mode))
283                         {
284                                 grp_idx[grp_cnt++] = i;
285                         }
286                 }
287
288                 object_old = -1;
289                 object_cnt = 0;
290         }
291         else
292         {
293                 object_kind *k_ptr = &k_info[direct_k_idx];
294                 object_kind *flavor_k_ptr;
295
296                 if (!visual_only && k_ptr->flavor)
297                 {
298                         flavor_k_ptr = &k_info[k_ptr->flavor];
299                 }
300                 else
301                 {
302                         flavor_k_ptr = k_ptr;
303                 }
304
305                 object_idx[0] = direct_k_idx;
306                 object_old = direct_k_idx;
307                 object_cnt = 1;
308                 object_idx[1] = -1;
309                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
310                         &attr_top, &char_left, &flavor_k_ptr->x_attr, &flavor_k_ptr->x_char, need_redraw);
311         }
312
313         grp_idx[grp_cnt] = -1;
314         mode = visual_only ? 0x02 : 0x00;
315         IDX old_grp_cur = -1;
316         IDX grp_cur = 0;
317         IDX grp_top = 0;
318         IDX object_cur = object_top = 0;
319         bool flag = FALSE;
320         bool redraw = TRUE;
321         int column = 0;
322         while (!flag)
323         {
324                 object_kind *k_ptr, *flavor_k_ptr;
325
326                 if (redraw)
327                 {
328                         clear_from(0);
329
330 #ifdef JP
331                         prt(format("%s - アイテム", !visual_only ? "知識" : "表示"), 2, 0);
332                         if (direct_k_idx < 0) prt("グループ", 4, 0);
333                         prt("名前", 4, max + 3);
334                         if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 70);
335                         prt("文字", 4, 74);
336 #else
337                         prt(format("%s - objects", !visual_only ? "Knowledge" : "Visuals"), 2, 0);
338                         if (direct_k_idx < 0) prt("Group", 4, 0);
339                         prt("Name", 4, max + 3);
340                         if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 70);
341                         prt("Sym", 4, 75);
342 #endif
343
344                         for (IDX i = 0; i < 78; i++)
345                         {
346                                 Term_putch(i, 5, TERM_WHITE, '=');
347                         }
348
349                         if (direct_k_idx < 0)
350                         {
351                                 for (IDX i = 0; i < browser_rows; i++)
352                                 {
353                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
354                                 }
355                         }
356
357                         redraw = FALSE;
358                 }
359
360                 if (direct_k_idx < 0)
361                 {
362                         if (grp_cur < grp_top) grp_top = grp_cur;
363                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
364
365                         display_group_list(0, 6, max, browser_rows, grp_idx, object_group_text, grp_cur, grp_top);
366                         if (old_grp_cur != grp_cur)
367                         {
368                                 old_grp_cur = grp_cur;
369                                 object_cnt = collect_objects(grp_idx[grp_cur], object_idx, mode);
370                         }
371
372                         while (object_cur < object_top)
373                                 object_top = MAX(0, object_top - browser_rows / 2);
374                         while (object_cur >= object_top + browser_rows)
375                                 object_top = MIN(object_cnt - browser_rows, object_top + browser_rows / 2);
376                 }
377
378                 if (!visual_list)
379                 {
380                         display_object_list(max + 3, 6, browser_rows, object_idx, object_cur, object_top, visual_only);
381                 }
382                 else
383                 {
384                         object_top = object_cur;
385                         display_object_list(max + 3, 6, 1, object_idx, object_cur, object_top, visual_only);
386                         display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
387                 }
388
389                 k_ptr = &k_info[object_idx[object_cur]];
390
391                 if (!visual_only && k_ptr->flavor)
392                 {
393                         flavor_k_ptr = &k_info[k_ptr->flavor];
394                 }
395                 else
396                 {
397                         flavor_k_ptr = k_ptr;
398                 }
399
400 #ifdef JP
401                 prt(format("<方向>%s%s%s, ESC",
402                         (!visual_list && !visual_only) ? ", 'r'で詳細を見る" : "",
403                         visual_list ? ", ENTERで決定" : ", 'v'でシンボル変更",
404                         (attr_idx || char_idx) ? ", 'c', 'p'でペースト" : ", 'c'でコピー"),
405                         hgt - 1, 0);
406 #else
407                 prt(format("<dir>%s%s%s, ESC",
408                         (!visual_list && !visual_only) ? ", 'r' to recall" : "",
409                         visual_list ? ", ENTER to accept" : ", 'v' for visuals",
410                         (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"),
411                         hgt - 1, 0);
412 #endif
413
414                 if (!visual_only)
415                 {
416                         if (object_cnt) object_kind_track(creature_ptr, object_idx[object_cur]);
417
418                         if (object_old != object_idx[object_cur])
419                         {
420                                 handle_stuff(creature_ptr);
421                                 object_old = object_idx[object_cur];
422                         }
423                 }
424
425                 if (visual_list)
426                 {
427                         place_visual_list_cursor(max + 3, 7, flavor_k_ptr->x_attr, flavor_k_ptr->x_char, attr_top, char_left);
428                 }
429                 else if (!column)
430                 {
431                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
432                 }
433                 else
434                 {
435                         Term_gotoxy(max + 3, 6 + (object_cur - object_top));
436                 }
437
438                 char ch = inkey();
439                 if (visual_mode_command(ch, &visual_list, browser_rows - 1, wid - (max + 3), &attr_top, &char_left, &flavor_k_ptr->x_attr, &flavor_k_ptr->x_char, need_redraw))
440                 {
441                         if (direct_k_idx >= 0)
442                         {
443                                 switch (ch)
444                                 {
445                                 case '\n':
446                                 case '\r':
447                                 case ESCAPE:
448                                         flag = TRUE;
449                                         break;
450                                 }
451                         }
452                         continue;
453                 }
454
455                 switch (ch)
456                 {
457                 case ESCAPE:
458                 {
459                         flag = TRUE;
460                         break;
461                 }
462
463                 case 'R':
464                 case 'r':
465                 {
466                         if (!visual_list && !visual_only && (grp_cnt > 0))
467                         {
468                                 desc_obj_fake(creature_ptr, object_idx[object_cur]);
469                                 redraw = TRUE;
470                         }
471
472                         break;
473                 }
474
475                 default:
476                 {
477                         browser_cursor(ch, &column, &grp_cur, grp_cnt, &object_cur, object_cnt);
478                         break;
479                 }
480                 }
481         }
482
483         C_KILL(object_idx, max_k_idx, KIND_OBJECT_IDX);
484 }