OSDN Git Service

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