OSDN Git Service

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