OSDN Git Service

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