OSDN Git Service

[Refactor] #39962 process_pref_file_command() の整形 / Reshaped process_pref_file_command()
[hengband/hengband.git] / src / files.c
1 /*!
2  * @file files.c
3  * @brief ファイル入出力管理 / Purpose: code dealing with files (and death)
4  * @date 2014/01/28
5  * @author
6  * <pre>
7  * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
8  * This software may be copied and distributed for educational, research,
9  * and not for profit purposes provided that this copyright and statement
10  * are included in all such copies.  Other copyrights may also apply.
11  * 2014 Deskull rearranged comment for Doxygen.\n
12  * </pre>
13  */
14
15 #include "angband.h"
16 #include "term.h"
17 #include "signal-handlers.h"
18 #include "view/display-util.h"
19 #include "view/status-first-page.h"
20 #include "uid-checker.h"
21 #include "util.h"
22 #include "files.h"
23 #include "core.h"
24
25 #include "birth.h"
26 #include "files.h"
27
28 #include "bldg.h"
29
30 #include "cmd-magiceat.h"
31 #include "cmd-dump.h"
32 #include "world.h"
33 #include "player-inventory.h"
34 #include "player-move.h"
35 #include "player-skill.h"
36 #include "player-personality.h"
37 #include "player-sex.h"
38 #include "player-effects.h"
39 #include "sort.h"
40 #include "mutation.h"
41 #include "quest.h"
42 #include "store.h"
43 #include "avatar.h"
44 #include "shoot.h"
45 #include "patron.h"
46 #include "monster-status.h"
47 #include "object-flavor.h"
48 #include "object-hook.h"
49 #include "realm-hex.h"
50 #include "cmd-pet.h"
51 #include "view-mainwindow.h"
52 #include "floor-town.h"
53 #include "dungeon-file.h"
54 #include "init.h"
55 #include "monster-spell.h"
56 #include "dungeon.h"
57 #include "objectkind.h"
58 #include "autopick.h"
59 #include "save.h"
60 #include "realm-song.h"
61
62 #define PREF_TYPE_NORMAL   0
63 #define PREF_TYPE_AUTOPICK 1
64 #define PREF_TYPE_HISTPREF 2
65
66  /* Mode flags for displaying player flags */
67 #define DP_CURSE   0x01
68 #define DP_IMM     0x02
69 #define DP_WP      0x08
70
71 concptr ANGBAND_DIR; //!< Path name: The main "lib" directory This variable is not actually used anywhere in the code
72 concptr ANGBAND_DIR_APEX; //!< High score files (binary) These files may be portable between platforms
73 concptr ANGBAND_DIR_BONE; //!< Bone files for player ghosts (ascii) These files are portable between platforms
74 concptr ANGBAND_DIR_DATA; //!< Binary image files for the "*_info" arrays (binary) These files are not portable between platforms
75 concptr ANGBAND_DIR_EDIT; //!< Textual template files for the "*_info" arrays (ascii) These files are portable between platforms
76 concptr ANGBAND_DIR_SCRIPT; //!< Script files These files are portable between platforms.
77 concptr ANGBAND_DIR_FILE; //!< Various extra files (ascii) These files may be portable between platforms
78 concptr ANGBAND_DIR_HELP; //!< Help files (normal) for the online help (ascii) These files are portable between platforms
79 concptr ANGBAND_DIR_INFO; //!< Help files (spoilers) for the online help (ascii) These files are portable between platforms
80 concptr ANGBAND_DIR_PREF; //!< Default user "preference" files (ascii) These files are rarely portable between platforms
81 concptr ANGBAND_DIR_SAVE; //!< Savefiles for current characters (binary)
82 concptr ANGBAND_DIR_USER; //!< User "preference" files (ascii) These files are rarely portable between platforms
83 concptr ANGBAND_DIR_XTRA; //!< Various extra files (binary) These files are rarely portable between platforms
84
85 /*
86  * Buffer to hold the current savefile name
87  * 'savefile' holds full path name. 'savefile_base' holds only base name.
88  */
89 char savefile[1024];
90 char savefile_base[40];
91
92 /*!
93  * @brief 各種データテキストをトークン単位に分解する / Extract the first few "tokens" from a buffer
94  * @param buf データテキストの参照ポインタ
95  * @param num トークンの数
96  * @param tokens トークンを保管する文字列参照ポインタ配列
97  * @param mode オプション
98  * @return 解釈した文字列数
99  * @details
100  * <pre>
101  * This function uses "colon" and "slash" as the delimeter characters.
102  * We never extract more than "num" tokens.  The "last" token may include
103  * "delimeter" characters, allowing the buffer to include a "string" token.
104  * We save pointers to the tokens in "tokens", and return the number found.
105  * Hack -- Attempt to handle the 'c' character formalism
106  * Hack -- An empty buffer, or a final delimeter, yields an "empty" token.
107  * Hack -- We will always extract at least one token
108  * </pre>
109  */
110 s16b tokenize(char *buf, s16b num, char **tokens, BIT_FLAGS mode)
111 {
112         s16b i = 0;
113         char *s = buf;
114         while (i < num - 1)
115         {
116                 char *t;
117                 for (t = s; *t; t++)
118                 {
119                         if ((*t == ':') || (*t == '/')) break;
120
121                         if ((mode & TOKENIZE_CHECKQUOTE) && (*t == '\''))
122                         {
123                                 t++;
124                                 if (*t == '\\') t++;
125                                 if (!*t) break;
126
127                                 t++;
128                                 if (*t != '\'') *t = '\'';
129                         }
130
131                         if (*t == '\\') t++;
132                 }
133
134                 if (!*t) break;
135
136                 *t++ = '\0';
137                 tokens[i++] = s;
138                 s = t;
139         }
140
141         tokens[i++] = s;
142         return i;
143 }
144
145 /* A number with a name */
146 typedef struct named_num named_num;
147
148 struct named_num
149 {
150         concptr name;           /* The name of this thing */
151         int num;                        /* A number associated with it */
152 };
153
154 /* Index of spell type names */
155 static named_num gf_desc[] =
156 {
157         {"GF_ELEC",                             GF_ELEC                         },
158         {"GF_POIS",                             GF_POIS                         },
159         {"GF_ACID",                             GF_ACID                         },
160         {"GF_COLD",                             GF_COLD                         },
161         {"GF_FIRE",                                     GF_FIRE                         },
162         {"GF_PSY_SPEAR",                        GF_PSY_SPEAR            },
163         {"GF_MISSILE",                          GF_MISSILE                      },
164         {"GF_ARROW",                            GF_ARROW                        },
165         {"GF_PLASMA",                           GF_PLASMA                       },
166         {"GF_WATER",                            GF_WATER                        },
167         {"GF_LITE",                                     GF_LITE                         },
168         {"GF_DARK",                                     GF_DARK                         },
169         {"GF_LITE_WEAK",                        GF_LITE_WEAK            },
170         {"GF_DARK_WEAK",                        GF_DARK_WEAK            },
171         {"GF_SHARDS",                           GF_SHARDS                       },
172         {"GF_SOUND",                            GF_SOUND                        },
173         {"GF_CONFUSION",                        GF_CONFUSION            },
174         {"GF_FORCE",                            GF_FORCE                        },
175         {"GF_INERTIA",                          GF_INERTIAL                     },
176         {"GF_MANA",                                     GF_MANA                         },
177         {"GF_METEOR",                           GF_METEOR                       },
178         {"GF_ICE",                                      GF_ICE                          },
179         {"GF_CHAOS",                            GF_CHAOS                        },
180         {"GF_NETHER",                           GF_NETHER                       },
181         {"GF_DISENCHANT",                       GF_DISENCHANT           },
182         {"GF_NEXUS",                            GF_NEXUS                        },
183         {"GF_TIME",                                     GF_TIME                         },
184         {"GF_GRAVITY",                          GF_GRAVITY                      },
185         {"GF_KILL_WALL",                        GF_KILL_WALL            },
186         {"GF_KILL_DOOR",                        GF_KILL_DOOR            },
187         {"GF_KILL_TRAP",                        GF_KILL_TRAP            },
188         {"GF_MAKE_WALL",                        GF_MAKE_WALL            },
189         {"GF_MAKE_DOOR",                        GF_MAKE_DOOR            },
190         {"GF_MAKE_TRAP",                        GF_MAKE_TRAP            },
191         {"GF_MAKE_TREE",                        GF_MAKE_TREE            },
192         {"GF_OLD_CLONE",                        GF_OLD_CLONE            },
193         {"GF_OLD_POLY",                         GF_OLD_POLY                     },
194         {"GF_OLD_HEAL",                         GF_OLD_HEAL                     },
195         {"GF_OLD_SPEED",                        GF_OLD_SPEED            },
196         {"GF_OLD_SLOW",                         GF_OLD_SLOW                     },
197         {"GF_OLD_CONF",                         GF_OLD_CONF                     },
198         {"GF_OLD_SLEEP",                        GF_OLD_SLEEP            },
199         {"GF_HYPODYNAMIA",                      GF_HYPODYNAMIA          },
200         {"GF_AWAY_UNDEAD",                      GF_AWAY_UNDEAD          },
201         {"GF_AWAY_EVIL",                        GF_AWAY_EVIL            },
202         {"GF_AWAY_ALL",                         GF_AWAY_ALL                     },
203         {"GF_TURN_UNDEAD",                      GF_TURN_UNDEAD          },
204         {"GF_TURN_EVIL",                        GF_TURN_EVIL            },
205         {"GF_TURN_ALL",                         GF_TURN_ALL                     },
206         {"GF_DISP_UNDEAD",                      GF_DISP_UNDEAD          },
207         {"GF_DISP_EVIL",                        GF_DISP_EVIL            },
208         {"GF_DISP_ALL",                         GF_DISP_ALL                     },
209         {"GF_DISP_DEMON",                       GF_DISP_DEMON           },
210         {"GF_DISP_LIVING",                      GF_DISP_LIVING          },
211         {"GF_ROCKET",                           GF_ROCKET                       },
212         {"GF_NUKE",                                     GF_NUKE                         },
213         {"GF_MAKE_GLYPH",                       GF_MAKE_GLYPH           },
214         {"GF_STASIS",                           GF_STASIS                       },
215         {"GF_STONE_WALL",                       GF_STONE_WALL           },
216         {"GF_DEATH_RAY",                        GF_DEATH_RAY            },
217         {"GF_STUN",                                     GF_STUN                         },
218         {"GF_HOLY_FIRE",                        GF_HOLY_FIRE            },
219         {"GF_HELL_FIRE",                        GF_HELL_FIRE            },
220         {"GF_DISINTEGRATE",                     GF_DISINTEGRATE         },
221         {"GF_CHARM",                            GF_CHARM                        },
222         {"GF_CONTROL_UNDEAD",           GF_CONTROL_UNDEAD       },
223         {"GF_CONTROL_ANIMAL",           GF_CONTROL_ANIMAL       },
224         {"GF_PSI",                                      GF_PSI                          },
225         {"GF_PSI_DRAIN",                        GF_PSI_DRAIN            },
226         {"GF_TELEKINESIS",                      GF_TELEKINESIS          },
227         {"GF_JAM_DOOR",                         GF_JAM_DOOR                     },
228         {"GF_DOMINATION",                       GF_DOMINATION           },
229         {"GF_DISP_GOOD",                        GF_DISP_GOOD            },
230         {"GF_DRAIN_MANA",                       GF_DRAIN_MANA           },
231         {"GF_MIND_BLAST",                       GF_MIND_BLAST           },
232         {"GF_BRAIN_SMASH",                      GF_BRAIN_SMASH          },
233         {"GF_CAUSE_1",                          GF_CAUSE_1                      },
234         {"GF_CAUSE_2",                          GF_CAUSE_2                      },
235         {"GF_CAUSE_3",                          GF_CAUSE_3                      },
236         {"GF_CAUSE_4",                          GF_CAUSE_4                      },
237         {"GF_HAND_DOOM",                        GF_HAND_DOOM            },
238         {"GF_CAPTURE",                          GF_CAPTURE                      },
239         {"GF_ANIM_DEAD",                        GF_ANIM_DEAD            },
240         {"GF_CHARM_LIVING",                     GF_CHARM_LIVING         },
241         {"GF_IDENTIFY",                         GF_IDENTIFY                     },
242         {"GF_ATTACK",                           GF_ATTACK                       },
243         {"GF_ENGETSU",                          GF_ENGETSU                      },
244         {"GF_GENOCIDE",                         GF_GENOCIDE                     },
245         {"GF_PHOTO",                            GF_PHOTO                        },
246         {"GF_CONTROL_DEMON",            GF_CONTROL_DEMON        },
247         {"GF_LAVA_FLOW",                        GF_LAVA_FLOW            },
248         {"GF_BLOOD_CURSE",                      GF_BLOOD_CURSE          },
249         {"GF_SEEKER",                           GF_SEEKER                       },
250         {"GF_SUPER_RAY",                        GF_SUPER_RAY            },
251         {"GF_STAR_HEAL",                        GF_STAR_HEAL            },
252         {"GF_WATER_FLOW",                       GF_WATER_FLOW           },
253         {"GF_CRUSADE",                          GF_CRUSADE                      },
254         {"GF_STASIS_EVIL",                      GF_STASIS_EVIL          },
255         {"GF_WOUNDS",                           GF_WOUNDS                       },
256         {NULL,                                          0                                       }
257 };
258
259
260 /*!
261  * @brief 設定ファイルの各行から各種テキスト情報を取得する /
262  * Parse a sub-file of the "extra info" (format shown below)
263  * @param creature_ptr プレーヤーへの参照ポインタ
264  * @param buf データテキストの参照ポインタ
265  * @return エラーコード
266  * @details
267  * <pre>
268  * Each "action" line has an "action symbol" in the first column,
269  * followed by a colon, followed by some command specific info,
270  * usually in the form of "tokens" separated by colons or slashes.
271  * Blank lines, lines starting with white space, and lines starting
272  * with pound signs ("#") are ignored (as comments).
273  * Note the use of "tokenize()" to allow the use of both colons and
274  * slashes as delimeters, while still allowing final tokens which
275  * may contain any characters including "delimiters".
276  * Note the use of "strtol()" to allow all "integers" to be encoded
277  * in decimal, hexidecimal, or octal form.
278  * Note that "monster zero" is used for the "player" attr/char, "object
279  * zero" will be used for the "stack" attr/char, and "feature zero" is
280  * used for the "nothing" attr/char.
281  * Parse another file recursively, see below for details
282  *   %:\<filename\>
283  * Specify the attr/char values for "monsters" by race index
284  *   R:\<num\>:\<a\>:\<c\>
285  * Specify the attr/char values for "objects" by kind index
286  *   K:\<num\>:\<a\>:\<c\>
287  * Specify the attr/char values for "features" by feature index
288  *   F:\<num\>:\<a\>:\<c\>
289  * Specify the attr/char values for unaware "objects" by kind tval
290  *   U:\<tv\>:\<a\>:\<c\>
291  * Specify the attr/char values for inventory "objects" by kind tval
292  *   E:\<tv\>:\<a\>:\<c\>
293  * Define a macro action, given an encoded macro action
294  *   A:\<str\>
295  * Create a normal macro, given an encoded macro trigger
296  *   P:\<str\>
297  * Create a command macro, given an encoded macro trigger
298  *   C:\<str\>
299  * Create a keyset mapping
300  *   S:\<key\>:\<key\>:\<dir\>
301  * Turn an option off, given its name
302  *   X:\<str\>
303  * Turn an option on, given its name
304  *   Y:\<str\>
305  * Specify visual information, given an index, and some data
306  *   V:\<num\>:\<kv\>:\<rv\>:\<gv\>:\<bv\>
307  * Specify the set of colors to use when drawing a zapped spell
308  *   Z:\<type\>:\<str\>
309  * Specify a macro trigger template and macro trigger names.
310  *   T:\<template\>:\<modifier chr\>:\<modifier name1\>:\<modifier name2\>:...
311  *   T:\<trigger\>:\<keycode\>:\<shift-keycode\>
312  * </pre>
313  */
314 errr process_pref_file_command(player_type *creature_ptr, char *buf)
315 {
316         if (buf[1] != ':') return 1;
317
318         char *zz[16];
319         switch (buf[0])
320         {
321         case 'H':
322         {
323                 /* Process "H:<history>" */
324                 add_history_from_pref_line(buf + 2);
325                 return 0;
326         }
327         case 'R':
328         {
329                 /* Process "R:<num>:<a>/<c>" -- attr/char for monster races */
330                 if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3) return 1;
331
332                 monster_race *r_ptr;
333                 int i = (huge)strtol(zz[0], NULL, 0);
334                 TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
335                 SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
336                 if (i >= max_r_idx) return 1;
337                 r_ptr = &r_info[i];
338                 if (n1 || (!(n2 & 0x80) && n2)) r_ptr->x_attr = n1; /* Allow TERM_DARK text */
339                 if (n2) r_ptr->x_char = n2;
340                 return 0;
341         }
342         case 'K':
343         {
344                 /* Process "K:<num>:<a>/<c>"  -- attr/char for object kinds */
345                 if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3) return 1;
346                 
347                 object_kind *k_ptr;
348                 int i = (huge)strtol(zz[0], NULL, 0);
349                 TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
350                 SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
351                 if (i >= max_k_idx) return 1;
352                 k_ptr = &k_info[i];
353                 if (n1 || (!(n2 & 0x80) && n2)) k_ptr->x_attr = n1; /* Allow TERM_DARK text */
354                 if (n2) k_ptr->x_char = n2;
355                 return 0;
356         }
357         case 'F':
358         {
359                 /* Process "F:<num>:<a>/<c>" -- attr/char for terrain features */
360                 /* "F:<num>:<a>/<c>" */
361                 /* "F:<num>:<a>/<c>:LIT" */
362                 /* "F:<num>:<a>/<c>:<la>/<lc>:<da>/<dc>" */
363                 feature_type *f_ptr;
364                 int num = tokenize(buf + 2, F_LIT_MAX * 2 + 1, zz, TOKENIZE_CHECKQUOTE);
365
366                 if ((num != 3) && (num != 4) && (num != F_LIT_MAX * 2 + 1)) return 1;
367                 else if ((num == 4) && !streq(zz[3], "LIT")) return 1;
368
369                 int i = (huge)strtol(zz[0], NULL, 0);
370                 if (i >= max_f_idx) return 1;
371                 f_ptr = &f_info[i];
372
373                 TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
374                 SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
375                 if (n1 || (!(n2 & 0x80) && n2)) f_ptr->x_attr[F_LIT_STANDARD] = n1; /* Allow TERM_DARK text */
376                 if (n2) f_ptr->x_char[F_LIT_STANDARD] = n2;
377
378                 switch (num)
379                 {
380                 case 3:
381                 {
382                         /* No lighting support */
383                         n1 = f_ptr->x_attr[F_LIT_STANDARD];
384                         n2 = f_ptr->x_char[F_LIT_STANDARD];
385                         for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
386                         {
387                                 f_ptr->x_attr[j] = n1;
388                                 f_ptr->x_char[j] = n2;
389                         }
390
391                         return 0;
392                 }
393                 case 4:
394                 {
395                         /* Use default lighting */
396                         apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
397                         return 0;
398                 }
399                 case F_LIT_MAX * 2 + 1:
400                 {
401                         /* Use desired lighting */
402                         for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
403                         {
404                                 n1 = (TERM_COLOR)strtol(zz[j * 2 + 1], NULL, 0);
405                                 n2 = (SYMBOL_CODE)strtol(zz[j * 2 + 2], NULL, 0);
406                                 if (n1 || (!(n2 & 0x80) && n2)) f_ptr->x_attr[j] = n1; /* Allow TERM_DARK text */
407                                 if (n2) f_ptr->x_char[j] = n2;
408                         }
409
410                         return 0;
411                 }
412                 default:
413                         return 0;
414                 }
415         }
416         case 'S':
417         {
418                 /* Process "S:<num>:<a>/<c>" -- attr/char for special things */
419                 if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3) return 1;
420
421                 int j = (byte)strtol(zz[0], NULL, 0);
422                 TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
423                 SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
424                 misc_to_attr[j] = n1;
425                 misc_to_char[j] = n2;
426                 return 0;
427         }
428         case 'U':
429         {
430                 /* Process "U:<tv>:<a>/<c>" -- attr/char for unaware items */
431                 if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3) return 1;
432
433                 int j = (huge)strtol(zz[0], NULL, 0);
434                 TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
435                 SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
436                 for (int i = 1; i < max_k_idx; i++)
437                 {
438                         object_kind *k_ptr = &k_info[i];
439                         if (k_ptr->tval == j)
440                         {
441                                 if (n1) k_ptr->d_attr = n1;
442                                 if (n2) k_ptr->d_char = n2;
443                         }
444                 }
445
446                 return 0;
447         }
448         case 'E':
449         {
450                 /* Process "E:<tv>:<a>" -- attribute for inventory objects */
451                 if (tokenize(buf + 2, 2, zz, TOKENIZE_CHECKQUOTE) != 2) return 1;
452
453                 int j = (byte)strtol(zz[0], NULL, 0) % 128;
454                 TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
455                 if (n1) tval_to_attr[j] = n1;
456                 return 0;
457         }
458         case 'A':
459         {
460                 /* Process "A:<str>" -- save an "action" for later */
461                 text_to_ascii(macro__buf, buf + 2);
462                 return 0;
463         }
464         case 'P':
465         {
466                 /* Process "P:<str>" -- normal macro */
467                 char tmp[1024];
468                 text_to_ascii(tmp, buf + 2);
469                 macro_add(tmp, macro__buf);
470                 return 0;
471         }
472         case 'C':
473         {
474                 /* Process "C:<str>" -- create keymap */
475                 if (tokenize(buf + 2, 2, zz, TOKENIZE_CHECKQUOTE) != 2) return 1;
476
477                 int mode = strtol(zz[0], NULL, 0);
478                 if ((mode < 0) || (mode >= KEYMAP_MODES)) return 1;
479
480                 char tmp[1024];
481                 text_to_ascii(tmp, zz[1]);
482                 if (!tmp[0] || tmp[1]) return 1;
483
484                 int i = (byte)(tmp[0]);
485                 string_free(keymap_act[mode][i]);
486                 keymap_act[mode][i] = string_make(macro__buf);
487                 return 0;
488         }
489         case 'V':
490         {
491                 /* Process "V:<num>:<kv>:<rv>:<gv>:<bv>" -- visual info */
492                 if (tokenize(buf + 2, 5, zz, TOKENIZE_CHECKQUOTE) != 5) return 1;
493
494                 int i = (byte)strtol(zz[0], NULL, 0);
495                 angband_color_table[i][0] = (byte)strtol(zz[1], NULL, 0);
496                 angband_color_table[i][1] = (byte)strtol(zz[2], NULL, 0);
497                 angband_color_table[i][2] = (byte)strtol(zz[3], NULL, 0);
498                 angband_color_table[i][3] = (byte)strtol(zz[4], NULL, 0);
499                 return 0;
500         }
501         case 'X':
502         case 'Y':
503         {
504                 /* Process "X:<str>" -- turn option off */
505                 /* Process "Y:<str>" -- turn option on */
506                 for (int i = 0; option_info[i].o_desc; i++)
507                 {
508                         bool is_option = option_info[i].o_var != NULL;
509                         is_option &= option_info[i].o_text != NULL;
510                         is_option &= streq(option_info[i].o_text, buf + 2);
511                         if (!is_option) continue;
512
513                         int os = option_info[i].o_set;
514                         int ob = option_info[i].o_bit;
515
516                         if ((creature_ptr->playing || current_world_ptr->character_xtra) &&
517                                 (OPT_PAGE_BIRTH == option_info[i].o_page) && !current_world_ptr->wizard)
518                         {
519                                 msg_format(_("初期オプションは変更できません! '%s'", "Birth options can not changed! '%s'"), buf);
520                                 msg_print(NULL);
521                                 return 0;
522                         }
523
524                         if (buf[0] == 'X')
525                         {
526                                 option_flag[os] &= ~(1L << ob);
527                                 (*option_info[i].o_var) = FALSE;
528                                 return 0;
529                         }
530
531                         option_flag[os] |= (1L << ob);
532                         (*option_info[i].o_var) = TRUE;
533                         return 0;
534                 }
535
536                 msg_format(_("オプションの名前が正しくありません: %s", "Ignored invalid option: %s"), buf);
537                 msg_print(NULL);
538                 return 0;
539         }
540         case 'Z':
541         {
542                 /* Process "Z:<type>:<str>" -- set spell color */
543                 char *t = my_strchr(buf + 2, ':');
544                 if (!t) return 1;
545
546                 *(t++) = '\0';
547                 for (int i = 0; gf_desc[i].name; i++)
548                 {
549                         if (!streq(gf_desc[i].name, buf + 2)) continue;
550
551                         gf_color[gf_desc[i].num] = (TERM_COLOR)quark_add(t);
552                         return 0;
553                 }
554
555                 return 1;
556         }
557         case 'T':
558         {
559                 /* Initialize macro trigger names and a template */
560                 /* Process "T:<trigger>:<keycode>:<shift-keycode>" */
561                 /* Process "T:<template>:<modifier chr>:<modifier name>:..." */
562                 int tok = tokenize(buf + 2, 2 + MAX_MACRO_MOD, zz, 0);
563
564                 /* Process "T:<template>:<modifier chr>:<modifier name>:..." */
565                 if (tok >= 4)
566                 {
567                         if (macro_template != NULL)
568                         {
569                                 int macro_modifier_length = strlen(macro_modifier_chr);
570                                 string_free(macro_template);
571                                 macro_template = NULL;
572                                 string_free(macro_modifier_chr);
573                                 for (int i = 0; i < macro_modifier_length; i++)
574                                 {
575                                         string_free(macro_modifier_name[i]);
576                                 }
577
578                                 for (int i = 0; i < max_macrotrigger; i++)
579                                 {
580                                         string_free(macro_trigger_name[i]);
581                                         string_free(macro_trigger_keycode[0][i]);
582                                         string_free(macro_trigger_keycode[1][i]);
583                                 }
584
585                                 max_macrotrigger = 0;
586                         }
587
588                         if (*zz[0] == '\0') return 0;
589
590                         int zz_length = strlen(zz[1]);
591                         zz_length = MIN(MAX_MACRO_MOD, zz_length);
592                         if (2 + zz_length != tok) return 1;
593
594                         macro_template = string_make(zz[0]);
595                         macro_modifier_chr = string_make(zz[1]);
596                         for (int i = 0; i < zz_length; i++)
597                         {
598                                 macro_modifier_name[i] = string_make(zz[2 + i]);
599                         }
600
601                         return 0;
602                 }
603
604                 /* Process "T:<trigger>:<keycode>:<shift-keycode>" */
605                 if (tok < 2) return 0;
606
607                 char buf_aux[1024];
608                 char *t, *s;
609                 if (max_macrotrigger >= MAX_MACRO_TRIG)
610                 {
611                         msg_print(_("マクロトリガーの設定が多すぎます!", "Too many macro triggers!"));
612                         return 1;
613                 }
614
615                 int m = max_macrotrigger;
616                 max_macrotrigger++;
617                 t = buf_aux;
618                 s = zz[0];
619                 while (*s)
620                 {
621                         if ('\\' == *s) s++;
622                         *t++ = *s++;
623                 }
624
625                 *t = '\0';
626                 macro_trigger_name[m] = string_make(buf_aux);
627                 macro_trigger_keycode[0][m] = string_make(zz[1]);
628                 if (tok == 3)
629                 {
630                         macro_trigger_keycode[1][m] = string_make(zz[2]);
631                         return 0;
632                 }
633
634                 macro_trigger_keycode[1][m] = string_make(zz[1]);
635                 return 0;
636         }
637         }
638
639         return 1;
640 }
641
642
643 /*!
644  * @brief process_pref_fileのサブルーチンとして条件分岐処理の解釈と結果を返す /
645  * Helper function for "process_pref_file()"
646  * @param creature_ptr プレーヤーへの参照ポインタ
647  * @param sp テキスト文字列の参照ポインタ
648  * @param fp 再帰中のポインタ参照
649  * @return
650  * @details
651  * <pre>
652  * Input:
653  *   v: output buffer array
654  *   f: final character
655  * Output:
656  *   result
657  * </pre>
658  */
659 concptr process_pref_file_expr(player_type *creature_ptr, char **sp, char *fp)
660 {
661         char *s;
662         s = (*sp);
663         while (iswspace(*s)) s++;
664
665         char *b;
666         b = s;
667
668         concptr v = "?o?o?";
669
670         char b1 = '[';
671         char b2 = ']';
672         char f = ' ';
673         static char tmp[16];
674         if (*s == b1)
675         {
676                 concptr p;
677                 concptr t;
678
679                 /* Skip b1 */
680                 s++;
681
682                 /* First */
683                 t = process_pref_file_expr(creature_ptr, &s, &f);
684
685                 if (!*t)
686                 {
687                 }
688                 else if (streq(t, "IOR"))
689                 {
690                         v = "0";
691                         while (*s && (f != b2))
692                         {
693                                 t = process_pref_file_expr(creature_ptr, &s, &f);
694                                 if (*t && !streq(t, "0")) v = "1";
695                         }
696                 }
697                 else if (streq(t, "AND"))
698                 {
699                         v = "1";
700                         while (*s && (f != b2))
701                         {
702                                 t = process_pref_file_expr(creature_ptr, &s, &f);
703                                 if (*t && streq(t, "0")) v = "0";
704                         }
705                 }
706                 else if (streq(t, "NOT"))
707                 {
708                         v = "1";
709                         while (*s && (f != b2))
710                         {
711                                 t = process_pref_file_expr(creature_ptr, &s, &f);
712                                 if (*t && streq(t, "1")) v = "0";
713                         }
714                 }
715                 else if (streq(t, "EQU"))
716                 {
717                         v = "0";
718                         if (*s && (f != b2))
719                         {
720                                 t = process_pref_file_expr(creature_ptr, &s, &f);
721                         }
722                         while (*s && (f != b2))
723                         {
724                                 p = process_pref_file_expr(creature_ptr, &s, &f);
725                                 if (streq(t, p)) v = "1";
726                         }
727                 }
728                 else if (streq(t, "LEQ"))
729                 {
730                         v = "1";
731                         if (*s && (f != b2))
732                         {
733                                 t = process_pref_file_expr(creature_ptr, &s, &f);
734                         }
735                         while (*s && (f != b2))
736                         {
737                                 p = t;
738                                 t = process_pref_file_expr(creature_ptr, &s, &f);
739                                 if (*t && atoi(p) > atoi(t)) v = "0";
740                         }
741                 }
742                 else if (streq(t, "GEQ"))
743                 {
744                         v = "1";
745                         if (*s && (f != b2))
746                         {
747                                 t = process_pref_file_expr(creature_ptr, &s, &f);
748                         }
749                         while (*s && (f != b2))
750                         {
751                                 p = t;
752                                 t = process_pref_file_expr(creature_ptr, &s, &f);
753                                 if (*t && atoi(p) < atoi(t)) v = "0";
754                         }
755                 }
756                 else
757                 {
758                         while (*s && (f != b2))
759                         {
760                                 t = process_pref_file_expr(creature_ptr, &s, &f);
761                         }
762                 }
763
764                 if (f != b2) v = "?x?x?";
765
766                 if ((f = *s) != '\0') *s++ = '\0';
767
768                 *fp = f;
769                 *sp = s;
770                 return v;
771         }
772
773         /* Accept all printables except spaces and brackets */
774 #ifdef JP
775         while (iskanji(*s) || (isprint(*s) && !my_strchr(" []", *s)))
776         {
777                 if (iskanji(*s)) s++;
778                 s++;
779         }
780 #else
781         while (isprint(*s) && !my_strchr(" []", *s)) ++s;
782 #endif
783
784         if ((f = *s) != '\0') *s++ = '\0';
785
786         if (*b != '$')
787         {
788                 v = b;
789                 *fp = f;
790                 *sp = s;
791                 return v;
792         }
793
794         if (streq(b + 1, "SYS"))
795         {
796                 v = ANGBAND_SYS;
797         }
798         else if (streq(b + 1, "KEYBOARD"))
799         {
800                 v = ANGBAND_KEYBOARD;
801         }
802         else if (streq(b + 1, "GRAF"))
803         {
804                 v = ANGBAND_GRAF;
805         }
806         else if (streq(b + 1, "MONOCHROME"))
807         {
808                 if (arg_monochrome)
809                         v = "ON";
810                 else
811                         v = "OFF";
812         }
813         else if (streq(b + 1, "RACE"))
814         {
815 #ifdef JP
816                 v = rp_ptr->E_title;
817 #else
818                 v = rp_ptr->title;
819 #endif
820         }
821         else if (streq(b + 1, "CLASS"))
822         {
823 #ifdef JP
824                 v = cp_ptr->E_title;
825 #else
826                 v = cp_ptr->title;
827 #endif
828         }
829         else if (streq(b + 1, "PLAYER"))
830         {
831                 static char tmp_player_name[32];
832                 char *pn, *tpn;
833                 for (pn = creature_ptr->name, tpn = tmp_player_name; *pn; pn++, tpn++)
834                 {
835 #ifdef JP
836                         if (iskanji(*pn))
837                         {
838                                 *(tpn++) = *(pn++);
839                                 *tpn = *pn;
840                                 continue;
841                         }
842 #endif
843                         *tpn = my_strchr(" []", *pn) ? '_' : *pn;
844                 }
845
846                 *tpn = '\0';
847                 v = tmp_player_name;
848         }
849         else if (streq(b + 1, "REALM1"))
850         {
851 #ifdef JP
852                 v = E_realm_names[creature_ptr->realm1];
853 #else
854                 v = realm_names[creature_ptr->realm1];
855 #endif
856         }
857         else if (streq(b + 1, "REALM2"))
858         {
859 #ifdef JP
860                 v = E_realm_names[creature_ptr->realm2];
861 #else
862                 v = realm_names[creature_ptr->realm2];
863 #endif
864         }
865         else if (streq(b + 1, "LEVEL"))
866         {
867                 sprintf(tmp, "%02d", creature_ptr->lev);
868                 v = tmp;
869         }
870         else if (streq(b + 1, "AUTOREGISTER"))
871         {
872                 if (creature_ptr->autopick_autoregister)
873                         v = "1";
874                 else
875                         v = "0";
876         }
877         else if (streq(b + 1, "MONEY"))
878         {
879                 sprintf(tmp, "%09ld", (long int)creature_ptr->au);
880                 v = tmp;
881         }
882
883         *fp = f;
884         *sp = s;
885         return v;
886 }
887
888
889 /*!
890  * @brief process_pref_fileのサブルーチン /
891  * Open the "user pref file" and parse it.
892  * @param creature_ptr プレーヤーへの参照ポインタ
893  * @param name 読み込むファイル名
894  * @param preftype prefファイルのタイプ
895  * @return エラーコード
896  * @details
897  * <pre>
898  * Input:
899  *   v: output buffer array
900  *   f: final character
901  * Output:
902  *   result
903  * </pre>
904  */
905 static errr process_pref_file_aux(player_type *creature_ptr, concptr name, int preftype)
906 {
907         FILE *fp;
908         fp = my_fopen(name, "r");
909         if (!fp) return -1;
910
911         char buf[1024];
912         char old[1024];
913         int line = -1;
914         errr err = 0;
915         bool bypass = FALSE;
916         while (my_fgets(fp, buf, sizeof(buf)) == 0)
917         {
918                 line++;
919                 if (!buf[0]) continue;
920
921 #ifdef JP
922                 if (!iskanji(buf[0]))
923 #endif
924                         if (iswspace(buf[0])) continue;
925
926                 if (buf[0] == '#') continue;
927                 strcpy(old, buf);
928
929                 /* Process "?:<expr>" */
930                 if ((buf[0] == '?') && (buf[1] == ':'))
931                 {
932                         char f;
933                         char *s;
934                         s = buf + 2;
935                         concptr v = process_pref_file_expr(creature_ptr, &s, &f);
936                         bypass = streq(v, "0");
937                         continue;
938                 }
939
940                 if (bypass) continue;
941
942                 /* Process "%:<file>" */
943                 if (buf[0] == '%')
944                 {
945                         static int depth_count = 0;
946                         if (depth_count > 20) continue;
947
948                         depth_count++;
949
950                         /* Process that file if allowed */
951                         switch (preftype)
952                         {
953                         case PREF_TYPE_AUTOPICK:
954                                 (void)process_autopick_file(creature_ptr, buf + 2);
955                                 break;
956                         case PREF_TYPE_HISTPREF:
957                                 (void)process_histpref_file(creature_ptr, buf + 2);
958                                 break;
959                         default:
960                                 (void)process_pref_file(creature_ptr, buf + 2);
961                                 break;
962                         }
963
964                         depth_count--;
965                         continue;
966                 }
967
968                 err = process_pref_file_command(creature_ptr, buf);
969                 if (err != 0)
970                 {
971                         if (preftype != PREF_TYPE_AUTOPICK)
972                                 break;
973                         err = process_autopick_file_command(buf);
974                 }
975         }
976
977         if (err != 0)
978         {
979                 /* Print error message */
980                 /* ToDo: Add better error messages */
981                 msg_format(_("ファイル'%s'の%d行でエラー番号%dのエラー。", "Error %d in line %d of file '%s'."),
982                         _(name, err), line, _(err, name));
983                 msg_format(_("('%s'を解析中)", "Parsing '%s'"), old);
984                 msg_print(NULL);
985         }
986
987         my_fclose(fp);
988         return (err);
989 }
990
991
992 /*!
993  * @brief pref設定ファイルを読み込み設定を反映させる /
994  * Process the "user pref file" with the given name
995  * @param creature_ptr プレーヤーへの参照ポインタ
996  * @param name 読み込むファイル名
997  * @return エラーコード
998  * @details
999  * <pre>
1000  * See the functions above for a list of legal "commands".
1001  * We also accept the special "?" and "%" directives, which
1002  * allow conditional evaluation and filename inclusion.
1003  * </pre>
1004  */
1005 errr process_pref_file(player_type *creature_ptr, concptr name)
1006 {
1007         char buf[1024];
1008         path_build(buf, sizeof(buf), ANGBAND_DIR_PREF, name);
1009
1010         /* Process the system pref file */
1011         errr err1 = process_pref_file_aux(creature_ptr, buf, PREF_TYPE_NORMAL);
1012
1013         /* Stop at parser errors, but not at non-existing file */
1014         if (err1 > 0) return err1;
1015
1016         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name);
1017
1018         /* Process the user pref file */
1019         errr err2 = process_pref_file_aux(creature_ptr, buf, PREF_TYPE_NORMAL);
1020
1021         /* User file does not exist, but read system pref file */
1022         if (err2 < 0 && !err1)
1023                 return -2;
1024
1025         /* Result of user file processing */
1026         return err2;
1027 }
1028
1029
1030 /*!
1031  * @brief プレイヤーの打撃能力修正を表示する
1032  * @param creature_ptr プレーヤーへの参照ポインタ
1033  * @param hand 武器の装備部位ID
1034  * @param hand_entry 項目ID
1035  * @return なし
1036  */
1037 static void display_player_melee_bonus(player_type *creature_ptr, int hand, int hand_entry)
1038 {
1039         HIT_PROB show_tohit = creature_ptr->dis_to_h[hand];
1040         HIT_POINT show_todam = creature_ptr->dis_to_d[hand];
1041         object_type *o_ptr = &creature_ptr->inventory_list[INVEN_RARM + hand];
1042
1043         /* Hack -- add in weapon info if known */
1044         if (object_is_known(o_ptr)) show_tohit += o_ptr->to_h;
1045         if (object_is_known(o_ptr)) show_todam += o_ptr->to_d;
1046
1047         show_tohit += creature_ptr->skill_thn / BTH_PLUS_ADJ;
1048
1049         char buf[160];
1050         sprintf(buf, "(%+d,%+d)", (int)show_tohit, (int)show_todam);
1051
1052         /* Dump the bonuses to hit/dam */
1053         if (!has_melee_weapon(creature_ptr, INVEN_RARM) && !has_melee_weapon(creature_ptr, INVEN_LARM))
1054                 display_player_one_line(ENTRY_BARE_HAND, buf, TERM_L_BLUE);
1055         else if (creature_ptr->ryoute)
1056                 display_player_one_line(ENTRY_TWO_HANDS, buf, TERM_L_BLUE);
1057         else
1058                 display_player_one_line(hand_entry, buf, TERM_L_BLUE);
1059 }
1060
1061
1062 /*!
1063  * @brief プレイヤーステータス表示の中央部分を表示するサブルーチン
1064  * @param creature_ptr プレーヤーへの参照ポインタ
1065  * Prints the following information on the screen.
1066  * @return なし
1067  */
1068 static void display_player_middle(player_type *creature_ptr)
1069 {
1070         HIT_PROB show_tohit = creature_ptr->dis_to_h_b;
1071         HIT_POINT show_todam = 0;
1072
1073         if (creature_ptr->migite)
1074         {
1075                 display_player_melee_bonus(creature_ptr, 0, left_hander ? ENTRY_LEFT_HAND1 : ENTRY_RIGHT_HAND1);
1076         }
1077
1078         if (creature_ptr->hidarite)
1079         {
1080                 display_player_melee_bonus(creature_ptr, 1, left_hander ? ENTRY_RIGHT_HAND2 : ENTRY_LEFT_HAND2);
1081         }
1082         else if ((creature_ptr->pclass == CLASS_MONK) && (empty_hands(creature_ptr, TRUE) & EMPTY_HAND_RARM))
1083         {
1084                 int i;
1085                 if (creature_ptr->special_defense & KAMAE_MASK)
1086                 {
1087                         for (i = 0; i < MAX_KAMAE; i++)
1088                         {
1089                                 if ((creature_ptr->special_defense >> i) & KAMAE_GENBU) break;
1090                         }
1091                         if (i < MAX_KAMAE)
1092                         {
1093                                 display_player_one_line(ENTRY_POSTURE, format(_("%sの構え", "%s form"), kamae_shurui[i].desc), TERM_YELLOW);
1094                         }
1095                 }
1096                 else
1097                 {
1098                         display_player_one_line(ENTRY_POSTURE, _("構えなし", "none"), TERM_YELLOW);
1099                 }
1100         }
1101
1102         /* Apply weapon bonuses */
1103         object_type *o_ptr = &creature_ptr->inventory_list[INVEN_BOW];
1104         if (object_is_known(o_ptr)) show_tohit += o_ptr->to_h;
1105         if (object_is_known(o_ptr)) show_todam += o_ptr->to_d;
1106
1107         if ((o_ptr->sval == SV_LIGHT_XBOW) || (o_ptr->sval == SV_HEAVY_XBOW))
1108                 show_tohit += creature_ptr->weapon_exp[0][o_ptr->sval] / 400;
1109         else
1110                 show_tohit += (creature_ptr->weapon_exp[0][o_ptr->sval] - (WEAPON_EXP_MASTER / 2)) / 200;
1111
1112         show_tohit += creature_ptr->skill_thb / BTH_PLUS_ADJ;
1113
1114         /* Range attacks */
1115         display_player_one_line(ENTRY_SHOOT_HIT_DAM, format("(%+d,%+d)", show_tohit, show_todam), TERM_L_BLUE);
1116
1117         int tmul = 0;
1118         if (creature_ptr->inventory_list[INVEN_BOW].k_idx)
1119         {
1120                 tmul = bow_tmul(creature_ptr->inventory_list[INVEN_BOW].sval);
1121
1122                 /* Get extra "power" from "extra might" */
1123                 if (creature_ptr->xtra_might) tmul++;
1124
1125                 tmul = tmul * (100 + (int)(adj_str_td[creature_ptr->stat_ind[A_STR]]) - 128);
1126         }
1127
1128         /* shoot power */
1129         display_player_one_line(ENTRY_SHOOT_POWER, format("x%d.%02d", tmul / 100, tmul % 100), TERM_L_BLUE);
1130
1131         /* Dump the armor class */
1132         display_player_one_line(ENTRY_BASE_AC, format("[%d,%+d]", creature_ptr->dis_ac, creature_ptr->dis_to_a), TERM_L_BLUE);
1133
1134         int i = creature_ptr->pspeed - 110;
1135
1136         /* Hack -- Visually "undo" the Search Mode Slowdown */
1137         if (creature_ptr->action == ACTION_SEARCH) i += 10;
1138
1139         TERM_COLOR attr;
1140         if (i > 0)
1141         {
1142                 if (!creature_ptr->riding)
1143                         attr = TERM_L_GREEN;
1144                 else
1145                         attr = TERM_GREEN;
1146         }
1147         else if (i == 0)
1148         {
1149                 if (!creature_ptr->riding)
1150                         attr = TERM_L_BLUE;
1151                 else
1152                         attr = TERM_GREEN;
1153         }
1154         else
1155         {
1156                 if (!creature_ptr->riding)
1157                         attr = TERM_L_UMBER;
1158                 else
1159                         attr = TERM_RED;
1160         }
1161
1162         int tmp_speed = 0;
1163         if (!creature_ptr->riding)
1164         {
1165                 if (IS_FAST(creature_ptr)) tmp_speed += 10;
1166                 if (creature_ptr->slow) tmp_speed -= 10;
1167                 if (creature_ptr->lightspeed) tmp_speed = 99;
1168         }
1169         else
1170         {
1171                 if (MON_FAST(&creature_ptr->current_floor_ptr->m_list[creature_ptr->riding])) tmp_speed += 10;
1172                 if (MON_SLOW(&creature_ptr->current_floor_ptr->m_list[creature_ptr->riding])) tmp_speed -= 10;
1173         }
1174
1175         char buf[160];
1176         if (tmp_speed)
1177         {
1178                 if (!creature_ptr->riding)
1179                         sprintf(buf, "(%+d%+d)", i - tmp_speed, tmp_speed);
1180                 else
1181                         sprintf(buf, _("乗馬中 (%+d%+d)", "Riding (%+d%+d)"), i - tmp_speed, tmp_speed);
1182
1183                 if (tmp_speed > 0)
1184                         attr = TERM_YELLOW;
1185                 else
1186                         attr = TERM_VIOLET;
1187         }
1188         else
1189         {
1190                 if (!creature_ptr->riding)
1191                         sprintf(buf, "(%+d)", i);
1192                 else
1193                         sprintf(buf, _("乗馬中 (%+d)", "Riding (%+d)"), i);
1194         }
1195
1196         display_player_one_line(ENTRY_SPEED, buf, attr);
1197
1198         /* Dump character level */
1199         display_player_one_line(ENTRY_LEVEL, format("%d", creature_ptr->lev), TERM_L_GREEN);
1200
1201         /* Dump experience */
1202         int e;
1203         if (creature_ptr->prace == RACE_ANDROID) e = ENTRY_EXP_ANDR;
1204         else e = ENTRY_CUR_EXP;
1205
1206         if (creature_ptr->exp >= creature_ptr->max_exp)
1207                 display_player_one_line(e, format("%ld", creature_ptr->exp), TERM_L_GREEN);
1208         else
1209                 display_player_one_line(e, format("%ld", creature_ptr->exp), TERM_YELLOW);
1210
1211         /* Dump max experience */
1212         if (creature_ptr->prace == RACE_ANDROID)
1213                 /* Nothing */;
1214         else
1215                 display_player_one_line(ENTRY_MAX_EXP, format("%ld", creature_ptr->max_exp), TERM_L_GREEN);
1216
1217         /* Dump exp to advance */
1218         if (creature_ptr->prace == RACE_ANDROID) e = ENTRY_EXP_TO_ADV_ANDR;
1219         else e = ENTRY_EXP_TO_ADV;
1220
1221         if (creature_ptr->lev >= PY_MAX_LEVEL)
1222                 display_player_one_line(e, "*****", TERM_L_GREEN);
1223         else if (creature_ptr->prace == RACE_ANDROID)
1224                 display_player_one_line(e, format("%ld", (s32b)(player_exp_a[creature_ptr->lev - 1] * creature_ptr->expfact / 100L)), TERM_L_GREEN);
1225         else
1226                 display_player_one_line(e, format("%ld", (s32b)(player_exp[creature_ptr->lev - 1] * creature_ptr->expfact / 100L)), TERM_L_GREEN);
1227
1228         /* Dump gold */
1229         display_player_one_line(ENTRY_GOLD, format("%ld", creature_ptr->au), TERM_L_GREEN);
1230
1231         /* Dump Day */
1232         int day, hour, min;
1233         extract_day_hour_min(creature_ptr, &day, &hour, &min);
1234
1235         if (day < MAX_DAYS) sprintf(buf, _("%d日目 %2d:%02d", "Day %d %2d:%02d"), day, hour, min);
1236         else sprintf(buf, _("*****日目 %2d:%02d", "Day ***** %2d:%02d"), hour, min);
1237         display_player_one_line(ENTRY_DAY, buf, TERM_L_GREEN);
1238
1239         /* Dump hit point */
1240         if (creature_ptr->chp >= creature_ptr->mhp)
1241                 display_player_one_line(ENTRY_HP, format("%4d/%4d", creature_ptr->chp, creature_ptr->mhp), TERM_L_GREEN);
1242         else if (creature_ptr->chp > (creature_ptr->mhp * hitpoint_warn) / 10)
1243                 display_player_one_line(ENTRY_HP, format("%4d/%4d", creature_ptr->chp, creature_ptr->mhp), TERM_YELLOW);
1244         else
1245                 display_player_one_line(ENTRY_HP, format("%4d/%4d", creature_ptr->chp, creature_ptr->mhp), TERM_RED);
1246
1247         /* Dump mana power */
1248         if (creature_ptr->csp >= creature_ptr->msp)
1249                 display_player_one_line(ENTRY_SP, format("%4d/%4d", creature_ptr->csp, creature_ptr->msp), TERM_L_GREEN);
1250         else if (creature_ptr->csp > (creature_ptr->msp * mana_warn) / 10)
1251                 display_player_one_line(ENTRY_SP, format("%4d/%4d", creature_ptr->csp, creature_ptr->msp), TERM_YELLOW);
1252         else
1253                 display_player_one_line(ENTRY_SP, format("%4d/%4d", creature_ptr->csp, creature_ptr->msp), TERM_RED);
1254
1255         /* Dump play time */
1256         display_player_one_line(ENTRY_PLAY_TIME, format("%.2lu:%.2lu:%.2lu", current_world_ptr->play_time / (60 * 60), (current_world_ptr->play_time / 60) % 60, current_world_ptr->play_time % 60), TERM_L_GREEN);
1257 }
1258
1259
1260 /*!
1261  * @brief プレイヤーの職業、種族に応じた耐性フラグを返す
1262  * Prints ratings on certain abilities
1263  * @param creature_ptr 参照元クリーチャーポインタ
1264  * @param flgs フラグを保管する配列
1265  * @return なし
1266  * @details
1267  * Obtain the "flags" for the player as if he was an item
1268  * @todo
1269  * xtra1.c周りと多重実装になっているのを何とかする
1270  */
1271 static void player_flags(player_type *creature_ptr, BIT_FLAGS flgs[TR_FLAG_SIZE])
1272 {
1273         for (int i = 0; i < TR_FLAG_SIZE; i++)
1274                 flgs[i] = 0L;
1275
1276         switch (creature_ptr->pclass)
1277         {
1278         case CLASS_WARRIOR:
1279                 if (creature_ptr->lev > 44)
1280                         add_flag(flgs, TR_REGEN);
1281         case CLASS_SAMURAI:
1282                 if (creature_ptr->lev > 29)
1283                         add_flag(flgs, TR_RES_FEAR);
1284                 break;
1285         case CLASS_PALADIN:
1286                 if (creature_ptr->lev > 39)
1287                         add_flag(flgs, TR_RES_FEAR);
1288                 break;
1289         case CLASS_CHAOS_WARRIOR:
1290                 if (creature_ptr->lev > 29)
1291                         add_flag(flgs, TR_RES_CHAOS);
1292                 if (creature_ptr->lev > 39)
1293                         add_flag(flgs, TR_RES_FEAR);
1294                 break;
1295         case CLASS_MONK:
1296         case CLASS_FORCETRAINER:
1297                 if ((creature_ptr->lev > 9) && !heavy_armor(creature_ptr))
1298                         add_flag(flgs, TR_SPEED);
1299                 if ((creature_ptr->lev > 24) && !heavy_armor(creature_ptr))
1300                         add_flag(flgs, TR_FREE_ACT);
1301                 break;
1302         case CLASS_NINJA:
1303                 if (heavy_armor(creature_ptr))
1304                         add_flag(flgs, TR_SPEED);
1305                 else
1306                 {
1307                         if ((!creature_ptr->inventory_list[INVEN_RARM].k_idx || creature_ptr->migite) &&
1308                                 (!creature_ptr->inventory_list[INVEN_LARM].k_idx || creature_ptr->hidarite))
1309                                 add_flag(flgs, TR_SPEED);
1310                         if (creature_ptr->lev > 24)
1311                                 add_flag(flgs, TR_FREE_ACT);
1312                 }
1313
1314                 add_flag(flgs, TR_SLOW_DIGEST);
1315                 add_flag(flgs, TR_RES_FEAR);
1316                 if (creature_ptr->lev > 19) add_flag(flgs, TR_RES_POIS);
1317                 if (creature_ptr->lev > 24) add_flag(flgs, TR_SUST_DEX);
1318                 if (creature_ptr->lev > 29) add_flag(flgs, TR_SEE_INVIS);
1319                 break;
1320         case CLASS_MINDCRAFTER:
1321                 if (creature_ptr->lev > 9)
1322                         add_flag(flgs, TR_RES_FEAR);
1323                 if (creature_ptr->lev > 19)
1324                         add_flag(flgs, TR_SUST_WIS);
1325                 if (creature_ptr->lev > 29)
1326                         add_flag(flgs, TR_RES_CONF);
1327                 if (creature_ptr->lev > 39)
1328                         add_flag(flgs, TR_TELEPATHY);
1329                 break;
1330         case CLASS_BARD:
1331                 add_flag(flgs, TR_RES_SOUND);
1332                 break;
1333         case CLASS_BERSERKER:
1334                 add_flag(flgs, TR_SUST_STR);
1335                 add_flag(flgs, TR_SUST_DEX);
1336                 add_flag(flgs, TR_SUST_CON);
1337                 add_flag(flgs, TR_REGEN);
1338                 add_flag(flgs, TR_FREE_ACT);
1339                 add_flag(flgs, TR_SPEED);
1340                 if (creature_ptr->lev > 39) add_flag(flgs, TR_REFLECT);
1341                 break;
1342         case CLASS_MIRROR_MASTER:
1343                 if (creature_ptr->lev > 39)add_flag(flgs, TR_REFLECT);
1344                 break;
1345         default:
1346                 break; /* Do nothing */
1347         }
1348
1349         /* Races */
1350         if (creature_ptr->mimic_form)
1351         {
1352                 switch (creature_ptr->mimic_form)
1353                 {
1354                 case MIMIC_DEMON:
1355                         add_flag(flgs, TR_HOLD_EXP);
1356                         add_flag(flgs, TR_RES_CHAOS);
1357                         add_flag(flgs, TR_RES_NETHER);
1358                         add_flag(flgs, TR_RES_FIRE);
1359                         add_flag(flgs, TR_SEE_INVIS);
1360                         add_flag(flgs, TR_SPEED);
1361                         break;
1362                 case MIMIC_DEMON_LORD:
1363                         add_flag(flgs, TR_HOLD_EXP);
1364                         add_flag(flgs, TR_RES_CHAOS);
1365                         add_flag(flgs, TR_RES_NETHER);
1366                         add_flag(flgs, TR_RES_FIRE);
1367                         add_flag(flgs, TR_RES_COLD);
1368                         add_flag(flgs, TR_RES_ELEC);
1369                         add_flag(flgs, TR_RES_ACID);
1370                         add_flag(flgs, TR_RES_POIS);
1371                         add_flag(flgs, TR_RES_CONF);
1372                         add_flag(flgs, TR_RES_DISEN);
1373                         add_flag(flgs, TR_RES_NEXUS);
1374                         add_flag(flgs, TR_RES_FEAR);
1375                         add_flag(flgs, TR_IM_FIRE);
1376                         add_flag(flgs, TR_SH_FIRE);
1377                         add_flag(flgs, TR_SEE_INVIS);
1378                         add_flag(flgs, TR_TELEPATHY);
1379                         add_flag(flgs, TR_LEVITATION);
1380                         add_flag(flgs, TR_SPEED);
1381                         break;
1382                 case MIMIC_VAMPIRE:
1383                         add_flag(flgs, TR_HOLD_EXP);
1384                         add_flag(flgs, TR_RES_DARK);
1385                         add_flag(flgs, TR_RES_NETHER);
1386                         if (creature_ptr->pclass != CLASS_NINJA) add_flag(flgs, TR_LITE_1);
1387                         add_flag(flgs, TR_RES_POIS);
1388                         add_flag(flgs, TR_RES_COLD);
1389                         add_flag(flgs, TR_SEE_INVIS);
1390                         add_flag(flgs, TR_SPEED);
1391                         break;
1392                 }
1393         }
1394         else
1395         {
1396                 switch (creature_ptr->prace)
1397                 {
1398                 case RACE_ELF:
1399                         add_flag(flgs, TR_RES_LITE);
1400                         break;
1401                 case RACE_HOBBIT:
1402                         add_flag(flgs, TR_HOLD_EXP);
1403                         break;
1404                 case RACE_GNOME:
1405                         add_flag(flgs, TR_FREE_ACT);
1406                         break;
1407                 case RACE_DWARF:
1408                         add_flag(flgs, TR_RES_BLIND);
1409                         break;
1410                 case RACE_HALF_ORC:
1411                         add_flag(flgs, TR_RES_DARK);
1412                         break;
1413                 case RACE_HALF_TROLL:
1414                         add_flag(flgs, TR_SUST_STR);
1415                         if (creature_ptr->lev <= 14) break;
1416
1417                         add_flag(flgs, TR_REGEN);
1418                         if ((creature_ptr->pclass == CLASS_WARRIOR) || (creature_ptr->pclass == CLASS_BERSERKER))
1419                         {
1420                                 add_flag(flgs, TR_SLOW_DIGEST);
1421                                 /*
1422                                  * Let's not make Regeneration a disadvantage
1423                                  * for the poor warriors who can never learn
1424                                  * a spell that satisfies hunger (actually
1425                                  * neither can rogues, but half-trolls are not
1426                                  * supposed to play rogues)
1427                                  */
1428                         }
1429
1430                         break;
1431                 case RACE_AMBERITE:
1432                         add_flag(flgs, TR_SUST_CON);
1433                         add_flag(flgs, TR_REGEN);
1434                         break;
1435                 case RACE_HIGH_ELF:
1436                         add_flag(flgs, TR_RES_LITE);
1437                         add_flag(flgs, TR_SEE_INVIS);
1438                         break;
1439                 case RACE_BARBARIAN:
1440                         add_flag(flgs, TR_RES_FEAR);
1441                         break;
1442                 case RACE_HALF_OGRE:
1443                         add_flag(flgs, TR_SUST_STR);
1444                         add_flag(flgs, TR_RES_DARK);
1445                         break;
1446                 case RACE_HALF_GIANT:
1447                         add_flag(flgs, TR_RES_SHARDS);
1448                         add_flag(flgs, TR_SUST_STR);
1449                         break;
1450                 case RACE_HALF_TITAN:
1451                         add_flag(flgs, TR_RES_CHAOS);
1452                         break;
1453                 case RACE_CYCLOPS:
1454                         add_flag(flgs, TR_RES_SOUND);
1455                         break;
1456                 case RACE_YEEK:
1457                         add_flag(flgs, TR_RES_ACID);
1458                         if (creature_ptr->lev > 19)
1459                                 add_flag(flgs, TR_IM_ACID);
1460                         break;
1461                 case RACE_KLACKON:
1462                         add_flag(flgs, TR_RES_CONF);
1463                         add_flag(flgs, TR_RES_ACID);
1464                         if (creature_ptr->lev > 9)
1465                                 add_flag(flgs, TR_SPEED);
1466                         break;
1467                 case RACE_KOBOLD:
1468                         add_flag(flgs, TR_RES_POIS);
1469                         break;
1470                 case RACE_NIBELUNG:
1471                         add_flag(flgs, TR_RES_DISEN);
1472                         add_flag(flgs, TR_RES_DARK);
1473                         break;
1474                 case RACE_DARK_ELF:
1475                         add_flag(flgs, TR_RES_DARK);
1476                         if (creature_ptr->lev > 19)
1477                                 add_flag(flgs, TR_SEE_INVIS);
1478                         break;
1479                 case RACE_DRACONIAN:
1480                         add_flag(flgs, TR_LEVITATION);
1481                         if (creature_ptr->lev > 4)
1482                                 add_flag(flgs, TR_RES_FIRE);
1483                         if (creature_ptr->lev > 9)
1484                                 add_flag(flgs, TR_RES_COLD);
1485                         if (creature_ptr->lev > 14)
1486                                 add_flag(flgs, TR_RES_ACID);
1487                         if (creature_ptr->lev > 19)
1488                                 add_flag(flgs, TR_RES_ELEC);
1489                         if (creature_ptr->lev > 34)
1490                                 add_flag(flgs, TR_RES_POIS);
1491                         break;
1492                 case RACE_MIND_FLAYER:
1493                         add_flag(flgs, TR_SUST_INT);
1494                         add_flag(flgs, TR_SUST_WIS);
1495                         if (creature_ptr->lev > 14)
1496                                 add_flag(flgs, TR_SEE_INVIS);
1497                         if (creature_ptr->lev > 29)
1498                                 add_flag(flgs, TR_TELEPATHY);
1499                         break;
1500                 case RACE_IMP:
1501                         add_flag(flgs, TR_RES_FIRE);
1502                         if (creature_ptr->lev > 9)
1503                                 add_flag(flgs, TR_SEE_INVIS);
1504                         break;
1505                 case RACE_GOLEM:
1506                         add_flag(flgs, TR_SEE_INVIS);
1507                         add_flag(flgs, TR_FREE_ACT);
1508                         add_flag(flgs, TR_RES_POIS);
1509                         add_flag(flgs, TR_SLOW_DIGEST);
1510                         if (creature_ptr->lev > 34)
1511                                 add_flag(flgs, TR_HOLD_EXP);
1512                         break;
1513                 case RACE_SKELETON:
1514                         add_flag(flgs, TR_SEE_INVIS);
1515                         add_flag(flgs, TR_RES_SHARDS);
1516                         add_flag(flgs, TR_HOLD_EXP);
1517                         add_flag(flgs, TR_RES_POIS);
1518                         if (creature_ptr->lev > 9)
1519                                 add_flag(flgs, TR_RES_COLD);
1520                         break;
1521                 case RACE_ZOMBIE:
1522                         add_flag(flgs, TR_SEE_INVIS);
1523                         add_flag(flgs, TR_HOLD_EXP);
1524                         add_flag(flgs, TR_RES_NETHER);
1525                         add_flag(flgs, TR_RES_POIS);
1526                         add_flag(flgs, TR_SLOW_DIGEST);
1527                         if (creature_ptr->lev > 4)
1528                                 add_flag(flgs, TR_RES_COLD);
1529                         break;
1530                 case RACE_VAMPIRE:
1531                         add_flag(flgs, TR_HOLD_EXP);
1532                         add_flag(flgs, TR_RES_DARK);
1533                         add_flag(flgs, TR_RES_NETHER);
1534                         if (creature_ptr->pclass != CLASS_NINJA) add_flag(flgs, TR_LITE_1);
1535                         add_flag(flgs, TR_RES_POIS);
1536                         add_flag(flgs, TR_RES_COLD);
1537                         break;
1538                 case RACE_SPECTRE:
1539                         add_flag(flgs, TR_LEVITATION);
1540                         add_flag(flgs, TR_FREE_ACT);
1541                         add_flag(flgs, TR_RES_COLD);
1542                         add_flag(flgs, TR_SEE_INVIS);
1543                         add_flag(flgs, TR_HOLD_EXP);
1544                         add_flag(flgs, TR_RES_NETHER);
1545                         add_flag(flgs, TR_RES_POIS);
1546                         add_flag(flgs, TR_SLOW_DIGEST);
1547                         /* XXX pass_wall */
1548                         if (creature_ptr->lev > 34)
1549                                 add_flag(flgs, TR_TELEPATHY);
1550                         break;
1551                 case RACE_SPRITE:
1552                         add_flag(flgs, TR_RES_LITE);
1553                         add_flag(flgs, TR_LEVITATION);
1554                         if (creature_ptr->lev > 9)
1555                                 add_flag(flgs, TR_SPEED);
1556                         break;
1557                 case RACE_BEASTMAN:
1558                         add_flag(flgs, TR_RES_SOUND);
1559                         add_flag(flgs, TR_RES_CONF);
1560                         break;
1561                 case RACE_ANGEL:
1562                         add_flag(flgs, TR_LEVITATION);
1563                         add_flag(flgs, TR_SEE_INVIS);
1564                         break;
1565                 case RACE_DEMON:
1566                         add_flag(flgs, TR_RES_FIRE);
1567                         add_flag(flgs, TR_RES_NETHER);
1568                         add_flag(flgs, TR_HOLD_EXP);
1569                         if (creature_ptr->lev > 9)
1570                                 add_flag(flgs, TR_SEE_INVIS);
1571                         break;
1572                 case RACE_DUNADAN:
1573                         add_flag(flgs, TR_SUST_CON);
1574                         break;
1575                 case RACE_S_FAIRY:
1576                         add_flag(flgs, TR_LEVITATION);
1577                         break;
1578                 case RACE_KUTAR:
1579                         add_flag(flgs, TR_RES_CONF);
1580                         break;
1581                 case RACE_ANDROID:
1582                         add_flag(flgs, TR_FREE_ACT);
1583                         add_flag(flgs, TR_RES_POIS);
1584                         add_flag(flgs, TR_SLOW_DIGEST);
1585                         add_flag(flgs, TR_HOLD_EXP);
1586                         break;
1587                 default:
1588                         ; /* Do nothing */
1589                 }
1590         }
1591
1592         /* Mutations */
1593         if (creature_ptr->muta3)
1594         {
1595                 if (creature_ptr->muta3 & MUT3_FLESH_ROT)
1596                 {
1597                         remove_flag(flgs, TR_REGEN);
1598                 }
1599
1600                 if ((creature_ptr->muta3 & MUT3_XTRA_FAT) ||
1601                         (creature_ptr->muta3 & MUT3_XTRA_LEGS) ||
1602                         (creature_ptr->muta3 & MUT3_SHORT_LEG))
1603                 {
1604                         add_flag(flgs, TR_SPEED);
1605                 }
1606
1607                 if (creature_ptr->muta3  & MUT3_ELEC_TOUC)
1608                 {
1609                         add_flag(flgs, TR_SH_ELEC);
1610                 }
1611
1612                 if (creature_ptr->muta3 & MUT3_FIRE_BODY)
1613                 {
1614                         add_flag(flgs, TR_SH_FIRE);
1615                         add_flag(flgs, TR_LITE_1);
1616                 }
1617
1618                 if (creature_ptr->muta3 & MUT3_WINGS)
1619                 {
1620                         add_flag(flgs, TR_LEVITATION);
1621                 }
1622
1623                 if (creature_ptr->muta3 & MUT3_FEARLESS)
1624                 {
1625                         add_flag(flgs, TR_RES_FEAR);
1626                 }
1627
1628                 if (creature_ptr->muta3 & MUT3_REGEN)
1629                 {
1630                         add_flag(flgs, TR_REGEN);
1631                 }
1632
1633                 if (creature_ptr->muta3 & MUT3_ESP)
1634                 {
1635                         add_flag(flgs, TR_TELEPATHY);
1636                 }
1637
1638                 if (creature_ptr->muta3 & MUT3_MOTION)
1639                 {
1640                         add_flag(flgs, TR_FREE_ACT);
1641                 }
1642         }
1643
1644         if (creature_ptr->pseikaku == SEIKAKU_SEXY)
1645                 add_flag(flgs, TR_AGGRAVATE);
1646         if (creature_ptr->pseikaku == SEIKAKU_CHARGEMAN)
1647                 add_flag(flgs, TR_RES_CONF);
1648         if (creature_ptr->pseikaku == SEIKAKU_MUNCHKIN)
1649         {
1650                 add_flag(flgs, TR_RES_BLIND);
1651                 add_flag(flgs, TR_RES_CONF);
1652                 add_flag(flgs, TR_HOLD_EXP);
1653                 if (creature_ptr->pclass != CLASS_NINJA) add_flag(flgs, TR_LITE_1);
1654                 if (creature_ptr->lev > 9)
1655                         add_flag(flgs, TR_SPEED);
1656         }
1657
1658         if (creature_ptr->special_defense & KATA_FUUJIN)
1659                 add_flag(flgs, TR_REFLECT);
1660
1661         if (creature_ptr->special_defense & KAMAE_GENBU)
1662                 add_flag(flgs, TR_REFLECT);
1663
1664         if (creature_ptr->special_defense & KAMAE_SUZAKU)
1665                 add_flag(flgs, TR_LEVITATION);
1666
1667         if (creature_ptr->special_defense & KAMAE_SEIRYU)
1668         {
1669                 add_flag(flgs, TR_RES_FIRE);
1670                 add_flag(flgs, TR_RES_COLD);
1671                 add_flag(flgs, TR_RES_ACID);
1672                 add_flag(flgs, TR_RES_ELEC);
1673                 add_flag(flgs, TR_RES_POIS);
1674                 add_flag(flgs, TR_LEVITATION);
1675                 add_flag(flgs, TR_SH_FIRE);
1676                 add_flag(flgs, TR_SH_ELEC);
1677                 add_flag(flgs, TR_SH_COLD);
1678         }
1679
1680         if (creature_ptr->special_defense & KATA_MUSOU)
1681         {
1682                 add_flag(flgs, TR_RES_FEAR);
1683                 add_flag(flgs, TR_RES_LITE);
1684                 add_flag(flgs, TR_RES_DARK);
1685                 add_flag(flgs, TR_RES_BLIND);
1686                 add_flag(flgs, TR_RES_CONF);
1687                 add_flag(flgs, TR_RES_SOUND);
1688                 add_flag(flgs, TR_RES_SHARDS);
1689                 add_flag(flgs, TR_RES_NETHER);
1690                 add_flag(flgs, TR_RES_NEXUS);
1691                 add_flag(flgs, TR_RES_CHAOS);
1692                 add_flag(flgs, TR_RES_DISEN);
1693                 add_flag(flgs, TR_REFLECT);
1694                 add_flag(flgs, TR_HOLD_EXP);
1695                 add_flag(flgs, TR_FREE_ACT);
1696                 add_flag(flgs, TR_SH_FIRE);
1697                 add_flag(flgs, TR_SH_ELEC);
1698                 add_flag(flgs, TR_SH_COLD);
1699                 add_flag(flgs, TR_LEVITATION);
1700                 add_flag(flgs, TR_LITE_1);
1701                 add_flag(flgs, TR_SEE_INVIS);
1702                 add_flag(flgs, TR_TELEPATHY);
1703                 add_flag(flgs, TR_SLOW_DIGEST);
1704                 add_flag(flgs, TR_REGEN);
1705                 add_flag(flgs, TR_SUST_STR);
1706                 add_flag(flgs, TR_SUST_INT);
1707                 add_flag(flgs, TR_SUST_WIS);
1708                 add_flag(flgs, TR_SUST_DEX);
1709                 add_flag(flgs, TR_SUST_CON);
1710                 add_flag(flgs, TR_SUST_CHR);
1711         }
1712 }
1713
1714
1715 /*!
1716  * @brief プレイヤーの一時的魔法効果による耐性を返す
1717  * Prints ratings on certain abilities
1718  * @param creature_ptr プレーヤーへの参照ポインタ
1719  * @param flgs フラグを保管する配列
1720  * @return なし
1721  * @todo
1722  * xtra1.c周りと多重実装になっているのを何とかする
1723  */
1724 static void tim_player_flags(player_type *creature_ptr, BIT_FLAGS flgs[TR_FLAG_SIZE])
1725 {
1726         for (int i = 0; i < TR_FLAG_SIZE; i++)
1727                 flgs[i] = 0L;
1728
1729         if (IS_HERO(creature_ptr) || creature_ptr->shero)
1730                 add_flag(flgs, TR_RES_FEAR);
1731         if (creature_ptr->tim_invis)
1732                 add_flag(flgs, TR_SEE_INVIS);
1733         if (creature_ptr->tim_regen)
1734                 add_flag(flgs, TR_REGEN);
1735         if (is_time_limit_esp(creature_ptr))
1736                 add_flag(flgs, TR_TELEPATHY);
1737         if (IS_FAST(creature_ptr) || creature_ptr->slow)
1738                 add_flag(flgs, TR_SPEED);
1739
1740         if (is_oppose_acid(creature_ptr) && !(creature_ptr->special_defense & DEFENSE_ACID) && !(PRACE_IS_(creature_ptr, RACE_YEEK) && (creature_ptr->lev > 19)))
1741                 add_flag(flgs, TR_RES_ACID);
1742         if (is_oppose_elec(creature_ptr) && !(creature_ptr->special_defense & DEFENSE_ELEC))
1743                 add_flag(flgs, TR_RES_ELEC);
1744         if (is_oppose_fire(creature_ptr) && !(creature_ptr->special_defense & DEFENSE_FIRE))
1745                 add_flag(flgs, TR_RES_FIRE);
1746         if (is_oppose_cold(creature_ptr) && !(creature_ptr->special_defense & DEFENSE_COLD))
1747                 add_flag(flgs, TR_RES_COLD);
1748         if (is_oppose_pois(creature_ptr))
1749                 add_flag(flgs, TR_RES_POIS);
1750
1751         if (creature_ptr->special_attack & ATTACK_ACID)
1752                 add_flag(flgs, TR_BRAND_ACID);
1753         if (creature_ptr->special_attack & ATTACK_ELEC)
1754                 add_flag(flgs, TR_BRAND_ELEC);
1755         if (creature_ptr->special_attack & ATTACK_FIRE)
1756                 add_flag(flgs, TR_BRAND_FIRE);
1757         if (creature_ptr->special_attack & ATTACK_COLD)
1758                 add_flag(flgs, TR_BRAND_COLD);
1759         if (creature_ptr->special_attack & ATTACK_POIS)
1760                 add_flag(flgs, TR_BRAND_POIS);
1761         if (creature_ptr->special_defense & DEFENSE_ACID)
1762                 add_flag(flgs, TR_IM_ACID);
1763         if (creature_ptr->special_defense & DEFENSE_ELEC)
1764                 add_flag(flgs, TR_IM_ELEC);
1765         if (creature_ptr->special_defense & DEFENSE_FIRE)
1766                 add_flag(flgs, TR_IM_FIRE);
1767         if (creature_ptr->special_defense & DEFENSE_COLD)
1768                 add_flag(flgs, TR_IM_COLD);
1769         if (creature_ptr->wraith_form)
1770                 add_flag(flgs, TR_REFLECT);
1771         if (creature_ptr->tim_reflect)
1772                 add_flag(flgs, TR_REFLECT);
1773
1774         if (creature_ptr->magicdef)
1775         {
1776                 add_flag(flgs, TR_RES_BLIND);
1777                 add_flag(flgs, TR_RES_CONF);
1778                 add_flag(flgs, TR_REFLECT);
1779                 add_flag(flgs, TR_FREE_ACT);
1780                 add_flag(flgs, TR_LEVITATION);
1781         }
1782
1783         if (creature_ptr->tim_res_nether) add_flag(flgs, TR_RES_NETHER);
1784
1785         if (creature_ptr->tim_sh_fire) add_flag(flgs, TR_SH_FIRE);
1786
1787         if (creature_ptr->ult_res)
1788         {
1789                 add_flag(flgs, TR_RES_FEAR);
1790                 add_flag(flgs, TR_RES_LITE);
1791                 add_flag(flgs, TR_RES_DARK);
1792                 add_flag(flgs, TR_RES_BLIND);
1793                 add_flag(flgs, TR_RES_CONF);
1794                 add_flag(flgs, TR_RES_SOUND);
1795                 add_flag(flgs, TR_RES_SHARDS);
1796                 add_flag(flgs, TR_RES_NETHER);
1797                 add_flag(flgs, TR_RES_NEXUS);
1798                 add_flag(flgs, TR_RES_CHAOS);
1799                 add_flag(flgs, TR_RES_DISEN);
1800                 add_flag(flgs, TR_REFLECT);
1801                 add_flag(flgs, TR_HOLD_EXP);
1802                 add_flag(flgs, TR_FREE_ACT);
1803                 add_flag(flgs, TR_SH_FIRE);
1804                 add_flag(flgs, TR_SH_ELEC);
1805                 add_flag(flgs, TR_SH_COLD);
1806                 add_flag(flgs, TR_LEVITATION);
1807                 add_flag(flgs, TR_LITE_1);
1808                 add_flag(flgs, TR_SEE_INVIS);
1809                 add_flag(flgs, TR_TELEPATHY);
1810                 add_flag(flgs, TR_SLOW_DIGEST);
1811                 add_flag(flgs, TR_REGEN);
1812                 add_flag(flgs, TR_SUST_STR);
1813                 add_flag(flgs, TR_SUST_INT);
1814                 add_flag(flgs, TR_SUST_WIS);
1815                 add_flag(flgs, TR_SUST_DEX);
1816                 add_flag(flgs, TR_SUST_CON);
1817                 add_flag(flgs, TR_SUST_CHR);
1818         }
1819
1820         if (creature_ptr->realm1 != REALM_HEX) return;
1821
1822         if (hex_spelling(creature_ptr, HEX_DEMON_AURA))
1823         {
1824                 add_flag(flgs, TR_SH_FIRE);
1825                 add_flag(flgs, TR_REGEN);
1826         }
1827
1828         if (hex_spelling(creature_ptr, HEX_ICE_ARMOR)) add_flag(flgs, TR_SH_COLD);
1829         if (hex_spelling(creature_ptr, HEX_SHOCK_CLOAK)) add_flag(flgs, TR_SH_ELEC);
1830 }
1831
1832
1833 /*!
1834  * @brief プレイヤーの装備一覧をシンボルで並べる
1835  * Equippy chars
1836  * @param creature_ptr プレーヤーへの参照ポインタ
1837  * @param y 表示するコンソールの行
1838  * @param x 表示するコンソールの列
1839  * @param mode オプション
1840  * @return なし
1841  */
1842 void display_player_equippy(player_type *creature_ptr, TERM_LEN y, TERM_LEN x, BIT_FLAGS16 mode)
1843 {
1844         /* Weapon flags need only two column */
1845         int max_i = (mode & DP_WP) ? INVEN_LARM + 1 : INVEN_TOTAL;
1846
1847         /* Dump equippy chars */
1848         for (int i = INVEN_RARM; i < max_i; i++)
1849         {
1850                 object_type *o_ptr;
1851                 o_ptr = &creature_ptr->inventory_list[i];
1852
1853                 TERM_COLOR a = object_attr(o_ptr);
1854                 char c = object_char(o_ptr);
1855
1856                 if (!equippy_chars || !o_ptr->k_idx)
1857                 {
1858                         c = ' ';
1859                         a = TERM_DARK;
1860                 }
1861
1862                 Term_putch(x + i - INVEN_RARM, y, a, c);
1863         }
1864 }
1865
1866
1867 /*!
1868  * @brief プレイヤーの装備による免疫フラグを返す
1869  * @param creature_ptr プレーヤーへの参照ポインタ
1870  * @param flgs フラグを保管する配列
1871  * @return なし
1872  * @todo
1873  * xtra1.c周りと多重実装になっているのを何とかする
1874  */
1875 static void known_obj_immunity(player_type *creature_ptr, BIT_FLAGS flgs[TR_FLAG_SIZE])
1876 {
1877         for (int i = 0; i < TR_FLAG_SIZE; i++)
1878                 flgs[i] = 0L;
1879
1880         for (int i = INVEN_RARM; i < INVEN_TOTAL; i++)
1881         {
1882                 u32b o_flgs[TR_FLAG_SIZE];
1883                 object_type *o_ptr;
1884                 o_ptr = &creature_ptr->inventory_list[i];
1885                 if (!o_ptr->k_idx) continue;
1886
1887                 object_flags_known(o_ptr, o_flgs);
1888                 if (have_flag(o_flgs, TR_IM_ACID)) add_flag(flgs, TR_RES_ACID);
1889                 if (have_flag(o_flgs, TR_IM_ELEC)) add_flag(flgs, TR_RES_ELEC);
1890                 if (have_flag(o_flgs, TR_IM_FIRE)) add_flag(flgs, TR_RES_FIRE);
1891                 if (have_flag(o_flgs, TR_IM_COLD)) add_flag(flgs, TR_RES_COLD);
1892         }
1893 }
1894
1895
1896 /*!
1897  * @brief プレイヤーの種族による免疫フラグを返す
1898  * @param creature_ptr プレーヤーへの参照ポインタ
1899  * @param flgs フラグを保管する配列
1900  * @return なし
1901  * @todo
1902  * xtra1.c周りと多重実装になっているのを何とかする
1903  */
1904 static void player_immunity(player_type *creature_ptr, BIT_FLAGS flgs[TR_FLAG_SIZE])
1905 {
1906         for (int i = 0; i < TR_FLAG_SIZE; i++)
1907                 flgs[i] = 0L;
1908
1909         if (PRACE_IS_(creature_ptr, RACE_SPECTRE))
1910                 add_flag(flgs, TR_RES_NETHER);
1911         if (creature_ptr->mimic_form == MIMIC_VAMPIRE || PRACE_IS_(creature_ptr, RACE_VAMPIRE))
1912                 add_flag(flgs, TR_RES_DARK);
1913         if (creature_ptr->mimic_form == MIMIC_DEMON_LORD)
1914                 add_flag(flgs, TR_RES_FIRE);
1915         else if (PRACE_IS_(creature_ptr, RACE_YEEK) && creature_ptr->lev > 19)
1916                 add_flag(flgs, TR_RES_ACID);
1917 }
1918
1919
1920 /*!
1921  * @brief プレイヤーの一時的魔法効果による免疫フラグを返す
1922  * @param creature_ptr プレーヤーへの参照ポインタ
1923  * @param flgs フラグを保管する配列
1924  * @return なし
1925  * @todo
1926  * xtra1.c周りと多重実装になっているのを何とかする
1927  */
1928 static void tim_player_immunity(player_type *creature_ptr, BIT_FLAGS flgs[TR_FLAG_SIZE])
1929 {
1930         for (int i = 0; i < TR_FLAG_SIZE; i++)
1931                 flgs[i] = 0L;
1932
1933         if (creature_ptr->special_defense & DEFENSE_ACID)
1934                 add_flag(flgs, TR_RES_ACID);
1935         if (creature_ptr->special_defense & DEFENSE_ELEC)
1936                 add_flag(flgs, TR_RES_ELEC);
1937         if (creature_ptr->special_defense & DEFENSE_FIRE)
1938                 add_flag(flgs, TR_RES_FIRE);
1939         if (creature_ptr->special_defense & DEFENSE_COLD)
1940                 add_flag(flgs, TR_RES_COLD);
1941         if (creature_ptr->wraith_form)
1942                 add_flag(flgs, TR_RES_DARK);
1943 }
1944
1945
1946 /*!
1947  * @brief プレイヤーの種族による弱点フラグを返す
1948  * @param creature_ptr プレーヤーへの参照ポインタ
1949  * @param flgs フラグを保管する配列
1950  * @return なし
1951  * @todo
1952  * xtra1.c周りと多重実装になっているのを何とかする
1953  */
1954 static void player_vuln_flags(player_type *creature_ptr, BIT_FLAGS flgs[TR_FLAG_SIZE])
1955 {
1956         for (int i = 0; i < TR_FLAG_SIZE; i++)
1957                 flgs[i] = 0L;
1958
1959         if ((creature_ptr->muta3 & MUT3_VULN_ELEM) || (creature_ptr->special_defense & KATA_KOUKIJIN))
1960         {
1961                 add_flag(flgs, TR_RES_ACID);
1962                 add_flag(flgs, TR_RES_ELEC);
1963                 add_flag(flgs, TR_RES_FIRE);
1964                 add_flag(flgs, TR_RES_COLD);
1965         }
1966
1967         if (PRACE_IS_(creature_ptr, RACE_ANDROID))
1968                 add_flag(flgs, TR_RES_ELEC);
1969         if (PRACE_IS_(creature_ptr, RACE_ENT))
1970                 add_flag(flgs, TR_RES_FIRE);
1971         if (PRACE_IS_(creature_ptr, RACE_VAMPIRE) || PRACE_IS_(creature_ptr, RACE_S_FAIRY) ||
1972                 (creature_ptr->mimic_form == MIMIC_VAMPIRE))
1973                 add_flag(flgs, TR_RES_LITE);
1974 }
1975
1976
1977 /*
1978  * A struct for storing misc. flags
1979  */
1980 typedef struct {
1981         BIT_FLAGS player_flags[TR_FLAG_SIZE];
1982         BIT_FLAGS tim_player_flags[TR_FLAG_SIZE];
1983         BIT_FLAGS player_imm[TR_FLAG_SIZE];
1984         BIT_FLAGS tim_player_imm[TR_FLAG_SIZE];
1985         BIT_FLAGS player_vuln[TR_FLAG_SIZE];
1986         BIT_FLAGS known_obj_imm[TR_FLAG_SIZE];
1987 } all_player_flags;
1988
1989 /*!
1990  * @brief プレイヤーの特性フラグ一種を表示するサブルーチン /
1991  * Helper function, see below
1992  * @param creature_ptr プレーヤーへの参照ポインタ
1993  * @param row コンソール表示位置の左上行
1994  * @param col コンソール表示位置の左上列
1995  * @param header コンソール上で表示する特性名
1996  * @param flag1 参照する特性ID
1997  * @param f プレイヤーの特性情報構造体
1998  * @param mode 表示オプション
1999  * @return なし
2000  */
2001 static void display_flag_aux(player_type *creature_ptr, TERM_LEN row, TERM_LEN col, concptr header, int flag1, all_player_flags *f, u16b mode)
2002 {
2003         byte header_color = TERM_L_DARK;
2004         int header_col = col;
2005
2006         bool vuln = FALSE;
2007         if (have_flag(f->player_vuln, flag1) &&
2008                 !(have_flag(f->known_obj_imm, flag1) ||
2009                         have_flag(f->player_imm, flag1) ||
2010                         have_flag(f->tim_player_imm, flag1)))
2011                 vuln = TRUE;
2012
2013         col += strlen(header) + 1;
2014
2015         /* Weapon flags need only two column */
2016         int max_i = (mode & DP_WP) ? INVEN_LARM + 1 : INVEN_TOTAL;
2017
2018         for (int i = INVEN_RARM; i < max_i; i++)
2019         {
2020                 BIT_FLAGS flgs[TR_FLAG_SIZE];
2021                 object_type *o_ptr;
2022                 o_ptr = &creature_ptr->inventory_list[i];
2023                 object_flags_known(o_ptr, flgs);
2024                 if (!(mode & DP_IMM))
2025                         c_put_str((byte)(vuln ? TERM_RED : TERM_SLATE), ".", row, col);
2026
2027                 if (mode & DP_CURSE)
2028                 {
2029                         if (have_flag(flgs, TR_ADD_L_CURSE) || have_flag(flgs, TR_ADD_H_CURSE))
2030                         {
2031                                 c_put_str(TERM_L_DARK, "+", row, col);
2032                                 header_color = TERM_WHITE;
2033                         }
2034
2035                         if (o_ptr->curse_flags & (TRC_CURSED | TRC_HEAVY_CURSE))
2036                         {
2037                                 c_put_str(TERM_WHITE, "+", row, col);
2038                                 header_color = TERM_WHITE;
2039                         }
2040
2041                         if (o_ptr->curse_flags & TRC_PERMA_CURSE)
2042                         {
2043                                 c_put_str(TERM_WHITE, "*", row, col);
2044                                 header_color = TERM_WHITE;
2045                         }
2046
2047                         col++;
2048                         continue;
2049                 }
2050
2051                 if (flag1 == TR_LITE_1)
2052                 {
2053                         if (HAVE_DARK_FLAG(flgs))
2054                         {
2055                                 c_put_str(TERM_L_DARK, "+", row, col);
2056                                 header_color = TERM_WHITE;
2057                         }
2058                         else if (HAVE_LITE_FLAG(flgs))
2059                         {
2060                                 c_put_str(TERM_WHITE, "+", row, col);
2061                                 header_color = TERM_WHITE;
2062                         }
2063
2064                         col++;
2065                         continue;
2066                 }
2067
2068                 if (have_flag(flgs, flag1))
2069                 {
2070                         c_put_str((byte)(vuln ? TERM_L_RED : TERM_WHITE),
2071                                 (mode & DP_IMM) ? "*" : "+", row, col);
2072                         header_color = TERM_WHITE;
2073                 }
2074
2075                 col++;
2076         }
2077
2078         if (mode & DP_IMM)
2079         {
2080                 if (header_color != TERM_L_DARK)
2081                 {
2082                         c_put_str(header_color, header, row, header_col);
2083                 }
2084
2085                 return;
2086         }
2087
2088         c_put_str((byte)(vuln ? TERM_RED : TERM_SLATE), ".", row, col);
2089         if (have_flag(f->player_flags, flag1))
2090         {
2091                 c_put_str((byte)(vuln ? TERM_L_RED : TERM_WHITE), "+", row, col);
2092                 header_color = TERM_WHITE;
2093         }
2094
2095         if (have_flag(f->tim_player_flags, flag1))
2096         {
2097                 c_put_str((byte)(vuln ? TERM_ORANGE : TERM_YELLOW), "#", row, col);
2098                 header_color = TERM_WHITE;
2099         }
2100
2101         if (have_flag(f->tim_player_imm, flag1))
2102         {
2103                 c_put_str(TERM_YELLOW, "*", row, col);
2104                 header_color = TERM_WHITE;
2105         }
2106
2107         if (have_flag(f->player_imm, flag1))
2108         {
2109                 c_put_str(TERM_WHITE, "*", row, col);
2110                 header_color = TERM_WHITE;
2111         }
2112
2113         if (vuln) c_put_str(TERM_RED, "v", row, col + 1);
2114         c_put_str(header_color, header, row, header_col);
2115 }
2116
2117
2118 /*!
2119  * @brief プレイヤーの特性フラグ一覧表示1 /
2120  * @param creature_ptr プレーヤーへの参照ポインタ
2121  * Special display, part 1
2122  * @return なし
2123  */
2124 static void display_player_flag_info(player_type *creature_ptr)
2125 {
2126         all_player_flags f;
2127         player_flags(creature_ptr, f.player_flags);
2128         tim_player_flags(creature_ptr, f.tim_player_flags);
2129         player_immunity(creature_ptr, f.player_imm);
2130         tim_player_immunity(creature_ptr, f.tim_player_imm);
2131         known_obj_immunity(creature_ptr, f.known_obj_imm);
2132         player_vuln_flags(creature_ptr, f.player_vuln);
2133
2134         /*** Set 1 ***/
2135         TERM_LEN row = 12;
2136         TERM_LEN col = 1;
2137         display_player_equippy(creature_ptr, row - 2, col + 8, 0);
2138         c_put_str(TERM_WHITE, "abcdefghijkl@", row - 1, col + 8);
2139
2140 #ifdef JP
2141         display_flag_aux(creature_ptr, row + 0, col, "耐酸  :", TR_RES_ACID, &f, 0);
2142         display_flag_aux(creature_ptr, row + 0, col, "耐酸  :", TR_IM_ACID, &f, DP_IMM);
2143         display_flag_aux(creature_ptr, row + 1, col, "耐電撃:", TR_RES_ELEC, &f, 0);
2144         display_flag_aux(creature_ptr, row + 1, col, "耐電撃:", TR_IM_ELEC, &f, DP_IMM);
2145         display_flag_aux(creature_ptr, row + 2, col, "耐火炎:", TR_RES_FIRE, &f, 0);
2146         display_flag_aux(creature_ptr, row + 2, col, "耐火炎:", TR_IM_FIRE, &f, DP_IMM);
2147         display_flag_aux(creature_ptr, row + 3, col, "耐冷気:", TR_RES_COLD, &f, 0);
2148         display_flag_aux(creature_ptr, row + 3, col, "耐冷気:", TR_IM_COLD, &f, DP_IMM);
2149         display_flag_aux(creature_ptr, row + 4, col, "耐毒  :", TR_RES_POIS, &f, 0);
2150         display_flag_aux(creature_ptr, row + 5, col, "耐閃光:", TR_RES_LITE, &f, 0);
2151         display_flag_aux(creature_ptr, row + 6, col, "耐暗黒:", TR_RES_DARK, &f, 0);
2152         display_flag_aux(creature_ptr, row + 7, col, "耐破片:", TR_RES_SHARDS, &f, 0);
2153         display_flag_aux(creature_ptr, row + 8, col, "耐盲目:", TR_RES_BLIND, &f, 0);
2154         display_flag_aux(creature_ptr, row + 9, col, "耐混乱:", TR_RES_CONF, &f, 0);
2155 #else
2156         display_flag_aux(creature_ptr, row + 0, col, "Acid  :", TR_RES_ACID, &f, 0);
2157         display_flag_aux(creature_ptr, row + 0, col, "Acid  :", TR_IM_ACID, &f, DP_IMM);
2158         display_flag_aux(creature_ptr, row + 1, col, "Elec  :", TR_RES_ELEC, &f, 0);
2159         display_flag_aux(creature_ptr, row + 1, col, "Elec  :", TR_IM_ELEC, &f, DP_IMM);
2160         display_flag_aux(creature_ptr, row + 2, col, "Fire  :", TR_RES_FIRE, &f, 0);
2161         display_flag_aux(creature_ptr, row + 2, col, "Fire  :", TR_IM_FIRE, &f, DP_IMM);
2162         display_flag_aux(creature_ptr, row + 3, col, "Cold  :", TR_RES_COLD, &f, 0);
2163         display_flag_aux(creature_ptr, row + 3, col, "Cold  :", TR_IM_COLD, &f, DP_IMM);
2164         display_flag_aux(creature_ptr, row + 4, col, "Poison:", TR_RES_POIS, &f, 0);
2165         display_flag_aux(creature_ptr, row + 5, col, "Light :", TR_RES_LITE, &f, 0);
2166         display_flag_aux(creature_ptr, row + 6, col, "Dark  :", TR_RES_DARK, &f, 0);
2167         display_flag_aux(creature_ptr, row + 7, col, "Shard :", TR_RES_SHARDS, &f, 0);
2168         display_flag_aux(creature_ptr, row + 8, col, "Blind :", TR_RES_BLIND, &f, 0);
2169         display_flag_aux(creature_ptr, row + 9, col, "Conf  :", TR_RES_CONF, &f, 0);
2170 #endif
2171
2172         /*** Set 2 ***/
2173         row = 12;
2174         col = 26;
2175         display_player_equippy(creature_ptr, row - 2, col + 8, 0);
2176         c_put_str(TERM_WHITE, "abcdefghijkl@", row - 1, col + 8);
2177
2178 #ifdef JP
2179         display_flag_aux(creature_ptr, row + 0, col, "耐轟音:", TR_RES_SOUND, &f, 0);
2180         display_flag_aux(creature_ptr, row + 1, col, "耐地獄:", TR_RES_NETHER, &f, 0);
2181         display_flag_aux(creature_ptr, row + 2, col, "耐因混:", TR_RES_NEXUS, &f, 0);
2182         display_flag_aux(creature_ptr, row + 3, col, "耐カオ:", TR_RES_CHAOS, &f, 0);
2183         display_flag_aux(creature_ptr, row + 4, col, "耐劣化:", TR_RES_DISEN, &f, 0);
2184         display_flag_aux(creature_ptr, row + 5, col, "耐恐怖:", TR_RES_FEAR, &f, 0);
2185         display_flag_aux(creature_ptr, row + 6, col, "反射  :", TR_REFLECT, &f, 0);
2186         display_flag_aux(creature_ptr, row + 7, col, "火炎オ:", TR_SH_FIRE, &f, 0);
2187         display_flag_aux(creature_ptr, row + 8, col, "電気オ:", TR_SH_ELEC, &f, 0);
2188         display_flag_aux(creature_ptr, row + 9, col, "冷気オ:", TR_SH_COLD, &f, 0);
2189 #else
2190         display_flag_aux(creature_ptr, row + 0, col, "Sound :", TR_RES_SOUND, &f, 0);
2191         display_flag_aux(creature_ptr, row + 1, col, "Nether:", TR_RES_NETHER, &f, 0);
2192         display_flag_aux(creature_ptr, row + 2, col, "Nexus :", TR_RES_NEXUS, &f, 0);
2193         display_flag_aux(creature_ptr, row + 3, col, "Chaos :", TR_RES_CHAOS, &f, 0);
2194         display_flag_aux(creature_ptr, row + 4, col, "Disnch:", TR_RES_DISEN, &f, 0);
2195         display_flag_aux(creature_ptr, row + 5, col, "Fear  :", TR_RES_FEAR, &f, 0);
2196         display_flag_aux(creature_ptr, row + 6, col, "Reflct:", TR_REFLECT, &f, 0);
2197         display_flag_aux(creature_ptr, row + 7, col, "AuFire:", TR_SH_FIRE, &f, 0);
2198         display_flag_aux(creature_ptr, row + 8, col, "AuElec:", TR_SH_ELEC, &f, 0);
2199         display_flag_aux(creature_ptr, row + 9, col, "AuCold:", TR_SH_COLD, &f, 0);
2200 #endif
2201
2202         /*** Set 3 ***/
2203         row = 12;
2204         col = 51;
2205         display_player_equippy(creature_ptr, row - 2, col + 12, 0);
2206         c_put_str(TERM_WHITE, "abcdefghijkl@", row - 1, col + 12);
2207
2208 #ifdef JP
2209         display_flag_aux(creature_ptr, row + 0, col, "加速      :", TR_SPEED, &f, 0);
2210         display_flag_aux(creature_ptr, row + 1, col, "耐麻痺    :", TR_FREE_ACT, &f, 0);
2211         display_flag_aux(creature_ptr, row + 2, col, "透明体視認:", TR_SEE_INVIS, &f, 0);
2212         display_flag_aux(creature_ptr, row + 3, col, "経験値保持:", TR_HOLD_EXP, &f, 0);
2213         display_flag_aux(creature_ptr, row + 4, col, "警告      :", TR_WARNING, &f, 0);
2214         display_flag_aux(creature_ptr, row + 5, col, "遅消化    :", TR_SLOW_DIGEST, &f, 0);
2215         display_flag_aux(creature_ptr, row + 6, col, "急回復    :", TR_REGEN, &f, 0);
2216         display_flag_aux(creature_ptr, row + 7, col, "浮遊      :", TR_LEVITATION, &f, 0);
2217         display_flag_aux(creature_ptr, row + 8, col, "永遠光源  :", TR_LITE_1, &f, 0);
2218         display_flag_aux(creature_ptr, row + 9, col, "呪い      :", 0, &f, DP_CURSE);
2219 #else
2220         display_flag_aux(creature_ptr, row + 0, col, "Speed     :", TR_SPEED, &f, 0);
2221         display_flag_aux(creature_ptr, row + 1, col, "FreeAction:", TR_FREE_ACT, &f, 0);
2222         display_flag_aux(creature_ptr, row + 2, col, "SeeInvisi.:", TR_SEE_INVIS, &f, 0);
2223         display_flag_aux(creature_ptr, row + 3, col, "Hold Exp  :", TR_HOLD_EXP, &f, 0);
2224         display_flag_aux(creature_ptr, row + 4, col, "Warning   :", TR_WARNING, &f, 0);
2225         display_flag_aux(creature_ptr, row + 5, col, "SlowDigest:", TR_SLOW_DIGEST, &f, 0);
2226         display_flag_aux(creature_ptr, row + 6, col, "Regene.   :", TR_REGEN, &f, 0);
2227         display_flag_aux(creature_ptr, row + 7, col, "Levitation:", TR_LEVITATION, &f, 0);
2228         display_flag_aux(creature_ptr, row + 8, col, "Perm Lite :", TR_LITE_1, &f, 0);
2229         display_flag_aux(creature_ptr, row + 9, col, "Cursed    :", 0, &f, DP_CURSE);
2230 #endif
2231 }
2232
2233
2234 /*!
2235  * @brief プレイヤーの特性フラグ一覧表示2 /
2236  * @param creature_ptr プレーヤーへの参照ポインタ
2237  * Special display, part 2
2238  * @return なし
2239  */
2240 static void display_player_other_flag_info(player_type *creature_ptr)
2241 {
2242         /* Extract flags and store */
2243         all_player_flags f;
2244         player_flags(creature_ptr, f.player_flags);
2245         tim_player_flags(creature_ptr, f.tim_player_flags);
2246         player_immunity(creature_ptr, f.player_imm);
2247         tim_player_immunity(creature_ptr, f.tim_player_imm);
2248         known_obj_immunity(creature_ptr, f.known_obj_imm);
2249         player_vuln_flags(creature_ptr, f.player_vuln);
2250
2251         /*** Set 1 ***/
2252         TERM_LEN row = 3;
2253         TERM_LEN col = 1;
2254         display_player_equippy(creature_ptr, row - 2, col + 12, DP_WP);
2255         c_put_str(TERM_WHITE, "ab@", row - 1, col + 12);
2256
2257 #ifdef JP
2258         display_flag_aux(creature_ptr, row + 0, col, "邪悪 倍打 :", TR_SLAY_EVIL, &f, DP_WP);
2259         display_flag_aux(creature_ptr, row + 0, col, "邪悪 倍打 :", TR_KILL_EVIL, &f, (DP_WP | DP_IMM));
2260         display_flag_aux(creature_ptr, row + 1, col, "不死 倍打 :", TR_SLAY_UNDEAD, &f, DP_WP);
2261         display_flag_aux(creature_ptr, row + 1, col, "不死 倍打 :", TR_KILL_UNDEAD, &f, (DP_WP | DP_IMM));
2262         display_flag_aux(creature_ptr, row + 2, col, "悪魔 倍打 :", TR_SLAY_DEMON, &f, DP_WP);
2263         display_flag_aux(creature_ptr, row + 2, col, "悪魔 倍打 :", TR_KILL_DEMON, &f, (DP_WP | DP_IMM));
2264         display_flag_aux(creature_ptr, row + 3, col, "龍 倍打   :", TR_SLAY_DRAGON, &f, DP_WP);
2265         display_flag_aux(creature_ptr, row + 3, col, "龍 倍打   :", TR_KILL_DRAGON, &f, (DP_WP | DP_IMM));
2266         display_flag_aux(creature_ptr, row + 4, col, "人間 倍打 :", TR_SLAY_HUMAN, &f, DP_WP);
2267         display_flag_aux(creature_ptr, row + 4, col, "人間 倍打 :", TR_KILL_HUMAN, &f, (DP_WP | DP_IMM));
2268         display_flag_aux(creature_ptr, row + 5, col, "動物 倍打 :", TR_SLAY_ANIMAL, &f, DP_WP);
2269         display_flag_aux(creature_ptr, row + 5, col, "動物 倍打 :", TR_KILL_ANIMAL, &f, (DP_WP | DP_IMM));
2270         display_flag_aux(creature_ptr, row + 6, col, "オーク倍打:", TR_SLAY_ORC, &f, DP_WP);
2271         display_flag_aux(creature_ptr, row + 6, col, "オーク倍打:", TR_KILL_ORC, &f, (DP_WP | DP_IMM));
2272         display_flag_aux(creature_ptr, row + 7, col, "トロル倍打:", TR_SLAY_TROLL, &f, DP_WP);
2273         display_flag_aux(creature_ptr, row + 7, col, "トロル倍打:", TR_KILL_TROLL, &f, (DP_WP | DP_IMM));
2274         display_flag_aux(creature_ptr, row + 8, col, "巨人 倍打 :", TR_SLAY_GIANT, &f, DP_WP);
2275         display_flag_aux(creature_ptr, row + 8, col, "巨人 倍打 :", TR_KILL_GIANT, &f, (DP_WP | DP_IMM));
2276         display_flag_aux(creature_ptr, row + 9, col, "溶解      :", TR_BRAND_ACID, &f, DP_WP);
2277         display_flag_aux(creature_ptr, row + 10, col, "電撃      :", TR_BRAND_ELEC, &f, DP_WP);
2278         display_flag_aux(creature_ptr, row + 11, col, "焼棄      :", TR_BRAND_FIRE, &f, DP_WP);
2279         display_flag_aux(creature_ptr, row + 12, col, "凍結      :", TR_BRAND_COLD, &f, DP_WP);
2280         display_flag_aux(creature_ptr, row + 13, col, "毒殺      :", TR_BRAND_POIS, &f, DP_WP);
2281         display_flag_aux(creature_ptr, row + 14, col, "切れ味    :", TR_VORPAL, &f, DP_WP);
2282         display_flag_aux(creature_ptr, row + 15, col, "地震      :", TR_IMPACT, &f, DP_WP);
2283         display_flag_aux(creature_ptr, row + 16, col, "吸血      :", TR_VAMPIRIC, &f, DP_WP);
2284         display_flag_aux(creature_ptr, row + 17, col, "カオス効果:", TR_CHAOTIC, &f, DP_WP);
2285         display_flag_aux(creature_ptr, row + 18, col, "理力      :", TR_FORCE_WEAPON, &f, DP_WP);
2286 #else
2287         display_flag_aux(creature_ptr, row + 0, col, "Slay Evil :", TR_SLAY_EVIL, &f, DP_WP);
2288         display_flag_aux(creature_ptr, row + 0, col, "Slay Evil :", TR_KILL_EVIL, &f, (DP_WP | DP_IMM));
2289         display_flag_aux(creature_ptr, row + 1, col, "Slay Und. :", TR_SLAY_UNDEAD, &f, DP_WP);
2290         display_flag_aux(creature_ptr, row + 1, col, "Slay Und. :", TR_KILL_UNDEAD, &f, (DP_WP | DP_IMM));
2291         display_flag_aux(creature_ptr, row + 2, col, "Slay Demon:", TR_SLAY_DEMON, &f, DP_WP);
2292         display_flag_aux(creature_ptr, row + 2, col, "Slay Demon:", TR_KILL_DEMON, &f, (DP_WP | DP_IMM));
2293         display_flag_aux(creature_ptr, row + 3, col, "Slay Drag.:", TR_SLAY_DRAGON, &f, DP_WP);
2294         display_flag_aux(creature_ptr, row + 3, col, "Slay Drag.:", TR_KILL_DRAGON, &f, (DP_WP | DP_IMM));
2295         display_flag_aux(creature_ptr, row + 4, col, "Slay Human:", TR_SLAY_HUMAN, &f, DP_WP);
2296         display_flag_aux(creature_ptr, row + 4, col, "Slay Human:", TR_KILL_HUMAN, &f, (DP_WP | DP_IMM));
2297         display_flag_aux(creature_ptr, row + 5, col, "Slay Anim.:", TR_SLAY_ANIMAL, &f, DP_WP);
2298         display_flag_aux(creature_ptr, row + 5, col, "Slay Anim.:", TR_KILL_ANIMAL, &f, (DP_WP | DP_IMM));
2299         display_flag_aux(creature_ptr, row + 6, col, "Slay Orc  :", TR_SLAY_ORC, &f, DP_WP);
2300         display_flag_aux(creature_ptr, row + 6, col, "Slay Orc  :", TR_KILL_ORC, &f, (DP_WP | DP_IMM));
2301         display_flag_aux(creature_ptr, row + 7, col, "Slay Troll:", TR_SLAY_TROLL, &f, DP_WP);
2302         display_flag_aux(creature_ptr, row + 7, col, "Slay Troll:", TR_KILL_TROLL, &f, (DP_WP | DP_IMM));
2303         display_flag_aux(creature_ptr, row + 8, col, "Slay Giant:", TR_SLAY_GIANT, &f, DP_WP);
2304         display_flag_aux(creature_ptr, row + 8, col, "Slay Giant:", TR_KILL_GIANT, &f, (DP_WP | DP_IMM));
2305         display_flag_aux(creature_ptr, row + 9, col, "Acid Brand:", TR_BRAND_ACID, &f, DP_WP);
2306         display_flag_aux(creature_ptr, row + 10, col, "Elec Brand:", TR_BRAND_ELEC, &f, DP_WP);
2307         display_flag_aux(creature_ptr, row + 11, col, "Fire Brand:", TR_BRAND_FIRE, &f, DP_WP);
2308         display_flag_aux(creature_ptr, row + 12, col, "Cold Brand:", TR_BRAND_COLD, &f, DP_WP);
2309         display_flag_aux(creature_ptr, row + 13, col, "Poison Brd:", TR_BRAND_POIS, &f, DP_WP);
2310         display_flag_aux(creature_ptr, row + 14, col, "Sharpness :", TR_VORPAL, &f, DP_WP);
2311         display_flag_aux(creature_ptr, row + 15, col, "Quake     :", TR_IMPACT, &f, DP_WP);
2312         display_flag_aux(creature_ptr, row + 16, col, "Vampiric  :", TR_VAMPIRIC, &f, DP_WP);
2313         display_flag_aux(creature_ptr, row + 17, col, "Chaotic   :", TR_CHAOTIC, &f, DP_WP);
2314         display_flag_aux(creature_ptr, row + 18, col, "Force Wep.:", TR_FORCE_WEAPON, &f, DP_WP);
2315 #endif
2316
2317         /*** Set 2 ***/
2318         row = 3;
2319         col = col + 12 + 7;
2320         display_player_equippy(creature_ptr, row - 2, col + 13, 0);
2321         c_put_str(TERM_WHITE, "abcdefghijkl@", row - 1, col + 13);
2322
2323 #ifdef JP
2324         display_flag_aux(creature_ptr, row + 0, col, "テレパシー :", TR_TELEPATHY, &f, 0);
2325         display_flag_aux(creature_ptr, row + 1, col, "邪悪ESP    :", TR_ESP_EVIL, &f, 0);
2326         display_flag_aux(creature_ptr, row + 2, col, "無生物ESP  :", TR_ESP_NONLIVING, &f, 0);
2327         display_flag_aux(creature_ptr, row + 3, col, "善良ESP    :", TR_ESP_GOOD, &f, 0);
2328         display_flag_aux(creature_ptr, row + 4, col, "不死ESP    :", TR_ESP_UNDEAD, &f, 0);
2329         display_flag_aux(creature_ptr, row + 5, col, "悪魔ESP    :", TR_ESP_DEMON, &f, 0);
2330         display_flag_aux(creature_ptr, row + 6, col, "龍ESP      :", TR_ESP_DRAGON, &f, 0);
2331         display_flag_aux(creature_ptr, row + 7, col, "人間ESP    :", TR_ESP_HUMAN, &f, 0);
2332         display_flag_aux(creature_ptr, row + 8, col, "動物ESP    :", TR_ESP_ANIMAL, &f, 0);
2333         display_flag_aux(creature_ptr, row + 9, col, "オークESP  :", TR_ESP_ORC, &f, 0);
2334         display_flag_aux(creature_ptr, row + 10, col, "トロルESP  :", TR_ESP_TROLL, &f, 0);
2335         display_flag_aux(creature_ptr, row + 11, col, "巨人ESP    :", TR_ESP_GIANT, &f, 0);
2336         display_flag_aux(creature_ptr, row + 12, col, "ユニークESP:", TR_ESP_UNIQUE, &f, 0);
2337         display_flag_aux(creature_ptr, row + 13, col, "腕力維持   :", TR_SUST_STR, &f, 0);
2338         display_flag_aux(creature_ptr, row + 14, col, "知力維持   :", TR_SUST_INT, &f, 0);
2339         display_flag_aux(creature_ptr, row + 15, col, "賢さ維持   :", TR_SUST_WIS, &f, 0);
2340         display_flag_aux(creature_ptr, row + 16, col, "器用維持   :", TR_SUST_DEX, &f, 0);
2341         display_flag_aux(creature_ptr, row + 17, col, "耐久維持   :", TR_SUST_CON, &f, 0);
2342         display_flag_aux(creature_ptr, row + 18, col, "魅力維持   :", TR_SUST_CHR, &f, 0);
2343 #else
2344         display_flag_aux(creature_ptr, row + 0, col, "Telepathy  :", TR_TELEPATHY, &f, 0);
2345         display_flag_aux(creature_ptr, row + 1, col, "ESP Evil   :", TR_ESP_EVIL, &f, 0);
2346         display_flag_aux(creature_ptr, row + 2, col, "ESP Noliv. :", TR_ESP_NONLIVING, &f, 0);
2347         display_flag_aux(creature_ptr, row + 3, col, "ESP Good   :", TR_ESP_GOOD, &f, 0);
2348         display_flag_aux(creature_ptr, row + 4, col, "ESP Undead :", TR_ESP_UNDEAD, &f, 0);
2349         display_flag_aux(creature_ptr, row + 5, col, "ESP Demon  :", TR_ESP_DEMON, &f, 0);
2350         display_flag_aux(creature_ptr, row + 6, col, "ESP Dragon :", TR_ESP_DRAGON, &f, 0);
2351         display_flag_aux(creature_ptr, row + 7, col, "ESP Human  :", TR_ESP_HUMAN, &f, 0);
2352         display_flag_aux(creature_ptr, row + 8, col, "ESP Animal :", TR_ESP_ANIMAL, &f, 0);
2353         display_flag_aux(creature_ptr, row + 9, col, "ESP Orc    :", TR_ESP_ORC, &f, 0);
2354         display_flag_aux(creature_ptr, row + 10, col, "ESP Troll  :", TR_ESP_TROLL, &f, 0);
2355         display_flag_aux(creature_ptr, row + 11, col, "ESP Giant  :", TR_ESP_GIANT, &f, 0);
2356         display_flag_aux(creature_ptr, row + 12, col, "ESP Unique :", TR_ESP_UNIQUE, &f, 0);
2357         display_flag_aux(creature_ptr, row + 13, col, "Sust Str   :", TR_SUST_STR, &f, 0);
2358         display_flag_aux(creature_ptr, row + 14, col, "Sust Int   :", TR_SUST_INT, &f, 0);
2359         display_flag_aux(creature_ptr, row + 15, col, "Sust Wis   :", TR_SUST_WIS, &f, 0);
2360         display_flag_aux(creature_ptr, row + 16, col, "Sust Dex   :", TR_SUST_DEX, &f, 0);
2361         display_flag_aux(creature_ptr, row + 17, col, "Sust Con   :", TR_SUST_CON, &f, 0);
2362         display_flag_aux(creature_ptr, row + 18, col, "Sust Chr   :", TR_SUST_CHR, &f, 0);
2363 #endif
2364
2365         /*** Set 3 ***/
2366         row = 3;
2367         col = col + 12 + 17;
2368         display_player_equippy(creature_ptr, row - 2, col + 14, 0);
2369         c_put_str(TERM_WHITE, "abcdefghijkl@", row - 1, col + 14);
2370
2371 #ifdef JP
2372         display_flag_aux(creature_ptr, row + 0, col, "追加攻撃    :", TR_BLOWS, &f, 0);
2373         display_flag_aux(creature_ptr, row + 1, col, "採掘        :", TR_TUNNEL, &f, 0);
2374         display_flag_aux(creature_ptr, row + 2, col, "赤外線視力  :", TR_INFRA, &f, 0);
2375         display_flag_aux(creature_ptr, row + 3, col, "魔法道具支配:", TR_MAGIC_MASTERY, &f, 0);
2376         display_flag_aux(creature_ptr, row + 4, col, "隠密        :", TR_STEALTH, &f, 0);
2377         display_flag_aux(creature_ptr, row + 5, col, "探索        :", TR_SEARCH, &f, 0);
2378
2379         display_flag_aux(creature_ptr, row + 7, col, "乗馬        :", TR_RIDING, &f, 0);
2380         display_flag_aux(creature_ptr, row + 8, col, "投擲        :", TR_THROW, &f, 0);
2381         display_flag_aux(creature_ptr, row + 9, col, "祝福        :", TR_BLESSED, &f, 0);
2382         display_flag_aux(creature_ptr, row + 10, col, "反テレポート:", TR_NO_TELE, &f, 0);
2383         display_flag_aux(creature_ptr, row + 11, col, "反魔法      :", TR_NO_MAGIC, &f, 0);
2384         display_flag_aux(creature_ptr, row + 12, col, "消費魔力減少:", TR_DEC_MANA, &f, 0);
2385
2386         display_flag_aux(creature_ptr, row + 14, col, "経験値減少  :", TR_DRAIN_EXP, &f, 0);
2387         display_flag_aux(creature_ptr, row + 15, col, "乱テレポート:", TR_TELEPORT, &f, 0);
2388         display_flag_aux(creature_ptr, row + 16, col, "反感        :", TR_AGGRAVATE, &f, 0);
2389         display_flag_aux(creature_ptr, row + 17, col, "太古の怨念  :", TR_TY_CURSE, &f, 0);
2390 #else
2391         display_flag_aux(creature_ptr, row + 0, col, "Add Blows   :", TR_BLOWS, &f, 0);
2392         display_flag_aux(creature_ptr, row + 1, col, "Add Tunnel  :", TR_TUNNEL, &f, 0);
2393         display_flag_aux(creature_ptr, row + 2, col, "Add Infra   :", TR_INFRA, &f, 0);
2394         display_flag_aux(creature_ptr, row + 3, col, "Add Device  :", TR_MAGIC_MASTERY, &f, 0);
2395         display_flag_aux(creature_ptr, row + 4, col, "Add Stealth :", TR_STEALTH, &f, 0);
2396         display_flag_aux(creature_ptr, row + 5, col, "Add Search  :", TR_SEARCH, &f, 0);
2397
2398         display_flag_aux(creature_ptr, row + 7, col, "Riding      :", TR_RIDING, &f, 0);
2399         display_flag_aux(creature_ptr, row + 8, col, "Throw       :", TR_THROW, &f, 0);
2400         display_flag_aux(creature_ptr, row + 9, col, "Blessed     :", TR_BLESSED, &f, 0);
2401         display_flag_aux(creature_ptr, row + 10, col, "No Teleport :", TR_NO_TELE, &f, 0);
2402         display_flag_aux(creature_ptr, row + 11, col, "Anti Magic  :", TR_NO_MAGIC, &f, 0);
2403         display_flag_aux(creature_ptr, row + 12, col, "Econom. Mana:", TR_DEC_MANA, &f, 0);
2404
2405         display_flag_aux(creature_ptr, row + 14, col, "Drain Exp   :", TR_DRAIN_EXP, &f, 0);
2406         display_flag_aux(creature_ptr, row + 15, col, "Rnd.Teleport:", TR_TELEPORT, &f, 0);
2407         display_flag_aux(creature_ptr, row + 16, col, "Aggravate   :", TR_AGGRAVATE, &f, 0);
2408         display_flag_aux(creature_ptr, row + 17, col, "TY Curse    :", TR_TY_CURSE, &f, 0);
2409 #endif
2410
2411 }
2412
2413
2414 /*!
2415  * @brief プレイヤーの特性フラグ一覧表示2a /
2416  * @param creature_ptr プレーヤーへの参照ポインタ
2417  * Special display, part 2a
2418  * @return なし
2419  */
2420 static void display_player_misc_info(player_type *creature_ptr)
2421 {
2422 #ifdef JP
2423         put_str("名前  :", 1, 26);
2424         put_str("性別  :", 3, 1);
2425         put_str("種族  :", 4, 1);
2426         put_str("職業  :", 5, 1);
2427 #else
2428         put_str("Name  :", 1, 26);
2429         put_str("Sex   :", 3, 1);
2430         put_str("Race  :", 4, 1);
2431         put_str("Class :", 5, 1);
2432 #endif
2433
2434         char    buf[80];
2435         char    tmp[80];
2436         strcpy(tmp, ap_ptr->title);
2437 #ifdef JP
2438         if (ap_ptr->no == 1)
2439                 strcat(tmp, "の");
2440 #else
2441         strcat(tmp, " ");
2442 #endif
2443         strcat(tmp, creature_ptr->name);
2444
2445         c_put_str(TERM_L_BLUE, tmp, 1, 34);
2446         c_put_str(TERM_L_BLUE, sp_ptr->title, 3, 9);
2447         c_put_str(TERM_L_BLUE, (creature_ptr->mimic_form ? mimic_info[creature_ptr->mimic_form].title : rp_ptr->title), 4, 9);
2448         c_put_str(TERM_L_BLUE, cp_ptr->title, 5, 9);
2449
2450 #ifdef JP
2451         put_str("レベル:", 6, 1);
2452         put_str("HP  :", 7, 1);
2453         put_str("MP  :", 8, 1);
2454 #else
2455         put_str("Level :", 6, 1);
2456         put_str("Hits  :", 7, 1);
2457         put_str("Mana  :", 8, 1);
2458 #endif
2459
2460         (void)sprintf(buf, "%d", (int)creature_ptr->lev);
2461         c_put_str(TERM_L_BLUE, buf, 6, 9);
2462         (void)sprintf(buf, "%d/%d", (int)creature_ptr->chp, (int)creature_ptr->mhp);
2463         c_put_str(TERM_L_BLUE, buf, 7, 9);
2464         (void)sprintf(buf, "%d/%d", (int)creature_ptr->csp, (int)creature_ptr->msp);
2465         c_put_str(TERM_L_BLUE, buf, 8, 9);
2466 }
2467
2468
2469 /*!
2470  * @brief プレイヤーの特性フラグ一覧表示2b /
2471  * Special display, part 2b
2472  * @param creature_ptr プレーヤーへの参照ポインタ
2473  * @return なし
2474  * @details
2475  * <pre>
2476  * How to print out the modifications and sustains.
2477  * Positive mods with no sustain will be light green.
2478  * Positive mods with a sustain will be dark green.
2479  * Sustains (with no modification) will be a dark green 's'.
2480  * Negative mods (from a curse) will be red.
2481  * Huge mods (>9), like from MICoMorgoth, will be a '*'
2482  * No mod, no sustain, will be a slate '.'
2483  * </pre>
2484  */
2485 static void display_player_stat_info(player_type *creature_ptr)
2486 {
2487         /* Print out the labels for the columns */
2488         int stat_col = 22;
2489         int row = 3;
2490         c_put_str(TERM_WHITE, _("能力", "Stat"), row, stat_col + 1);
2491         c_put_str(TERM_BLUE, _("  基本", "  Base"), row, stat_col + 7);
2492         c_put_str(TERM_L_BLUE, _(" 種 職 性 装 ", "RacClaPerMod"), row, stat_col + 13);
2493         c_put_str(TERM_L_GREEN, _("合計", "Actual"), row, stat_col + 28);
2494         c_put_str(TERM_YELLOW, _("現在", "Current"), row, stat_col + 35);
2495
2496         /* Display the stats */
2497         char buf[80];
2498         for (int i = 0; i < A_MAX; i++)
2499         {
2500                 int r_adj;
2501                 if (creature_ptr->mimic_form) r_adj = mimic_info[creature_ptr->mimic_form].r_adj[i];
2502                 else r_adj = rp_ptr->r_adj[i];
2503
2504                 int e_adj = 0;
2505
2506                 if ((creature_ptr->stat_max[i] > 18) && (creature_ptr->stat_top[i] > 18))
2507                         e_adj = (creature_ptr->stat_top[i] - creature_ptr->stat_max[i]) / 10;
2508                 if ((creature_ptr->stat_max[i] <= 18) && (creature_ptr->stat_top[i] <= 18))
2509                         e_adj = creature_ptr->stat_top[i] - creature_ptr->stat_max[i];
2510                 if ((creature_ptr->stat_max[i] <= 18) && (creature_ptr->stat_top[i] > 18))
2511                         e_adj = (creature_ptr->stat_top[i] - 18) / 10 - creature_ptr->stat_max[i] + 18;
2512
2513                 if ((creature_ptr->stat_max[i] > 18) && (creature_ptr->stat_top[i] <= 18))
2514                         e_adj = creature_ptr->stat_top[i] - (creature_ptr->stat_max[i] - 19) / 10 - 19;
2515
2516                 if (PRACE_IS_(creature_ptr, RACE_ENT))
2517                 {
2518                         switch (i)
2519                         {
2520                         case A_STR:
2521                         case A_CON:
2522                                 if (creature_ptr->lev > 25) r_adj++;
2523                                 if (creature_ptr->lev > 40) r_adj++;
2524                                 if (creature_ptr->lev > 45) r_adj++;
2525                                 break;
2526                         case A_DEX:
2527                                 if (creature_ptr->lev > 25) r_adj--;
2528                                 if (creature_ptr->lev > 40) r_adj--;
2529                                 if (creature_ptr->lev > 45) r_adj--;
2530                                 break;
2531                         }
2532                 }
2533
2534                 e_adj -= r_adj;
2535                 e_adj -= cp_ptr->c_adj[i];
2536                 e_adj -= ap_ptr->a_adj[i];
2537
2538                 if (creature_ptr->stat_cur[i] < creature_ptr->stat_max[i])
2539                         c_put_str(TERM_WHITE, stat_names_reduced[i], row + i + 1, stat_col + 1);
2540                 else
2541                         c_put_str(TERM_WHITE, stat_names[i], row + i + 1, stat_col + 1);
2542
2543                 /* Internal "natural" max value.  Maxes at 18/100 */
2544                 /* This is useful to see if you are maxed out */
2545                 cnv_stat(creature_ptr->stat_max[i], buf);
2546                 if (creature_ptr->stat_max[i] == creature_ptr->stat_max_max[i])
2547                 {
2548                         c_put_str(TERM_WHITE, "!", row + i + 1, _(stat_col + 6, stat_col + 4));
2549                 }
2550
2551                 c_put_str(TERM_BLUE, buf, row + i + 1, stat_col + 13 - strlen(buf));
2552
2553                 /* Race, class, and equipment modifiers */
2554                 (void)sprintf(buf, "%3d", r_adj);
2555                 c_put_str(TERM_L_BLUE, buf, row + i + 1, stat_col + 13);
2556                 (void)sprintf(buf, "%3d", (int)cp_ptr->c_adj[i]);
2557                 c_put_str(TERM_L_BLUE, buf, row + i + 1, stat_col + 16);
2558                 (void)sprintf(buf, "%3d", (int)ap_ptr->a_adj[i]);
2559                 c_put_str(TERM_L_BLUE, buf, row + i + 1, stat_col + 19);
2560                 (void)sprintf(buf, "%3d", (int)e_adj);
2561                 c_put_str(TERM_L_BLUE, buf, row + i + 1, stat_col + 22);
2562
2563                 /* Actual maximal modified value */
2564                 cnv_stat(creature_ptr->stat_top[i], buf);
2565                 c_put_str(TERM_L_GREEN, buf, row + i + 1, stat_col + 26);
2566
2567                 /* Only display stat_use if not maximal */
2568                 if (creature_ptr->stat_use[i] < creature_ptr->stat_top[i])
2569                 {
2570                         cnv_stat(creature_ptr->stat_use[i], buf);
2571                         c_put_str(TERM_YELLOW, buf, row + i + 1, stat_col + 33);
2572                 }
2573         }
2574
2575         int col = stat_col + 41;
2576         c_put_str(TERM_WHITE, "abcdefghijkl@", row, col);
2577         c_put_str(TERM_L_GREEN, _("能力修正", "Modification"), row - 1, col);
2578
2579         BIT_FLAGS flgs[TR_FLAG_SIZE];
2580         for (int i = INVEN_RARM; i < INVEN_TOTAL; i++)
2581         {
2582                 object_type *o_ptr;
2583                 o_ptr = &creature_ptr->inventory_list[i];
2584                 object_flags_known(o_ptr, flgs);
2585
2586                 /* Initialize color based of sign of pval. */
2587                 for (int stat = 0; stat < A_MAX; stat++)
2588                 {
2589                         byte a = TERM_SLATE;
2590                         char c = '.';
2591
2592                         /* Boost */
2593                         if (have_flag(flgs, stat))
2594                         {
2595                                 /* Default */
2596                                 c = '*';
2597
2598                                 /* Good */
2599                                 if (o_ptr->pval > 0)
2600                                 {
2601                                         /* Good */
2602                                         a = TERM_L_GREEN;
2603
2604                                         /* Label boost */
2605                                         if (o_ptr->pval < 10) c = '0' + o_ptr->pval;
2606                                 }
2607
2608                                 if (have_flag(flgs, stat + TR_SUST_STR))
2609                                 {
2610                                         /* Dark green for sustained stats */
2611                                         a = TERM_GREEN;
2612                                 }
2613
2614                                 /* Bad */
2615                                 if (o_ptr->pval < 0)
2616                                 {
2617                                         /* Bad */
2618                                         a = TERM_RED;
2619
2620                                         /* Label boost */
2621                                         if (o_ptr->pval > -10) c = '0' - o_ptr->pval;
2622                                 }
2623                         }
2624
2625                         /* Sustain */
2626                         else if (have_flag(flgs, stat + TR_SUST_STR))
2627                         {
2628                                 /* Dark green "s" */
2629                                 a = TERM_GREEN;
2630                                 c = 's';
2631                         }
2632
2633                         Term_putch(col, row + stat + 1, a, c);
2634                 }
2635
2636                 col++;
2637         }
2638
2639         player_flags(creature_ptr, flgs);
2640
2641         for (int stat = 0; stat < A_MAX; stat++)
2642         {
2643                 byte a = TERM_SLATE;
2644                 char c = '.';
2645
2646                 if (creature_ptr->muta3 || creature_ptr->tsuyoshi)
2647                 {
2648                         int dummy = 0;
2649
2650                         if (stat == A_STR)
2651                         {
2652                                 if (creature_ptr->muta3 & MUT3_HYPER_STR) dummy += 4;
2653                                 if (creature_ptr->muta3 & MUT3_PUNY) dummy -= 4;
2654                                 if (creature_ptr->tsuyoshi) dummy += 4;
2655                         }
2656                         else if (stat == A_WIS || stat == A_INT)
2657                         {
2658                                 if (creature_ptr->muta3 & MUT3_HYPER_INT) dummy += 4;
2659                                 if (creature_ptr->muta3 & MUT3_MORONIC) dummy -= 4;
2660                         }
2661                         else if (stat == A_DEX)
2662                         {
2663                                 if (creature_ptr->muta3 & MUT3_IRON_SKIN) dummy -= 1;
2664                                 if (creature_ptr->muta3 & MUT3_LIMBER) dummy += 3;
2665                                 if (creature_ptr->muta3 & MUT3_ARTHRITIS) dummy -= 3;
2666                         }
2667                         else if (stat == A_CON)
2668                         {
2669                                 if (creature_ptr->muta3 & MUT3_RESILIENT) dummy += 4;
2670                                 if (creature_ptr->muta3 & MUT3_XTRA_FAT) dummy += 2;
2671                                 if (creature_ptr->muta3 & MUT3_ALBINO) dummy -= 4;
2672                                 if (creature_ptr->muta3 & MUT3_FLESH_ROT) dummy -= 2;
2673                                 if (creature_ptr->tsuyoshi) dummy += 4;
2674                         }
2675                         else if (stat == A_CHR)
2676                         {
2677                                 if (creature_ptr->muta3 & MUT3_SILLY_VOI) dummy -= 4;
2678                                 if (creature_ptr->muta3 & MUT3_BLANK_FAC) dummy -= 1;
2679                                 if (creature_ptr->muta3 & MUT3_FLESH_ROT) dummy -= 1;
2680                                 if (creature_ptr->muta3 & MUT3_SCALES) dummy -= 1;
2681                                 if (creature_ptr->muta3 & MUT3_WART_SKIN) dummy -= 2;
2682                                 if (creature_ptr->muta3 & MUT3_ILL_NORM) dummy = 0;
2683                         }
2684
2685                         /* Boost */
2686                         if (dummy)
2687                         {
2688                                 c = '*';
2689
2690                                 /* Good */
2691                                 if (dummy > 0)
2692                                 {
2693                                         /* Good */
2694                                         a = TERM_L_GREEN;
2695
2696                                         /* Label boost */
2697                                         if (dummy < 10) c = '0' + dummy;
2698                                 }
2699
2700                                 /* Bad */
2701                                 if (dummy < 0)
2702                                 {
2703                                         /* Bad */
2704                                         a = TERM_RED;
2705
2706                                         /* Label boost */
2707                                         if (dummy > -10) c = '0' - dummy;
2708                                 }
2709                         }
2710                 }
2711
2712                 if (have_flag(flgs, stat + TR_SUST_STR))
2713                 {
2714                         /* Dark green "s" */
2715                         a = TERM_GREEN;
2716                         c = 's';
2717                 }
2718
2719                 Term_putch(col, row + stat + 1, a, c);
2720         }
2721 }
2722
2723
2724 /*!
2725  * @brief プレイヤーのステータス表示メイン処理
2726  * Display the character on the screen (various modes)
2727  * @param creature_ptr プレーヤーへの参照ポインタ
2728  * @param mode 表示モードID
2729  * @return なし
2730  * @details
2731  * <pre>
2732  * The top one and bottom two lines are left blank.
2733  * Mode 0 = standard display with skills
2734  * Mode 1 = standard display with history
2735  * Mode 2 = summary of various things
2736  * Mode 3 = summary of various things (part 2)
2737  * Mode 4 = mutations
2738  * </pre>
2739  */
2740 void display_player(player_type *creature_ptr, int mode)
2741 {
2742         if ((creature_ptr->muta1 || creature_ptr->muta2 || creature_ptr->muta3) && display_mutations)
2743                 mode = (mode % 5);
2744         else
2745                 mode = (mode % 4);
2746
2747         clear_from(0);
2748
2749         if (mode == 2)
2750         {
2751                 display_player_misc_info(creature_ptr);
2752                 display_player_stat_info(creature_ptr);
2753                 display_player_flag_info(creature_ptr);
2754                 return;
2755         }
2756
2757         if (mode == 3)
2758         {
2759                 display_player_other_flag_info(creature_ptr);
2760                 return;
2761         }
2762
2763         if (mode == 4)
2764         {
2765                 do_cmd_knowledge_mutations(creature_ptr);
2766                 return;
2767         }
2768
2769         char tmp[64];
2770         if ((mode != 0) && (mode != 1)) return;
2771
2772         /* Name, Sex, Race, Class */
2773 #ifdef JP
2774         sprintf(tmp, "%s%s%s", ap_ptr->title, ap_ptr->no == 1 ? "の" : "", creature_ptr->name);
2775 #else
2776         sprintf(tmp, "%s %s", ap_ptr->title, creature_ptr->name);
2777 #endif
2778
2779         display_player_one_line(ENTRY_NAME, tmp, TERM_L_BLUE);
2780         display_player_one_line(ENTRY_SEX, sp_ptr->title, TERM_L_BLUE);
2781         display_player_one_line(ENTRY_RACE, (creature_ptr->mimic_form ? mimic_info[creature_ptr->mimic_form].title : rp_ptr->title), TERM_L_BLUE);
2782         display_player_one_line(ENTRY_CLASS, cp_ptr->title, TERM_L_BLUE);
2783
2784         if (creature_ptr->realm1)
2785         {
2786                 if (creature_ptr->realm2)
2787                         sprintf(tmp, "%s, %s", realm_names[creature_ptr->realm1], realm_names[creature_ptr->realm2]);
2788                 else
2789                         strcpy(tmp, realm_names[creature_ptr->realm1]);
2790                 display_player_one_line(ENTRY_REALM, tmp, TERM_L_BLUE);
2791         }
2792
2793         if ((creature_ptr->pclass == CLASS_CHAOS_WARRIOR) || (creature_ptr->muta2 & MUT2_CHAOS_GIFT))
2794                 display_player_one_line(ENTRY_PATRON, chaos_patrons[creature_ptr->chaos_patron], TERM_L_BLUE);
2795
2796         /* Age, Height, Weight, Social */
2797         /* 身長はセンチメートルに、体重はキログラムに変更してあります */
2798 #ifdef JP
2799         display_player_one_line(ENTRY_AGE, format("%d才", (int)creature_ptr->age), TERM_L_BLUE);
2800         display_player_one_line(ENTRY_HEIGHT, format("%dcm", (int)((creature_ptr->ht * 254) / 100)), TERM_L_BLUE);
2801         display_player_one_line(ENTRY_WEIGHT, format("%dkg", (int)((creature_ptr->wt * 4536) / 10000)), TERM_L_BLUE);
2802         display_player_one_line(ENTRY_SOCIAL, format("%d  ", (int)creature_ptr->sc), TERM_L_BLUE);
2803 #else
2804         display_player_one_line(ENTRY_AGE, format("%d", (int)creature_ptr->age), TERM_L_BLUE);
2805         display_player_one_line(ENTRY_HEIGHT, format("%d", (int)creature_ptr->ht), TERM_L_BLUE);
2806         display_player_one_line(ENTRY_WEIGHT, format("%d", (int)creature_ptr->wt), TERM_L_BLUE);
2807         display_player_one_line(ENTRY_SOCIAL, format("%d", (int)creature_ptr->sc), TERM_L_BLUE);
2808 #endif
2809         display_player_one_line(ENTRY_ALIGN, format("%s", your_alignment(creature_ptr)), TERM_L_BLUE);
2810
2811         char buf[80];
2812         for (int i = 0; i < A_MAX; i++)
2813         {
2814                 /* Special treatment of "injured" stats */
2815                 if (creature_ptr->stat_cur[i] < creature_ptr->stat_max[i])
2816                 {
2817                         int value;
2818
2819                         /* Use lowercase stat name */
2820                         put_str(stat_names_reduced[i], 3 + i, 53);
2821
2822                         /* Get the current stat */
2823                         value = creature_ptr->stat_use[i];
2824
2825                         /* Obtain the current stat (modified) */
2826                         cnv_stat(value, buf);
2827
2828                         /* Display the current stat (modified) */
2829                         c_put_str(TERM_YELLOW, buf, 3 + i, 60);
2830
2831                         /* Acquire the max stat */
2832                         value = creature_ptr->stat_top[i];
2833
2834                         /* Obtain the maximum stat (modified) */
2835                         cnv_stat(value, buf);
2836
2837                         /* Display the maximum stat (modified) */
2838                         c_put_str(TERM_L_GREEN, buf, 3 + i, 67);
2839                 }
2840
2841                 /* Normal treatment of "normal" stats */
2842                 else
2843                 {
2844                         /* Assume uppercase stat name */
2845                         put_str(stat_names[i], 3 + i, 53);
2846
2847                         /* Obtain the current stat (modified) */
2848                         cnv_stat(creature_ptr->stat_use[i], buf);
2849
2850                         /* Display the current stat (modified) */
2851                         c_put_str(TERM_L_GREEN, buf, 3 + i, 60);
2852                 }
2853
2854                 if (creature_ptr->stat_max[i] == creature_ptr->stat_max_max[i])
2855                 {
2856                         c_put_str(TERM_WHITE, "!", 3 + i, _(58, 58 - 2));
2857                 }
2858         }
2859
2860         /* Display "history" info */
2861         floor_type *floor_ptr = creature_ptr->current_floor_ptr;
2862         if (mode == 0)
2863         {
2864                 display_player_middle(creature_ptr);
2865                 display_player_various(creature_ptr);
2866                 return;
2867         }
2868
2869         char statmsg[1000];
2870         put_str(_("(キャラクターの生い立ち)", "(Character Background)"), 11, 25);
2871
2872         for (int i = 0; i < 4; i++)
2873         {
2874                 put_str(creature_ptr->history[i], i + 12, 10);
2875         }
2876
2877         *statmsg = '\0';
2878
2879         if (creature_ptr->is_dead)
2880         {
2881                 if (current_world_ptr->total_winner)
2882                 {
2883 #ifdef JP
2884                         sprintf(statmsg, "…あなたは勝利の後%sした。", streq(creature_ptr->died_from, "Seppuku") ? "切腹" : "引退");
2885 #else
2886                         sprintf(statmsg, "...You %s after winning.", streq(creature_ptr->died_from, "Seppuku") ? "committed seppuku" : "retired from the adventure");
2887 #endif
2888                 }
2889                 else if (!floor_ptr->dun_level)
2890                 {
2891 #ifdef JP
2892                         sprintf(statmsg, "…あなたは%sで%sに殺された。", map_name(creature_ptr), creature_ptr->died_from);
2893 #else
2894                         sprintf(statmsg, "...You were killed by %s in %s.", creature_ptr->died_from, map_name(creature_ptr));
2895 #endif
2896                 }
2897                 else if (floor_ptr->inside_quest && is_fixed_quest_idx(floor_ptr->inside_quest))
2898                 {
2899                         /* Get the quest text */
2900                         /* Bewere that INIT_ASSIGN resets the cur_num. */
2901                         init_flags = INIT_NAME_ONLY;
2902
2903                         process_dungeon_file(creature_ptr, "q_info.txt", 0, 0, 0, 0);
2904
2905 #ifdef JP
2906                         sprintf(statmsg, "…あなたは、クエスト「%s」で%sに殺された。", quest[floor_ptr->inside_quest].name, creature_ptr->died_from);
2907 #else
2908                         sprintf(statmsg, "...You were killed by %s in the quest '%s'.", creature_ptr->died_from, quest[floor_ptr->inside_quest].name);
2909 #endif
2910                 }
2911                 else
2912                 {
2913 #ifdef JP
2914                         sprintf(statmsg, "…あなたは、%sの%d階で%sに殺された。", map_name(creature_ptr), (int)floor_ptr->dun_level, creature_ptr->died_from);
2915 #else
2916                         sprintf(statmsg, "...You were killed by %s on level %d of %s.", creature_ptr->died_from, floor_ptr->dun_level, map_name(creature_ptr));
2917 #endif
2918                 }
2919         }
2920         else if (current_world_ptr->character_dungeon)
2921         {
2922                 if (!floor_ptr->dun_level)
2923                 {
2924                         sprintf(statmsg, _("…あなたは現在、 %s にいる。", "...Now, you are in %s."), map_name(creature_ptr));
2925                 }
2926                 else if (floor_ptr->inside_quest && is_fixed_quest_idx(floor_ptr->inside_quest))
2927                 {
2928                         /* Clear the text */
2929                         /* Must be done before doing INIT_SHOW_TEXT */
2930                         for (int i = 0; i < 10; i++)
2931                         {
2932                                 quest_text[i][0] = '\0';
2933                         }
2934
2935                         quest_text_line = 0;
2936
2937                         /* Get the quest text */
2938                         init_flags = INIT_NAME_ONLY;
2939                         process_dungeon_file(creature_ptr, "q_info.txt", 0, 0, 0, 0);
2940                         sprintf(statmsg, _("…あなたは現在、 クエスト「%s」を遂行中だ。", "...Now, you are in the quest '%s'."), quest[floor_ptr->inside_quest].name);
2941                 }
2942                 else
2943                 {
2944 #ifdef JP
2945                         sprintf(statmsg, "…あなたは現在、 %s の %d 階で探索している。", map_name(creature_ptr), (int)floor_ptr->dun_level);
2946 #else
2947                         sprintf(statmsg, "...Now, you are exploring level %d of %s.", floor_ptr->dun_level, map_name(creature_ptr));
2948 #endif
2949                 }
2950         }
2951
2952         if (!*statmsg) return;
2953
2954         char temp[64 * 2];
2955         roff_to_buf(statmsg, 60, temp, sizeof(temp));
2956         char  *t;
2957         t = temp;
2958         for (int i = 0; i < 2; i++)
2959         {
2960                 if (t[0] == 0) return;
2961
2962                 put_str(t, i + 5 + 12, 10);
2963                 t += strlen(t) + 1;
2964         }
2965 }
2966
2967
2968 /*!
2969  * @brief プレイヤーのステータス表示をファイルにダンプする
2970  * @param creature_ptr プレーヤーへの参照ポインタ
2971  * @param fff ファイルポインタ
2972  * @return なし
2973  */
2974 static void dump_aux_display_player(player_type *creature_ptr, FILE *fff)
2975 {
2976         TERM_COLOR a;
2977         char c;
2978         char buf[1024];
2979         display_player(creature_ptr, 0);
2980
2981         for (TERM_LEN y = 1; y < 22; y++)
2982         {
2983                 TERM_LEN x;
2984                 for (x = 0; x < 79; x++)
2985                 {
2986                         (void)(Term_what(x, y, &a, &c));
2987                         buf[x] = c;
2988                 }
2989
2990                 buf[x] = '\0';
2991                 while ((x > 0) && (buf[x - 1] == ' '))
2992                         buf[--x] = '\0';
2993
2994                 fprintf(fff, _("%s\n", "%s\n"), buf);
2995         }
2996
2997         display_player(creature_ptr, 1);
2998         for (TERM_LEN y = 10; y < 19; y++)
2999         {
3000                 TERM_LEN x;
3001                 for (x = 0; x < 79; x++)
3002                 {
3003                         (void)(Term_what(x, y, &a, &c));
3004                         buf[x] = c;
3005                 }
3006
3007                 buf[x] = '\0';
3008                 while ((x > 0) && (buf[x - 1] == ' '))
3009                         buf[--x] = '\0';
3010
3011                 fprintf(fff, "%s\n", buf);
3012         }
3013
3014         fprintf(fff, "\n");
3015         display_player(creature_ptr, 2);
3016         for (TERM_LEN y = 2; y < 22; y++)
3017         {
3018                 TERM_LEN x;
3019                 for (x = 0; x < 79; x++)
3020                 {
3021                         (void)(Term_what(x, y, &a, &c));
3022                         if (a < 128)
3023                                 buf[x] = c;
3024                         else
3025                                 buf[x] = ' ';
3026                 }
3027
3028                 buf[x] = '\0';
3029                 while ((x > 0) && (buf[x - 1] == ' '))
3030                         buf[--x] = '\0';
3031
3032                 fprintf(fff, "%s\n", buf);
3033         }
3034
3035         fprintf(fff, "\n");
3036         display_player(creature_ptr, 3);
3037         for (TERM_LEN y = 1; y < 22; y++)
3038         {
3039                 TERM_LEN x;
3040                 for (x = 0; x < 79; x++)
3041                 {
3042                         (void)(Term_what(x, y, &a, &c));
3043                         if (a < 128)
3044                                 buf[x] = c;
3045                         else
3046                                 buf[x] = ' ';
3047                 }
3048
3049                 buf[x] = '\0';
3050                 while ((x > 0) && (buf[x - 1] == ' '))
3051                         buf[--x] = '\0';
3052
3053                 fprintf(fff, "%s\n", buf);
3054         }
3055
3056         fprintf(fff, "\n");
3057 }
3058
3059
3060 /*!
3061  * @brief プレイヤーのペット情報をファイルにダンプする
3062  * @param creature_ptr プレーヤーへの参照ポインタ
3063  * @param fff ファイルポインタ
3064  * @return なし
3065  */
3066 static void dump_aux_pet(player_type *master_ptr, FILE *fff)
3067 {
3068         bool pet = FALSE;
3069         bool pet_settings = FALSE;
3070         for (int i = master_ptr->current_floor_ptr->m_max - 1; i >= 1; i--)
3071         {
3072                 monster_type *m_ptr = &master_ptr->current_floor_ptr->m_list[i];
3073
3074                 if (!monster_is_valid(m_ptr)) continue;
3075                 if (!is_pet(m_ptr)) continue;
3076                 pet_settings = TRUE;
3077                 if (!m_ptr->nickname && (master_ptr->riding != i)) continue;
3078                 if (!pet)
3079                 {
3080                         fprintf(fff, _("\n\n  [主なペット]\n\n", "\n\n  [Leading Pets]\n\n"));
3081                         pet = TRUE;
3082                 }
3083
3084                 GAME_TEXT pet_name[MAX_NLEN];
3085                 monster_desc(master_ptr, pet_name, m_ptr, MD_ASSUME_VISIBLE | MD_INDEF_VISIBLE);
3086                 fprintf(fff, "%s\n", pet_name);
3087         }
3088
3089         if (!pet_settings) return;
3090
3091         fprintf(fff, _("\n\n  [ペットへの命令]\n", "\n\n  [Command for Pets]\n"));
3092
3093         fprintf(fff, _("\n ドアを開ける:                       %s", "\n Pets open doors:                    %s"),
3094                 (master_ptr->pet_extra_flags & PF_OPEN_DOORS) ? "ON" : "OFF");
3095
3096         fprintf(fff, _("\n アイテムを拾う:                     %s", "\n Pets pick up items:                 %s"),
3097                 (master_ptr->pet_extra_flags & PF_PICKUP_ITEMS) ? "ON" : "OFF");
3098
3099         fprintf(fff, _("\n テレポート系魔法を使う:             %s", "\n Allow teleport:                     %s"),
3100                 (master_ptr->pet_extra_flags & PF_TELEPORT) ? "ON" : "OFF");
3101
3102         fprintf(fff, _("\n 攻撃魔法を使う:                     %s", "\n Allow cast attack spell:            %s"),
3103                 (master_ptr->pet_extra_flags & PF_ATTACK_SPELL) ? "ON" : "OFF");
3104
3105         fprintf(fff, _("\n 召喚魔法を使う:                     %s", "\n Allow cast summon spell:            %s"),
3106                 (master_ptr->pet_extra_flags & PF_SUMMON_SPELL) ? "ON" : "OFF");
3107
3108         fprintf(fff, _("\n プレイヤーを巻き込む範囲魔法を使う: %s", "\n Allow involve player in area spell: %s"),
3109                 (master_ptr->pet_extra_flags & PF_BALL_SPELL) ? "ON" : "OFF");
3110
3111         fputc('\n', fff);
3112 }
3113
3114
3115 /*!
3116  * todo ここはenum/switchで扱いたい
3117  * @brief プレイヤーの職業能力情報をファイルにダンプする
3118  * @param creature_ptr プレーヤーへの参照ポインタ
3119  * @param fff ファイルポインタ
3120  * @return なし
3121  */
3122 static void dump_aux_class_special(player_type *creature_ptr, FILE *fff)
3123 {
3124         bool is_special_class = creature_ptr->pclass == CLASS_MAGIC_EATER;
3125         is_special_class |= creature_ptr->pclass == CLASS_SMITH;
3126         is_special_class |= creature_ptr->pclass != CLASS_BLUE_MAGE;
3127         if (!is_special_class) return;
3128
3129         if (creature_ptr->pclass == CLASS_MAGIC_EATER)
3130         {
3131                 char s[EATER_EXT][MAX_NLEN];
3132                 OBJECT_TYPE_VALUE tval = 0;
3133                 fprintf(fff, _("\n\n  [取り込んだ魔法道具]\n", "\n\n  [Magic devices eaten]\n"));
3134
3135                 for (int ext = 0; ext < 3; ext++)
3136                 {
3137                         int eat_num = 0;
3138
3139                         /* Dump an extent name */
3140                         switch (ext)
3141                         {
3142                         case 0:
3143                                 tval = TV_STAFF;
3144                                 fprintf(fff, _("\n[杖]\n", "\n[Staffs]\n"));
3145                                 break;
3146                         case 1:
3147                                 tval = TV_WAND;
3148                                 fprintf(fff, _("\n[魔法棒]\n", "\n[Wands]\n"));
3149                                 break;
3150                         case 2:
3151                                 tval = TV_ROD;
3152                                 fprintf(fff, _("\n[ロッド]\n", "\n[Rods]\n"));
3153                                 break;
3154                         }
3155
3156                         /* Get magic device names that were eaten */
3157                         for (OBJECT_SUBTYPE_VALUE i = 0; i < EATER_EXT; i++)
3158                         {
3159                                 int idx = EATER_EXT * ext + i;
3160                                 int magic_num = creature_ptr->magic_num2[idx];
3161                                 if (!magic_num) continue;
3162
3163                                 KIND_OBJECT_IDX k_idx = lookup_kind(tval, i);
3164                                 if (!k_idx) continue;
3165                                 sprintf(s[eat_num], "%23s (%2d)", (k_name + k_info[k_idx].name), magic_num);
3166                                 eat_num++;
3167                         }
3168
3169                         /* Dump magic devices in this extent */
3170                         if (eat_num <= 0)
3171                         {
3172                                 fputs(_("  (なし)\n", "  (none)\n"), fff);
3173                                 continue;
3174                         }
3175
3176                         OBJECT_SUBTYPE_VALUE i;
3177                         for (i = 0; i < eat_num; i++)
3178                         {
3179                                 fputs(s[i], fff);
3180                                 if (i % 3 < 2) fputs("    ", fff);
3181                                 else fputs("\n", fff);
3182                         }
3183
3184                         if (i % 3 > 0) fputs("\n", fff);
3185                 }
3186
3187                 return;
3188         }
3189
3190         if (creature_ptr->pclass == CLASS_SMITH)
3191         {
3192                 int i, id[250], n = 0, row;
3193
3194                 fprintf(fff, _("\n\n  [手に入れたエッセンス]\n\n", "\n\n  [Get Essence]\n\n"));
3195                 fprintf(fff, _("エッセンス   個数     エッセンス   個数     エッセンス   個数",
3196                         "Essence      Num      Essence      Num      Essence      Num "));
3197                 for (i = 0; essence_name[i]; i++)
3198                 {
3199                         if (!essence_name[i][0]) continue;
3200                         id[n] = i;
3201                         n++;
3202                 }
3203
3204                 row = n / 3 + 1;
3205
3206                 for (i = 0; i < row; i++)
3207                 {
3208                         fprintf(fff, "\n");
3209                         fprintf(fff, "%-11s %5d     ", essence_name[id[i]], (int)creature_ptr->magic_num1[id[i]]);
3210                         if (i + row < n) fprintf(fff, "%-11s %5d     ", essence_name[id[i + row]], (int)creature_ptr->magic_num1[id[i + row]]);
3211                         if (i + row * 2 < n) fprintf(fff, "%-11s %5d", essence_name[id[i + row * 2]], (int)creature_ptr->magic_num1[id[i + row * 2]]);
3212                 }
3213
3214                 fputs("\n", fff);
3215                 return;
3216         }
3217
3218         // Blue mage
3219         int l1 = 0;
3220         int l2 = 0;
3221         int spellnum[MAX_MONSPELLS];
3222         BIT_FLAGS f4 = 0, f5 = 0, f6 = 0;
3223         char p[60][80];
3224         int col = 0;
3225         bool pcol = FALSE;
3226
3227         for (int i = 0; i < 60; i++)
3228         {
3229                 p[i][0] = '\0';
3230         }
3231
3232         strcat(p[col], _("\n\n  [学習済みの青魔法]\n", "\n\n  [Learned Blue Magic]\n"));
3233
3234         for (int j = 1; j < 6; j++)
3235         {
3236                 col++;
3237                 set_rf_masks(&f4, &f5, &f6, j);
3238                 switch (j)
3239                 {
3240                 case MONSPELL_TYPE_BOLT:
3241                         strcat(p[col], _("\n     [ボルト型]\n", "\n     [Bolt  Type]\n"));
3242                         break;
3243
3244                 case MONSPELL_TYPE_BALL:
3245                         strcat(p[col], _("\n     [ボール型]\n", "\n     [Ball  Type]\n"));
3246                         break;
3247
3248                 case MONSPELL_TYPE_BREATH:
3249                         strcat(p[col], _("\n     [ブレス型]\n", "\n     [  Breath  ]\n"));
3250                         break;
3251
3252                 case MONSPELL_TYPE_SUMMON:
3253                         strcat(p[col], _("\n     [召喚魔法]\n", "\n     [Summonning]\n"));
3254                         break;
3255
3256                 case MONSPELL_TYPE_OTHER:
3257                         strcat(p[col], _("\n     [ その他 ]\n", "\n     [Other Type]\n"));
3258                         break;
3259                 }
3260
3261                 int num = 0;
3262                 for (int i = 0; i < 32; i++)
3263                 {
3264                         if ((0x00000001 << i) & f4) spellnum[num++] = i;
3265                 }
3266
3267                 for (int i = 32; i < 64; i++)
3268                 {
3269                         if ((0x00000001 << (i - 32)) & f5) spellnum[num++] = i;
3270                 }
3271
3272                 for (int i = 64; i < 96; i++)
3273                 {
3274                         if ((0x00000001 << (i - 64)) & f6) spellnum[num++] = i;
3275                 }
3276
3277                 col++;
3278                 pcol = FALSE;
3279                 strcat(p[col], "       ");
3280
3281                 for (int i = 0; i < num; i++)
3282                 {
3283                         if (creature_ptr->magic_num2[spellnum[i]] == 0) continue;
3284
3285                         pcol = TRUE;
3286                         /* Dump blue magic */
3287                         l1 = strlen(p[col]);
3288                         l2 = strlen(monster_powers_short[spellnum[i]]);
3289                         if ((l1 + l2) >= 75)
3290                         {
3291                                 strcat(p[col], "\n");
3292                                 col++;
3293                                 strcat(p[col], "       ");
3294                         }
3295
3296                         strcat(p[col], monster_powers_short[spellnum[i]]);
3297                         strcat(p[col], ", ");
3298                 }
3299
3300                 if (!pcol)
3301                 {
3302                         strcat(p[col], _("なし", "None"));
3303                         strcat(p[col], "\n");
3304                         continue;
3305                 }
3306
3307                 if (p[col][strlen(p[col]) - 2] == ',')
3308                 {
3309                         p[col][strlen(p[col]) - 2] = '\0';
3310                 }
3311                 else
3312                 {
3313                         p[col][strlen(p[col]) - 10] = '\0';
3314                 }
3315
3316                 strcat(p[col], "\n");
3317         }
3318
3319         for (int i = 0; i <= col; i++)
3320         {
3321                 fputs(p[i], fff);
3322         }
3323 }
3324
3325
3326 /*!
3327  * @brief クエスト情報をファイルにダンプする
3328  * @param creature_ptr プレーヤーへの参照ポインタ
3329  * @param fff ファイルポインタ
3330  * @return なし
3331  */
3332 static void dump_aux_quest(player_type *creature_ptr, FILE *fff)
3333 {
3334         fprintf(fff, _("\n\n  [クエスト情報]\n", "\n\n  [Quest Information]\n"));
3335         QUEST_IDX *quest_num;
3336         C_MAKE(quest_num, max_q_idx, QUEST_IDX);
3337
3338         for (QUEST_IDX i = 1; i < max_q_idx; i++)
3339                 quest_num[i] = i;
3340         int dummy;
3341         ang_sort(quest_num, &dummy, max_q_idx, ang_sort_comp_quest_num, ang_sort_swap_quest_num);
3342
3343         fputc('\n', fff);
3344         do_cmd_knowledge_quests_completed(creature_ptr, fff, quest_num);
3345         fputc('\n', fff);
3346         do_cmd_knowledge_quests_failed(creature_ptr, fff, quest_num);
3347         fputc('\n', fff);
3348
3349         C_KILL(quest_num, max_q_idx, QUEST_IDX);
3350 }
3351
3352
3353 /*!
3354  * @brief 死の直前メッセージ並びに遺言をファイルにダンプする
3355  * @param creature_ptr プレーヤーへの参照ポインタ
3356  * @param fff ファイルポインタ
3357  * @return なし
3358  */
3359 static void dump_aux_last_message(player_type *creature_ptr, FILE *fff)
3360 {
3361         if (!creature_ptr->is_dead) return;
3362
3363         if (!current_world_ptr->total_winner)
3364         {
3365                 fprintf(fff, _("\n  [死ぬ直前のメッセージ]\n\n", "\n  [Last Messages]\n\n"));
3366                 for (int i = MIN(message_num(), 30); i >= 0; i--)
3367                 {
3368                         fprintf(fff, "> %s\n", message_str((s16b)i));
3369                 }
3370
3371                 fputc('\n', fff);
3372                 return;
3373         }
3374
3375         if (creature_ptr->last_message)
3376         {
3377                 fprintf(fff, _("\n  [*勝利*メッセージ]\n\n", "\n  [*Winning* Message]\n\n"));
3378                 fprintf(fff, "  %s\n", creature_ptr->last_message);
3379                 fputc('\n', fff);
3380         }
3381 }
3382
3383
3384 /*!
3385  * @brief 帰還場所情報をファイルにダンプする
3386  * @param fff ファイルポインタ
3387  * @return なし
3388  */
3389 static void dump_aux_recall(FILE *fff)
3390 {
3391         fprintf(fff, _("\n  [帰還場所]\n\n", "\n  [Recall Depth]\n\n"));
3392         for (int y = 1; y < current_world_ptr->max_d_idx; y++)
3393         {
3394                 bool seiha = FALSE;
3395
3396                 if (!d_info[y].maxdepth) continue;
3397                 if (!max_dlv[y]) continue;
3398                 if (d_info[y].final_guardian)
3399                 {
3400                         if (!r_info[d_info[y].final_guardian].max_num) seiha = TRUE;
3401                 }
3402                 else if (max_dlv[y] == d_info[y].maxdepth) seiha = TRUE;
3403
3404                 fprintf(fff, _("   %c%-12s: %3d 階\n", "   %c%-16s: level %3d\n"),
3405                         seiha ? '!' : ' ', d_name + d_info[y].name, (int)max_dlv[y]);
3406         }
3407 }
3408
3409
3410 /*!
3411  * @brief オプション情報をファイルにダンプする
3412  * @param fff ファイルポインタ
3413  * @return なし
3414  */
3415 static void dump_aux_options(FILE *fff)
3416 {
3417         fprintf(fff, _("\n  [オプション設定]\n", "\n  [Option Settings]\n"));
3418         if (preserve_mode)
3419                 fprintf(fff, _("\n 保存モード:         ON", "\n Preserve Mode:      ON"));
3420
3421         else
3422                 fprintf(fff, _("\n 保存モード:         OFF", "\n Preserve Mode:      OFF"));
3423
3424         if (ironman_small_levels)
3425                 fprintf(fff, _("\n 小さいダンジョン:   ALWAYS", "\n Small Levels:       ALWAYS"));
3426         else if (always_small_levels)
3427                 fprintf(fff, _("\n 小さいダンジョン:   ON", "\n Small Levels:       ON"));
3428         else if (small_levels)
3429                 fprintf(fff, _("\n 小さいダンジョン:   ENABLED", "\n Small Levels:       ENABLED"));
3430         else
3431                 fprintf(fff, _("\n 小さいダンジョン:   OFF", "\n Small Levels:       OFF"));
3432
3433         if (vanilla_town)
3434                 fprintf(fff, _("\n 元祖の町のみ:       ON", "\n Vanilla Town:       ON"));
3435         else if (lite_town)
3436                 fprintf(fff, _("\n 小規模な町:         ON", "\n Lite Town:          ON"));
3437
3438         if (ironman_shops)
3439                 fprintf(fff, _("\n 店なし:             ON", "\n No Shops:           ON"));
3440
3441         if (ironman_downward)
3442                 fprintf(fff, _("\n 階段を上がれない:   ON", "\n Diving Only:        ON"));
3443
3444         if (ironman_rooms)
3445                 fprintf(fff, _("\n 普通でない部屋:     ON", "\n Unusual Rooms:      ON"));
3446
3447         if (ironman_nightmare)
3448                 fprintf(fff, _("\n 悪夢モード:         ON", "\n Nightmare Mode:     ON"));
3449
3450         if (ironman_empty_levels)
3451                 fprintf(fff, _("\n アリーナ:           ALWAYS", "\n Arena Levels:       ALWAYS"));
3452         else if (empty_levels)
3453                 fprintf(fff, _("\n アリーナ:           ENABLED", "\n Arena Levels:       ENABLED"));
3454         else
3455                 fprintf(fff, _("\n アリーナ:           OFF", "\n Arena Levels:       OFF"));
3456
3457         fputc('\n', fff);
3458
3459         if (current_world_ptr->noscore)
3460                 fprintf(fff, _("\n 何か不正なことをしてしまっています。\n", "\n You have done something illegal.\n"));
3461
3462         fputc('\n', fff);
3463 }
3464
3465
3466 /*!
3467  * @brief 闘技場の情報をファイルにダンプする
3468  * @param creature_ptr プレーヤーへの参照ポインタ
3469  * @param fff ファイルポインタ
3470  * @return なし
3471  */
3472 static void dump_aux_arena(player_type *creature_ptr, FILE *fff)
3473 {
3474         if (lite_town || vanilla_town) return;
3475
3476         if (creature_ptr->arena_number < 0)
3477         {
3478                 if (creature_ptr->arena_number <= ARENA_DEFEATED_OLD_VER)
3479                 {
3480                         fprintf(fff, _("\n 闘技場: 敗北\n", "\n Arena: Defeated\n"));
3481                 }
3482                 else
3483                 {
3484 #ifdef JP
3485                         fprintf(fff, "\n 闘技場: %d回戦で%sの前に敗北\n", -creature_ptr->arena_number,
3486                                 r_name + r_info[arena_info[-1 - creature_ptr->arena_number].r_idx].name);
3487 #else
3488                         fprintf(fff, "\n Arena: Defeated by %s in the %d%s fight\n",
3489                                 r_name + r_info[arena_info[-1 - creature_ptr->arena_number].r_idx].name,
3490                                 -creature_ptr->arena_number, get_ordinal_number_suffix(-creature_ptr->arena_number));
3491 #endif
3492                 }
3493
3494                 fprintf(fff, "\n");
3495                 return;
3496         }
3497
3498         if (creature_ptr->arena_number > MAX_ARENA_MONS + 2)
3499         {
3500                 fprintf(fff, _("\n 闘技場: 真のチャンピオン\n", "\n Arena: True Champion\n"));
3501                 fprintf(fff, "\n");
3502                 return;
3503         }
3504
3505         if (creature_ptr->arena_number > MAX_ARENA_MONS - 1)
3506         {
3507                 fprintf(fff, _("\n 闘技場: チャンピオン\n", "\n Arena: Champion\n"));
3508                 fprintf(fff, "\n");
3509                 return;
3510         }
3511
3512 #ifdef JP
3513         fprintf(fff, "\n 闘技場: %2d勝\n", (creature_ptr->arena_number > MAX_ARENA_MONS ? MAX_ARENA_MONS : creature_ptr->arena_number));
3514 #else
3515         fprintf(fff, "\n Arena: %2d Victor%s\n", (creature_ptr->arena_number > MAX_ARENA_MONS ? MAX_ARENA_MONS : creature_ptr->arena_number), (creature_ptr->arena_number > 1) ? "ies" : "y");
3516 #endif
3517         fprintf(fff, "\n");
3518 }
3519
3520
3521 /*!
3522  * @brief 撃破モンスターの情報をファイルにダンプする
3523  * @param fff ファイルポインタ
3524  * @return なし
3525  */
3526 static void dump_aux_monsters(FILE *fff)
3527 {
3528         fprintf(fff, _("\n  [倒したモンスター]\n\n", "\n  [Defeated Monsters]\n\n"));
3529
3530         /* Allocate the "who" array */
3531         MONRACE_IDX *who;
3532         u16b why = 2;
3533         C_MAKE(who, max_r_idx, MONRACE_IDX);
3534
3535         /* Count monster kills */
3536         long uniq_total = 0;
3537         long norm_total = 0;
3538         for (IDX k = 1; k < max_r_idx; k++)
3539         {
3540                 /* Ignore unused index */
3541                 monster_race *r_ptr = &r_info[k];
3542                 if (!r_ptr->name) continue;
3543
3544                 if (r_ptr->flags1 & RF1_UNIQUE)
3545                 {
3546                         bool dead = (r_ptr->max_num == 0);
3547                         if (dead)
3548                         {
3549                                 norm_total++;
3550
3551                                 /* Add a unique monster to the list */
3552                                 who[uniq_total++] = k;
3553                         }
3554
3555                         continue;
3556                 }
3557
3558                 if (r_ptr->r_pkills > 0)
3559                 {
3560                         norm_total += r_ptr->r_pkills;
3561                 }
3562         }
3563
3564         /* No monsters is defeated */
3565         if (norm_total < 1)
3566         {
3567                 fprintf(fff, _("まだ敵を倒していません。\n", "You have defeated no enemies yet.\n"));
3568                 C_KILL(who, max_r_idx, s16b);
3569                 return;
3570         }
3571
3572         /* Defeated more than one normal monsters */
3573         if (uniq_total == 0)
3574         {
3575 #ifdef JP
3576                 fprintf(fff, "%ld体の敵を倒しています。\n", norm_total);
3577 #else
3578                 fprintf(fff, "You have defeated %ld %s.\n", norm_total, norm_total == 1 ? "enemy" : "enemies");
3579 #endif
3580                 C_KILL(who, max_r_idx, s16b);
3581                 return;
3582         }
3583
3584         /* Defeated more than one unique monsters */
3585 #ifdef JP
3586         fprintf(fff, "%ld体のユニーク・モンスターを含む、合計%ld体の敵を倒しています。\n", uniq_total, norm_total);
3587 #else
3588         fprintf(fff, "You have defeated %ld %s including %ld unique monster%s in total.\n", norm_total, norm_total == 1 ? "enemy" : "enemies", uniq_total, (uniq_total == 1 ? "" : "s"));
3589 #endif
3590
3591         /* Sort the array by dungeon depth of monsters */
3592         ang_sort(who, &why, uniq_total, ang_sort_comp_hook, ang_sort_swap_hook);
3593         fprintf(fff, _("\n《上位%ld体のユニーク・モンスター》\n", "\n< Unique monsters top %ld >\n"), MIN(uniq_total, 10));
3594
3595         for (IDX k = uniq_total - 1; k >= 0 && k >= uniq_total - 10; k--)
3596         {
3597                 monster_race *r_ptr = &r_info[who[k]];
3598                 fprintf(fff, _("  %-40s (レベル%3d)\n", "  %-40s (level %3d)\n"), (r_name + r_ptr->name), (int)r_ptr->level);
3599         }
3600
3601         C_KILL(who, max_r_idx, s16b);
3602 }
3603
3604
3605 /*!
3606  * @brief 元種族情報をファイルにダンプする
3607  * @param creature_ptr プレーヤーへの参照ポインタ
3608  * @param fff ファイルポインタ
3609  * @return なし
3610  */
3611 static void dump_aux_race_history(player_type *creature_ptr, FILE *fff)
3612 {
3613         if (!creature_ptr->old_race1 && !creature_ptr->old_race2) return;
3614
3615         fprintf(fff, _("\n\n あなたは%sとして生まれた。", "\n\n You were born as %s."), race_info[creature_ptr->start_race].title);
3616         for (int i = 0; i < MAX_RACES; i++)
3617         {
3618                 if (creature_ptr->start_race == i) continue;
3619                 if (i < 32)
3620                 {
3621                         if (!(creature_ptr->old_race1 & 1L << i)) continue;
3622                 }
3623                 else
3624                 {
3625                         if (!(creature_ptr->old_race2 & 1L << (i - 32))) continue;
3626                 }
3627
3628                 fprintf(fff, _("\n あなたはかつて%sだった。", "\n You were a %s before."), race_info[i].title);
3629         }
3630
3631         fputc('\n', fff);
3632 }
3633
3634
3635 /*!
3636  * @brief 元魔法領域情報をファイルにダンプする
3637  * @param creature_ptr プレーヤーへの参照ポインタ
3638  * @param fff ファイルポインタ
3639  * @return なし
3640  */
3641 static void dump_aux_realm_history(player_type *creature_ptr, FILE *fff)
3642 {
3643         if (creature_ptr->old_realm) return;
3644
3645         fputc('\n', fff);
3646         for (int i = 0; i < MAX_MAGIC; i++)
3647         {
3648                 if (!(creature_ptr->old_realm & 1L << i)) continue;
3649                 fprintf(fff, _("\n あなたはかつて%s魔法を使えた。", "\n You were able to use %s magic before."), realm_names[i + 1]);
3650         }
3651
3652         fputc('\n', fff);
3653 }
3654
3655
3656 /*!
3657  * @brief 徳の情報をファイルにダンプする
3658  * @param creature_ptr プレーヤーへの参照ポインタ
3659  * @param fff ファイルポインタ
3660  * @return なし
3661  */
3662 static void dump_aux_virtues(player_type *creature_ptr, FILE *fff)
3663 {
3664         fprintf(fff, _("\n\n  [自分に関する情報]\n\n", "\n\n  [HP-rate & Max stat & Virtues]\n\n"));
3665
3666         int percent = (int)(((long)creature_ptr->player_hp[PY_MAX_LEVEL - 1] * 200L) /
3667                 (2 * creature_ptr->hitdie +
3668                 ((PY_MAX_LEVEL - 1 + 3) * (creature_ptr->hitdie + 1))));
3669
3670 #ifdef JP
3671         if (creature_ptr->knowledge & KNOW_HPRATE) fprintf(fff, "現在の体力ランク : %d/100\n\n", percent);
3672         else fprintf(fff, "現在の体力ランク : ???\n\n");
3673         fprintf(fff, "能力の最大値\n");
3674 #else
3675         if (creature_ptr->knowledge & KNOW_HPRATE) fprintf(fff, "Your current Life Rating is %d/100.\n\n", percent);
3676         else fprintf(fff, "Your current Life Rating is ???.\n\n");
3677         fprintf(fff, "Limits of maximum stats\n");
3678 #endif
3679         for (int v_nr = 0; v_nr < A_MAX; v_nr++)
3680         {
3681                 if ((creature_ptr->knowledge & KNOW_STAT) || creature_ptr->stat_max[v_nr] == creature_ptr->stat_max_max[v_nr]) fprintf(fff, "%s 18/%d\n", stat_names[v_nr], creature_ptr->stat_max_max[v_nr] - 18);
3682                 else fprintf(fff, "%s ???\n", stat_names[v_nr]);
3683         }
3684
3685         fprintf(fff, _("\n属性 : %s\n", "\nYour alignment : %s\n"), your_alignment(creature_ptr));
3686         fprintf(fff, "\n");
3687         dump_virtues(creature_ptr, fff);
3688 }
3689
3690
3691 /*!
3692  * @brief 突然変異の情報をファイルにダンプする
3693  * @param creature_ptr プレーヤーへの参照ポインタ
3694  * @param fff ファイルポインタ
3695  * @return なし
3696  */
3697 static void dump_aux_mutations(player_type *creature_ptr, FILE *fff)
3698 {
3699         if (creature_ptr->muta1 || creature_ptr->muta2 || creature_ptr->muta3)
3700         {
3701                 fprintf(fff, _("\n\n  [突然変異]\n\n", "\n\n  [Mutations]\n\n"));
3702                 dump_mutations(creature_ptr, fff);
3703         }
3704 }
3705
3706
3707 /*!
3708  * @brief 所持品の情報をファイルにダンプする
3709  * @param creature_ptr プレーヤーへの参照ポインタ
3710  * @param fff ファイルポインタ
3711  * @return なし
3712  */
3713 static void dump_aux_equipment_inventory(player_type *creature_ptr, FILE *fff)
3714 {
3715         GAME_TEXT o_name[MAX_NLEN];
3716         if (creature_ptr->equip_cnt)
3717         {
3718                 fprintf(fff, _("  [キャラクタの装備]\n\n", "  [Character Equipment]\n\n"));
3719                 for (int i = INVEN_RARM; i < INVEN_TOTAL; i++)
3720                 {
3721                         object_desc(creature_ptr, o_name, &creature_ptr->inventory_list[i], 0);
3722                         if ((((i == INVEN_RARM) && creature_ptr->hidarite) || ((i == INVEN_LARM) && creature_ptr->migite)) && creature_ptr->ryoute)
3723                                 strcpy(o_name, _("(武器を両手持ち)", "(wielding with two-hands)"));
3724
3725                         fprintf(fff, "%c) %s\n",
3726                                 index_to_label(i), o_name);
3727                 }
3728
3729                 fprintf(fff, "\n\n");
3730         }
3731
3732         fprintf(fff, _("  [キャラクタの持ち物]\n\n", "  [Character Inventory]\n\n"));
3733
3734         for (int i = 0; i < INVEN_PACK; i++)
3735         {
3736                 if (!creature_ptr->inventory_list[i].k_idx) break;
3737                 object_desc(creature_ptr, o_name, &creature_ptr->inventory_list[i], 0);
3738                 fprintf(fff, "%c) %s\n", index_to_label(i), o_name);
3739         }
3740
3741         fprintf(fff, "\n\n");
3742 }
3743
3744
3745 /*!
3746  * @brief 我が家と博物館のオブジェクト情報をファイルにダンプする
3747  * @param fff ファイルポインタ
3748  * @return なし
3749  */
3750 static void dump_aux_home_museum(player_type *creature_ptr, FILE *fff)
3751 {
3752         store_type  *st_ptr;
3753         st_ptr = &town_info[1].store[STORE_HOME];
3754
3755         GAME_TEXT o_name[MAX_NLEN];
3756         if (st_ptr->stock_num)
3757         {
3758                 fprintf(fff, _("  [我が家のアイテム]\n", "  [Home Inventory]\n"));
3759
3760                 TERM_LEN x = 1;
3761                 for (int i = 0; i < st_ptr->stock_num; i++)
3762                 {
3763                         if ((i % 12) == 0)
3764                                 fprintf(fff, _("\n ( %d ページ )\n", "\n ( page %d )\n"), x++);
3765                         object_desc(creature_ptr, o_name, &st_ptr->stock[i], 0);
3766                         fprintf(fff, "%c) %s\n", I2A(i % 12), o_name);
3767                 }
3768
3769                 fprintf(fff, "\n\n");
3770         }
3771
3772         st_ptr = &town_info[1].store[STORE_MUSEUM];
3773
3774         if (st_ptr->stock_num == 0) return;
3775
3776         fprintf(fff, _("  [博物館のアイテム]\n", "  [Museum]\n"));
3777
3778         TERM_LEN x = 1;
3779         for (int i = 0; i < st_ptr->stock_num; i++)
3780         {
3781 #ifdef JP
3782                 if ((i % 12) == 0) fprintf(fff, "\n ( %d ページ )\n", x++);
3783                 object_desc(creature_ptr, o_name, &st_ptr->stock[i], 0);
3784                 fprintf(fff, "%c) %s\n", I2A(i % 12), o_name);
3785 #else
3786                 if ((i % 12) == 0) fprintf(fff, "\n ( page %d )\n", x++);
3787                 object_desc(creature_ptr, o_name, &st_ptr->stock[i], 0);
3788                 fprintf(fff, "%c) %s\n", I2A(i % 12), o_name);
3789 #endif
3790         }
3791
3792         fprintf(fff, "\n\n");
3793 }
3794
3795
3796 /*!
3797  * @brief ダンプ出力のメインルーチン
3798  * Output the character dump to a file
3799  * @param creature_ptr プレーヤーへの参照ポインタ
3800  * @param fff ファイルポインタ
3801  * @return エラーコード
3802  */
3803 errr make_character_dump(player_type *creature_ptr, FILE *fff)
3804 {
3805 #ifdef JP
3806         fprintf(fff, "  [変愚蛮怒 %d.%d.%d キャラクタ情報]\n\n",
3807                 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH);
3808 #else
3809         fprintf(fff, "  [Hengband %d.%d.%d Character Dump]\n\n",
3810                 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH);
3811 #endif
3812         update_playtime();
3813
3814         dump_aux_display_player(creature_ptr, fff);
3815         dump_aux_last_message(creature_ptr, fff);
3816         dump_aux_options(fff);
3817         dump_aux_recall(fff);
3818         dump_aux_quest(creature_ptr, fff);
3819         dump_aux_arena(creature_ptr, fff);
3820         dump_aux_monsters(fff);
3821         dump_aux_virtues(creature_ptr, fff);
3822         dump_aux_race_history(creature_ptr, fff);
3823         dump_aux_realm_history(creature_ptr, fff);
3824         dump_aux_class_special(creature_ptr, fff);
3825         dump_aux_mutations(creature_ptr, fff);
3826         dump_aux_pet(creature_ptr, fff);
3827         fputs("\n\n", fff);
3828         dump_aux_equipment_inventory(creature_ptr, fff);
3829         dump_aux_home_museum(creature_ptr, fff);
3830
3831         fprintf(fff, _("  [チェックサム: \"%s\"]\n\n", "  [Check Sum: \"%s\"]\n\n"), get_check_sum());
3832         return 0;
3833 }
3834
3835
3836 /*!
3837  * @brief プレイヤーステータスをファイルダンプ出力する
3838  * Hack -- Dump a character description file
3839  * @param creature_ptr プレーヤーへの参照ポインタ
3840  * @param name 出力ファイル名
3841  * @return エラーコード
3842  * @details
3843  * Allow the "full" flag to dump additional info,
3844  * and trigger its usage from various places in the code.
3845  */
3846 errr file_character(player_type *creature_ptr, concptr name)
3847 {
3848         char buf[1024];
3849         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name);
3850
3851         FILE_TYPE(FILE_TYPE_TEXT);
3852
3853         int     fd = fd_open(buf, O_RDONLY);
3854         if (fd >= 0)
3855         {
3856                 char out_val[160];
3857                 (void)fd_close(fd);
3858                 (void)sprintf(out_val, _("現存するファイル %s に上書きしますか? ", "Replace existing file %s? "), buf);
3859                 if (get_check_strict(out_val, CHECK_NO_HISTORY)) fd = -1;
3860         }
3861
3862         FILE *fff = NULL;
3863         if (fd < 0) fff = my_fopen(buf, "w");
3864
3865         if (!fff)
3866         {
3867                 prt(_("キャラクタ情報のファイルへの書き出しに失敗しました!", "Character dump failed!"), 0, 0);
3868                 (void)inkey();
3869                 return -1;
3870         }
3871
3872         (void)make_character_dump(creature_ptr, fff);
3873         my_fclose(fff);
3874         msg_print(_("キャラクタ情報のファイルへの書き出しに成功しました。", "Character dump successful."));
3875         msg_print(NULL);
3876         return 0;
3877 }
3878
3879
3880 /*!
3881  * @brief ファイル内容の一行をコンソールに出力する
3882  * Display single line of on-line help file
3883  * @param str 出力する文字列
3884  * @param cy コンソールの行
3885  * @param shower 確認中
3886  * @return なし
3887  * @details
3888  * <pre>
3889  * You can insert some special color tag to change text color.
3890  * Such as...
3891  * WHITETEXT [[[[y|SOME TEXT WHICH IS DISPLAYED IN YELLOW| WHITETEXT
3892  * A colored segment is between "[[[[y|" and the last "|".
3893  * You can use any single character in place of the "|".
3894  * </pre>
3895  */
3896 static void show_file_aux_line(concptr str, int cy, concptr shower)
3897 {
3898         char lcstr[1024];
3899         if (shower)
3900         {
3901                 strcpy(lcstr, str);
3902                 str_tolower(lcstr);
3903         }
3904
3905         int cx = 0;
3906         Term_gotoxy(cx, cy);
3907
3908         static const char tag_str[] = "[[[[";
3909         byte color = TERM_WHITE;
3910         char in_tag = '\0';
3911         for (int i = 0; str[i];)
3912         {
3913                 int len = strlen(&str[i]);
3914                 int showercol = len + 1;
3915                 int bracketcol = len + 1;
3916                 int endcol = len;
3917                 concptr ptr;
3918
3919                 /* Search for a shower string in the line */
3920                 if (shower)
3921                 {
3922                         ptr = my_strstr(&lcstr[i], shower);
3923                         if (ptr) showercol = ptr - &lcstr[i];
3924                 }
3925
3926                 /* Search for a color segment tag */
3927                 ptr = in_tag ? my_strchr(&str[i], in_tag) : my_strstr(&str[i], tag_str);
3928                 if (ptr) bracketcol = ptr - &str[i];
3929
3930                 /* A color tag is found */
3931                 if (bracketcol < endcol) endcol = bracketcol;
3932
3933                 /* The shower string is found before the color tag */
3934                 if (showercol < endcol) endcol = showercol;
3935
3936                 /* Print a segment of the line */
3937                 Term_addstr(endcol, color, &str[i]);
3938                 cx += endcol;
3939                 i += endcol;
3940
3941                 if (endcol == showercol)
3942                 {
3943                         int showerlen = strlen(shower);
3944
3945                         /* Print the shower string in yellow */
3946                         Term_addstr(showerlen, TERM_YELLOW, &str[i]);
3947                         cx += showerlen;
3948                         i += showerlen;
3949                         continue;
3950                 }
3951
3952                 if (endcol != bracketcol) continue;
3953
3954                 if (in_tag)
3955                 {
3956                         /* Found the end of colored segment */
3957                         i++;
3958
3959                         /* Now looking for an another tag_str */
3960                         in_tag = '\0';
3961
3962                         /* Set back to the default color */
3963                         color = TERM_WHITE;
3964                         continue;
3965                 }
3966
3967                 /* Found a tag_str, and get a tag color */
3968                 i += sizeof(tag_str) - 1;
3969
3970                 /* Get tag color */
3971                 color = color_char_to_attr(str[i]);
3972
3973                 /* Illegal color tag */
3974                 if (color == 255 || str[i + 1] == '\0')
3975                 {
3976                         /* Illegal color tag */
3977                         color = TERM_WHITE;
3978
3979                         /* Print the broken tag as a string */
3980                         Term_addstr(-1, TERM_WHITE, tag_str);
3981                         cx += sizeof(tag_str) - 1;
3982                         continue;
3983                 }
3984
3985                 i++;
3986                 in_tag = str[i];
3987                 i++;
3988         }
3989
3990         Term_erase(cx, cy, 255);
3991 }
3992
3993
3994 /*!
3995  * @brief ファイル内容をコンソールに出力する
3996  * Recursive file perusal.
3997  * @param creature_ptr プレーヤーへの参照ポインタ
3998  * @param show_version TRUEならばコンソール上にゲームのバージョンを表示する
3999  * @param name ファイル名の文字列
4000  * @param what 内容キャプションの文字列
4001  * @param line 表示の現在行
4002  * @param mode オプション
4003  * @return なし
4004  * @details
4005  * <pre>
4006  * Process various special text in the input file, including
4007  * the "menu" structures used by the "help file" system.
4008  * Return FALSE on 'q' to exit from a deep, otherwise TRUE.
4009  * </pre>
4010  */
4011 bool show_file(player_type *creature_ptr, bool show_version, concptr name, concptr what, int line, BIT_FLAGS mode)
4012 {
4013         int i, n, skey;
4014         int next = 0;
4015         int size = 0;
4016         int back = 0;
4017         bool menu = FALSE;
4018         FILE *fff = NULL;
4019         concptr find = NULL;
4020         concptr tag = NULL;
4021         char finder_str[81];
4022         char shower_str[81];
4023         char back_str[81];
4024         concptr shower = NULL;
4025         char filename[1024];
4026         char caption[128];
4027         char path[1024];
4028         char buf[1024];
4029         char hook[68][32];
4030         bool reverse = (line < 0);
4031         int wid, hgt, rows;
4032         Term_get_size(&wid, &hgt);
4033         rows = hgt - 4;
4034
4035         strcpy(finder_str, "");
4036         strcpy(shower_str, "");
4037         strcpy(caption, "");
4038         for (i = 0; i < 68; i++)
4039         {
4040                 hook[i][0] = '\0';
4041         }
4042
4043         strcpy(filename, name);
4044         n = strlen(filename);
4045
4046         for (i = 0; i < n; i++)
4047         {
4048                 if (filename[i] == '#')
4049                 {
4050                         filename[i] = '\0';
4051                         tag = filename + i + 1;
4052                         break;
4053                 }
4054         }
4055
4056         name = filename;
4057         if (what)
4058         {
4059                 strcpy(caption, what);
4060                 strcpy(path, name);
4061                 fff = my_fopen(path, "r");
4062         }
4063
4064         if (!fff)
4065         {
4066                 sprintf(caption, _("ヘルプ・ファイル'%s'", "Help file '%s'"), name);
4067                 path_build(path, sizeof(path), ANGBAND_DIR_HELP, name);
4068                 fff = my_fopen(path, "r");
4069         }
4070
4071         if (!fff)
4072         {
4073                 sprintf(caption, _("スポイラー・ファイル'%s'", "Info file '%s'"), name);
4074                 path_build(path, sizeof(path), ANGBAND_DIR_INFO, name);
4075                 fff = my_fopen(path, "r");
4076         }
4077
4078         if (!fff)
4079         {
4080                 path_build(path, sizeof(path), ANGBAND_DIR, name);
4081
4082                 for (i = 0; path[i]; i++)
4083                         if ('\\' == path[i])
4084                                 path[i] = PATH_SEP[0];
4085
4086                 sprintf(caption, _("スポイラー・ファイル'%s'", "Info file '%s'"), name);
4087                 fff = my_fopen(path, "r");
4088         }
4089
4090         if (!fff)
4091         {
4092                 msg_format(_("'%s'をオープンできません。", "Cannot open '%s'."), name);
4093                 msg_print(NULL);
4094
4095                 return TRUE;
4096         }
4097
4098         while (TRUE)
4099         {
4100                 char *str = buf;
4101                 if (my_fgets(fff, buf, sizeof(buf))) break;
4102                 if (!prefix(str, "***** "))
4103                 {
4104                         next++;
4105                         continue;
4106                 }
4107
4108                 if ((str[6] == '[') && isalpha(str[7]))
4109                 {
4110                         int k = str[7] - 'A';
4111                         menu = TRUE;
4112                         if ((str[8] == ']') && (str[9] == ' '))
4113                         {
4114                                 strncpy(hook[k], str + 10, 31);
4115                                 hook[k][31] = '\0';
4116                         }
4117
4118                         continue;
4119                 }
4120
4121                 if (str[6] != '<') continue;
4122
4123                 size_t len = strlen(str);
4124                 if (str[len - 1] == '>')
4125                 {
4126                         str[len - 1] = '\0';
4127                         if (tag && streq(str + 7, tag)) line = next;
4128                 }
4129         }
4130
4131         size = next;
4132         if (line == -1) line = ((size - 1) / rows)*rows;
4133         Term_clear();
4134
4135         while (TRUE)
4136         {
4137                 if (line >= size - rows)
4138                         line = size - rows;
4139                 if (line < 0) line = 0;
4140
4141                 if (next > line)
4142                 {
4143                         my_fclose(fff);
4144                         fff = my_fopen(path, "r");
4145                         if (!fff) return FALSE;
4146
4147                         next = 0;
4148                 }
4149
4150                 while (next < line)
4151                 {
4152                         if (my_fgets(fff, buf, sizeof(buf))) break;
4153                         if (prefix(buf, "***** ")) continue;
4154                         next++;
4155                 }
4156
4157                 for (i = 0; i < rows; )
4158                 {
4159                         concptr str = buf;
4160                         if (!i) line = next;
4161                         if (my_fgets(fff, buf, sizeof(buf))) break;
4162                         if (prefix(buf, "***** ")) continue;
4163                         next++;
4164                         if (find && !i)
4165                         {
4166                                 char lc_buf[1024];
4167                                 strcpy(lc_buf, str);
4168                                 str_tolower(lc_buf);
4169                                 if (!my_strstr(lc_buf, find)) continue;
4170                         }
4171
4172                         find = NULL;
4173                         show_file_aux_line(str, i + 2, shower);
4174                         i++;
4175                 }
4176
4177                 while (i < rows)
4178                 {
4179                         Term_erase(0, i + 2, 255);
4180                         i++;
4181                 }
4182
4183                 if (find)
4184                 {
4185                         bell();
4186                         line = back;
4187                         find = NULL;
4188                         continue;
4189                 }
4190
4191                 if (show_version)
4192                 {
4193                         prt(format(_("[変愚蛮怒 %d.%d.%d, %s, %d/%d]", "[Hengband %d.%d.%d, %s, Line %d/%d]"),
4194                                 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH,
4195                                 caption, line, size), 0, 0);
4196                 }
4197                 else
4198                 {
4199                         prt(format(_("[%s, %d/%d]", "[%s, Line %d/%d]"),
4200                                 caption, line, size), 0, 0);
4201                 }
4202
4203                 if (size <= rows)
4204                 {
4205                         prt(_("[キー:(?)ヘルプ (ESC)終了]", "[Press ESC to exit.]"), hgt - 1, 0);
4206                 }
4207                 else
4208                 {
4209 #ifdef JP
4210                         if (reverse)
4211                                 prt("[キー:(RET/スペース)↑ (-)↓ (?)ヘルプ (ESC)終了]", hgt - 1, 0);
4212                         else
4213                                 prt("[キー:(RET/スペース)↓ (-)↑ (?)ヘルプ (ESC)終了]", hgt - 1, 0);
4214 #else
4215                         prt("[Press Return, Space, -, =, /, |, or ESC to exit.]", hgt - 1, 0);
4216 #endif
4217                 }
4218
4219                 skey = inkey_special(TRUE);
4220                 switch (skey)
4221                 {
4222                 case '?':
4223                         if (strcmp(name, _("jhelpinfo.txt", "helpinfo.txt")) != 0)
4224                                 show_file(creature_ptr, TRUE, _("jhelpinfo.txt", "helpinfo.txt"), NULL, 0, mode);
4225                         break;
4226                 case '=':
4227                         prt(_("強調: ", "Show: "), hgt - 1, 0);
4228
4229                         strcpy(back_str, shower_str);
4230                         if (askfor(shower_str, 80))
4231                         {
4232                                 if (shower_str[0])
4233                                 {
4234                                         str_tolower(shower_str);
4235                                         shower = shower_str;
4236                                 }
4237                                 else shower = NULL;
4238                         }
4239                         else strcpy(shower_str, back_str);
4240                         break;
4241
4242                 case '/':
4243                 case KTRL('s'):
4244                         prt(_("検索: ", "Find: "), hgt - 1, 0);
4245                         strcpy(back_str, finder_str);
4246                         if (askfor(finder_str, 80))
4247                         {
4248                                 if (finder_str[0])
4249                                 {
4250                                         find = finder_str;
4251                                         back = line;
4252                                         line = line + 1;
4253                                         str_tolower(finder_str);
4254                                         shower = finder_str;
4255                                 }
4256                                 else shower = NULL;
4257                         }
4258                         else strcpy(finder_str, back_str);
4259                         break;
4260
4261                 case '#':
4262                 {
4263                         char tmp[81];
4264                         prt(_("行: ", "Goto Line: "), hgt - 1, 0);
4265                         strcpy(tmp, "0");
4266
4267                         if (askfor(tmp, 80)) line = atoi(tmp);
4268                         break;
4269                 }
4270
4271                 case SKEY_TOP:
4272                         line = 0;
4273                         break;
4274
4275                 case SKEY_BOTTOM:
4276                         line = ((size - 1) / rows) * rows;
4277                         break;
4278
4279                 case '%':
4280                 {
4281                         char tmp[81];
4282                         prt(_("ファイル・ネーム: ", "Goto File: "), hgt - 1, 0);
4283                         strcpy(tmp, _("jhelp.hlp", "help.hlp"));
4284
4285                         if (askfor(tmp, 80))
4286                         {
4287                                 if (!show_file(creature_ptr, TRUE, tmp, NULL, 0, mode)) skey = 'q';
4288                         }
4289
4290                         break;
4291                 }
4292
4293                 case '-':
4294                         line = line + (reverse ? rows : -rows);
4295                         if (line < 0) line = 0;
4296                         break;
4297
4298                 case SKEY_PGUP:
4299                         line = line - rows;
4300                         if (line < 0) line = 0;
4301                         break;
4302
4303                 case '\n':
4304                 case '\r':
4305                         line = line + (reverse ? -1 : 1);
4306                         if (line < 0) line = 0;
4307                         break;
4308
4309                 case '8':
4310                 case SKEY_UP:
4311                         line--;
4312                         if (line < 0) line = 0;
4313                         break;
4314
4315                 case '2':
4316                 case SKEY_DOWN:
4317                         line++;
4318                         break;
4319
4320                 case ' ':
4321                         line = line + (reverse ? -rows : rows);
4322                         if (line < 0) line = 0;
4323                         break;
4324
4325                 case SKEY_PGDOWN:
4326                         line = line + rows;
4327                         break;
4328                 }
4329
4330                 if (menu)
4331                 {
4332                         int key = -1;
4333                         if (!(skey & SKEY_MASK) && isalpha(skey))
4334                                 key = skey - 'A';
4335
4336                         if ((key > -1) && hook[key][0])
4337                         {
4338                                 /* Recurse on that file */
4339                                 if (!show_file(creature_ptr, TRUE, hook[key], NULL, 0, mode))
4340                                         skey = 'q';
4341                         }
4342                 }
4343
4344                 if (skey == '|')
4345                 {
4346                         FILE *ffp;
4347                         char buff[1024];
4348                         char xtmp[82];
4349
4350                         strcpy(xtmp, "");
4351
4352                         if (!get_string(_("ファイル名: ", "File name: "), xtmp, 80)) continue;
4353                         my_fclose(fff);
4354                         path_build(buff, sizeof(buff), ANGBAND_DIR_USER, xtmp);
4355
4356                         /* Hack -- Re-Open the file */
4357                         fff = my_fopen(path, "r");
4358
4359                         ffp = my_fopen(buff, "w");
4360
4361                         if (!(fff && ffp))
4362                         {
4363                                 msg_print(_("ファイルを開けません。", "Failed to open file."));
4364                                 skey = ESCAPE;
4365                                 break;
4366                         }
4367
4368                         sprintf(xtmp, "%s: %s", creature_ptr->name, what ? what : caption);
4369                         my_fputs(ffp, xtmp, 80);
4370                         my_fputs(ffp, "\n", 80);
4371
4372                         while (!my_fgets(fff, buff, sizeof(buff)))
4373                                 my_fputs(ffp, buff, 80);
4374                         my_fclose(fff);
4375                         my_fclose(ffp);
4376                         fff = my_fopen(path, "r");
4377                 }
4378
4379                 if ((skey == ESCAPE) || (skey == '<')) break;
4380
4381                 if (skey == KTRL('q')) skey = 'q';
4382
4383                 if (skey == 'q') break;
4384         }
4385
4386         my_fclose(fff);
4387         if (skey == 'q') return FALSE;
4388
4389         return TRUE;
4390 }
4391
4392
4393 /*!
4394  * @brief ヘルプを表示するコマンドのメインルーチン
4395  * Peruse the On-Line-Help
4396  * @param creature_ptr プレーヤーへの参照ポインタ
4397  * @return なし
4398  * @details
4399  */
4400 void do_cmd_help(player_type *creature_ptr)
4401 {
4402         screen_save();
4403         (void)show_file(creature_ptr, TRUE, _("jhelp.hlp", "help.hlp"), NULL, 0, 0);
4404         screen_load();
4405 }
4406
4407
4408 /*!
4409  * @brief プレイヤーの名前をチェックして修正する
4410  * Process the player name.
4411  * @param player_ptr プレーヤーへの参照ポインタ
4412  * @param sf セーブファイル名に合わせた修正を行うならばTRUE
4413  * @return なし
4414  * @details
4415  * Extract a clean "base name".
4416  * Build the savefile name if needed.
4417  */
4418 void process_player_name(player_type *creature_ptr, bool sf)
4419 {
4420         char old_player_base[32] = "";
4421         if (current_world_ptr->character_generated)
4422                 strcpy(old_player_base, creature_ptr->base_name);
4423
4424         for (int i = 0; creature_ptr->name[i]; i++)
4425         {
4426 #ifdef JP
4427                 if (iskanji(creature_ptr->name[i])) { i++; continue; }
4428                 if (iscntrl((unsigned char)creature_ptr->name[i]))
4429 #else
4430                 if (iscntrl(creature_ptr->name[i]))
4431 #endif
4432                 {
4433                         quit_fmt(_("'%s' という名前は不正なコントロールコードを含んでいます。", "The name '%s' contains control chars!"), creature_ptr->name);
4434                 }
4435         }
4436
4437         int k = 0;
4438         for (int i = 0; creature_ptr->name[i]; i++)
4439         {
4440 #ifdef JP
4441                 unsigned char c = creature_ptr->name[i];
4442 #else
4443                 char c = creature_ptr->name[i];
4444 #endif
4445
4446 #ifdef JP
4447                 if (iskanji(c)) {
4448                         if (k + 2 >= sizeof(creature_ptr->base_name) || !creature_ptr->name[i + 1])
4449                                 break;
4450                         creature_ptr->base_name[k++] = c;
4451                         i++;
4452                         creature_ptr->base_name[k++] = creature_ptr->name[i];
4453                 }
4454 #ifdef SJIS
4455                 else if (iskana(c)) creature_ptr->base_name[k++] = c;
4456 #endif
4457                 else
4458 #endif
4459                         if (!strncmp(PATH_SEP, creature_ptr->name + i, strlen(PATH_SEP)))
4460                         {
4461                                 creature_ptr->base_name[k++] = '_';
4462                                 i += strlen(PATH_SEP);
4463                         }
4464 #if defined(WINDOWS)
4465                         else if (my_strchr("\"*,/:;<>?\\|", c))
4466                                 creature_ptr->base_name[k++] = '_';
4467 #endif
4468                         else if (isprint(c))
4469                                 creature_ptr->base_name[k++] = c;
4470         }
4471
4472         creature_ptr->base_name[k] = '\0';
4473         if (!creature_ptr->base_name[0])
4474                 strcpy(creature_ptr->base_name, "PLAYER");
4475
4476 #ifdef SAVEFILE_MUTABLE
4477         sf = TRUE;
4478 #endif
4479         if (!savefile_base[0] && savefile[0])
4480         {
4481                 concptr s;
4482                 s = savefile;
4483                 while (TRUE)
4484                 {
4485                         concptr t;
4486                         t = my_strstr(s, PATH_SEP);
4487                         if (!t)
4488                                 break;
4489                         s = t + 1;
4490                 }
4491
4492                 strcpy(savefile_base, s);
4493         }
4494
4495         if (!savefile_base[0] || !savefile[0])
4496                 sf = TRUE;
4497
4498         if (sf)
4499         {
4500                 char temp[128];
4501
4502                 strcpy(savefile_base, creature_ptr->base_name);
4503
4504 #ifdef SAVEFILE_USE_UID
4505                 /* Rename the savefile, using the creature_ptr->player_uid and creature_ptr->base_name */
4506                 (void)sprintf(temp, "%d.%s", creature_ptr->player_uid, creature_ptr->base_name);
4507 #else
4508                 /* Rename the savefile, using the creature_ptr->base_name */
4509                 (void)sprintf(temp, "%s", creature_ptr->base_name);
4510 #endif
4511                 path_build(savefile, sizeof(savefile), ANGBAND_DIR_SAVE, temp);
4512         }
4513
4514         if (current_world_ptr->character_generated && !streq(old_player_base, creature_ptr->base_name))
4515         {
4516                 autopick_load_pref(creature_ptr, FALSE);
4517         }
4518 }
4519
4520
4521 /*!
4522  * @brief プレイヤーの名前を変更するコマンドのメインルーチン
4523  * Gets a name for the character, reacting to name changes.
4524  * @param creature_ptr プレーヤーへの参照ポインタ
4525  * @return なし
4526  * @details
4527  * <pre>
4528  * Assumes that "display_player()" has just been called
4529  * Perhaps we should NOT ask for a name (at "birth()") on
4530  * Unix machines?  XXX XXX
4531  * What a horrible name for a global function.
4532  * </pre>
4533  */
4534 void get_name(player_type *creature_ptr)
4535 {
4536         char tmp[64];
4537         strcpy(tmp, creature_ptr->name);
4538
4539         if (get_string(_("キャラクターの名前を入力して下さい: ", "Enter a name for your character: "), tmp, 15))
4540         {
4541                 strcpy(creature_ptr->name, tmp);
4542         }
4543
4544         if (strlen(creature_ptr->name) == 0)
4545         {
4546                 strcpy(creature_ptr->name, "PLAYER");
4547         }
4548
4549         strcpy(tmp, ap_ptr->title);
4550 #ifdef JP
4551         if (ap_ptr->no == 1)
4552                 strcat(tmp, "の");
4553 #else
4554         strcat(tmp, " ");
4555 #endif
4556         strcat(tmp, creature_ptr->name);
4557
4558         Term_erase(34, 1, 255);
4559         c_put_str(TERM_L_BLUE, tmp, 1, 34);
4560         clear_from(22);
4561 }
4562
4563
4564 /*!
4565  * @brief セーブするコマンドのメインルーチン
4566  * Save the game
4567  * @param creature_ptr プレーヤーへの参照ポインタ
4568  * @param is_autosave オートセーブ中の処理ならばTRUE
4569  * @return なし
4570  * @details
4571  */
4572 void do_cmd_save_game(player_type *creature_ptr, int is_autosave)
4573 {
4574         if (is_autosave)
4575         {
4576                 msg_print(_("自動セーブ中", "Autosaving the game..."));
4577         }
4578         else
4579         {
4580                 disturb(creature_ptr, TRUE, TRUE);
4581         }
4582
4583         msg_print(NULL);
4584         handle_stuff(creature_ptr);
4585         prt(_("ゲームをセーブしています...", "Saving game..."), 0, 0);
4586         Term_fresh();
4587         (void)strcpy(creature_ptr->died_from, _("(セーブ)", "(saved)"));
4588         signals_ignore_tstp();
4589         if (save_player(creature_ptr))
4590         {
4591                 prt(_("ゲームをセーブしています... 終了", "Saving game... done."), 0, 0);
4592         }
4593         else
4594         {
4595                 prt(_("ゲームをセーブしています... 失敗!", "Saving game... failed!"), 0, 0);
4596         }
4597
4598         signals_handle_tstp();
4599         Term_fresh();
4600         (void)strcpy(creature_ptr->died_from, _("(元気に生きている)", "(alive and well)"));
4601         current_world_ptr->is_loading_now = FALSE;
4602         update_creature(creature_ptr);
4603         mproc_init(creature_ptr->current_floor_ptr);
4604         current_world_ptr->is_loading_now = TRUE;
4605 }
4606
4607
4608 /*!
4609  * @brief セーブ後にゲーム中断フラグを立てる/
4610  * Save the game and exit
4611  * @return なし
4612  * @details
4613  */
4614 void do_cmd_save_and_exit(player_type *creature_ptr)
4615 {
4616         creature_ptr->playing = FALSE;
4617         creature_ptr->leaving = TRUE;
4618         exe_write_diary(creature_ptr, DIARY_GAMESTART, 0, _("----ゲーム中断----", "---- Save and Exit Game ----"));
4619 }
4620
4621
4622 /*!
4623  * @brief 異常発生時のゲーム緊急終了処理 /
4624  * Handle abrupt death of the visual system
4625  * @param creature_ptr プレーヤーへの参照ポインタ
4626  * @return なし
4627  * @details
4628  * <pre>
4629  * This routine is called only in very rare situations, and only
4630  * by certain visual systems, when they experience fatal errors.
4631  * XXX XXX Hack -- clear the death flag when creating a HANGUP
4632  * save file so that player can see tombstone when restart.
4633  * </pre>
4634  */
4635 void exit_game_panic(player_type *creature_ptr)
4636 {
4637         if (!current_world_ptr->character_generated || current_world_ptr->character_saved)
4638                 quit(_("緊急事態", "panic"));
4639         msg_flag = FALSE;
4640
4641         prt("", 0, 0);
4642         disturb(creature_ptr, TRUE, TRUE);
4643         if (creature_ptr->chp < 0) creature_ptr->is_dead = FALSE;
4644
4645         creature_ptr->panic_save = 1;
4646         signals_ignore_tstp();
4647         (void)strcpy(creature_ptr->died_from, _("(緊急セーブ)", "(panic save)"));
4648         if (!save_player(creature_ptr)) quit(_("緊急セーブ失敗!", "panic save failed!"));
4649         quit(_("緊急セーブ成功!", "panic save succeeded!"));
4650 }
4651
4652
4653 /*!
4654  * @brief ファイルからランダムに行を一つ取得する /
4655  * Get a random line from a file
4656  * @param file_name ファイル名
4657  * @param entry 特定条件時のN:タグヘッダID
4658  * @param output 出力先の文字列参照ポインタ
4659  * @return エラーコード
4660  * @details
4661  * <pre>
4662  * Based on the monster speech patch by Matt Graham,
4663  * </pre>
4664  */
4665 errr get_rnd_line(concptr file_name, int entry, char *output)
4666 {
4667         char buf[1024];
4668         path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, file_name);
4669         FILE *fp;
4670         fp = my_fopen(buf, "r");
4671         if (!fp) return -1;
4672
4673         int test;
4674         int line_num = 0;
4675         while (TRUE)
4676         {
4677                 if (my_fgets(fp, buf, sizeof(buf)) != 0)
4678                 {
4679                         my_fclose(fp);
4680                         return -1;
4681                 }
4682
4683                 line_num++;
4684                 if ((buf[0] != 'N') || (buf[1] != ':')) continue;
4685
4686                 if (buf[2] == '*')
4687                 {
4688                         break;
4689                 }
4690                 else if (buf[2] == 'M')
4691                 {
4692                         if (r_info[entry].flags1 & RF1_MALE) break;
4693                 }
4694                 else if (buf[2] == 'F')
4695                 {
4696                         if (r_info[entry].flags1 & RF1_FEMALE) break;
4697                 }
4698                 else if (sscanf(&(buf[2]), "%d", &test) != EOF)
4699                 {
4700                         if (test == entry) break;
4701                 }
4702
4703                 msg_format("Error in line %d of %s!", line_num, file_name);
4704                 my_fclose(fp);
4705                 return -1;
4706         }
4707
4708         int counter;
4709         for (counter = 0; ; counter++)
4710         {
4711                 while (TRUE)
4712                 {
4713                         test = my_fgets(fp, buf, sizeof(buf));
4714                         if (!test)
4715                         {
4716                                 /* Ignore lines starting with 'N:' */
4717                                 if ((buf[0] == 'N') && (buf[1] == ':')) continue;
4718
4719                                 if (buf[0] != '#') break;
4720                         }
4721                         else break;
4722                 }
4723
4724                 if (!buf[0]) break;
4725
4726                 if (one_in_(counter + 1)) strcpy(output, buf);
4727         }
4728
4729         my_fclose(fp);
4730         return counter ? 0 : -1;
4731 }
4732
4733
4734 #ifdef JP
4735 /*!
4736  * @brief ファイルからランダムに行を一つ取得する(日本語文字列のみ) /
4737  * @param file_name ファイル名
4738  * @param entry 特定条件時のN:タグヘッダID
4739  * @param output 出力先の文字列参照ポインタ
4740  * @param count 試行回数
4741  * @return エラーコード
4742  * @details
4743  */
4744 errr get_rnd_line_jonly(concptr file_name, int entry, char *output, int count)
4745 {
4746         errr result = 1;
4747         for (int i = 0; i < count; i++)
4748         {
4749                 result = get_rnd_line(file_name, entry, output);
4750                 if (result) break;
4751                 bool kanji = FALSE;
4752                 for (int j = 0; output[j]; j++) kanji |= iskanji(output[j]);
4753                 if (kanji) break;
4754         }
4755
4756         return result;
4757 }
4758 #endif
4759
4760
4761 /*!
4762  * @brief 自動拾いファイルを読み込む /
4763  * @param creature_ptr プレーヤーへの参照ポインタ
4764  * @param name ファイル名
4765  * @details
4766  */
4767 errr process_autopick_file(player_type *creature_ptr, concptr name)
4768 {
4769         char buf[1024];
4770         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name);
4771         errr err = process_pref_file_aux(creature_ptr, buf, PREF_TYPE_AUTOPICK);
4772         return err;
4773 }
4774
4775
4776 /*!
4777  * @brief プレイヤーの生い立ちファイルを読み込む /
4778  * Process file for player's history editor.
4779  * @param creature_ptr プレーヤーへの参照ポインタ
4780  * @param name ファイル名
4781  * @return エラーコード
4782  * @details
4783  */
4784 errr process_histpref_file(player_type *creature_ptr, concptr name)
4785 {
4786         bool old_character_xtra = current_world_ptr->character_xtra;
4787         char buf[1024];
4788         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name);
4789
4790         /* Hack -- prevent modification birth options in this file */
4791         current_world_ptr->character_xtra = TRUE;
4792         errr err = process_pref_file_aux(creature_ptr, buf, PREF_TYPE_HISTPREF);
4793         current_world_ptr->character_xtra = old_character_xtra;
4794         return err;
4795 }
4796
4797
4798 /*!
4799  * @brief ファイル位置をシーク /
4800  * @param creature_ptr プレーヤーへの参照ポインタ
4801  * @param fd ファイルディスクリプタ
4802  * @param where ファイルバイト位置
4803  * @param flag FALSEならば現ファイルを超えた位置へシーク時エラー、TRUEなら足りない間を0で埋め尽くす
4804  * @return エラーコード
4805  * @details
4806  */
4807 static errr counts_seek(player_type *creature_ptr, int fd, u32b where, bool flag)
4808 {
4809         char temp1[128], temp2[128];
4810 #ifdef SAVEFILE_USE_UID
4811         (void)sprintf(temp1, "%d.%s.%d%d%d", creature_ptr->player_uid, savefile_base, creature_ptr->pclass, creature_ptr->pseikaku, creature_ptr->age);
4812 #else
4813         (void)sprintf(temp1, "%s.%d%d%d", savefile_base, creature_ptr->pclass, creature_ptr->pseikaku, creature_ptr->age);
4814 #endif
4815         for (int i = 0; temp1[i]; i++)
4816                 temp1[i] ^= (i + 1) * 63;
4817
4818         int seekpoint = 0;
4819         u32b zero_header[3] = { 0L, 0L, 0L };
4820         while (TRUE)
4821         {
4822                 if (fd_seek(fd, seekpoint + 3 * sizeof(u32b)))
4823                         return 1;
4824                 if (fd_read(fd, (char*)(temp2), sizeof(temp2)))
4825                 {
4826                         if (!flag)
4827                                 return 1;
4828                         /* add new name */
4829                         fd_seek(fd, seekpoint);
4830                         fd_write(fd, (char*)zero_header, 3 * sizeof(u32b));
4831                         fd_write(fd, (char*)(temp1), sizeof(temp1));
4832                         break;
4833                 }
4834
4835                 if (strcmp(temp1, temp2) == 0)
4836                         break;
4837
4838                 seekpoint += 128 + 3 * sizeof(u32b);
4839         }
4840
4841         return fd_seek(fd, seekpoint + where * sizeof(u32b));
4842 }
4843
4844
4845 /*!
4846  * @brief ファイル位置を読み込む
4847  * @param creature_ptr プレーヤーへの参照ポインタ
4848  * @param where ファイルバイト位置
4849  * @return エラーコード
4850  * @details
4851  */
4852 u32b counts_read(player_type *creature_ptr, int where)
4853 {
4854         char buf[1024];
4855         path_build(buf, sizeof(buf), ANGBAND_DIR_DATA, _("z_info_j.raw", "z_info.raw"));
4856         int fd = fd_open(buf, O_RDONLY);
4857
4858         u32b count = 0;
4859         if (counts_seek(creature_ptr, fd, where, FALSE) ||
4860                 fd_read(fd, (char*)(&count), sizeof(u32b)))
4861                 count = 0;
4862
4863         (void)fd_close(fd);
4864
4865         return count;
4866 }
4867
4868
4869 /*!
4870  * @brief ファイル位置に書き込む /
4871  * @param creature_ptr プレーヤーへの参照ポインタ
4872  * @param where ファイルバイト位置
4873  * @param count 書き込む値
4874  * @return エラーコード
4875  * @details
4876  */
4877 errr counts_write(player_type *creature_ptr, int where, u32b count)
4878 {
4879         char buf[1024];
4880         path_build(buf, sizeof(buf), ANGBAND_DIR_DATA, _("z_info_j.raw", "z_info.raw"));
4881
4882         /* Grab permissions */
4883         safe_setuid_grab();
4884
4885         int fd = fd_open(buf, O_RDWR);
4886
4887         /* Drop permissions */
4888         safe_setuid_drop();
4889
4890         if (fd < 0)
4891         {
4892                 /* File type is "DATA" */
4893                 FILE_TYPE(FILE_TYPE_DATA);
4894
4895                 /* Grab permissions */
4896                 safe_setuid_grab();
4897
4898                 /* Create a new high score file */
4899                 fd = fd_make(buf, 0644);
4900
4901                 /* Drop permissions */
4902                 safe_setuid_drop();
4903         }
4904
4905         /* Grab permissions */
4906         safe_setuid_grab();
4907
4908         errr err = fd_lock(fd, F_WRLCK);
4909
4910         /* Drop permissions */
4911         safe_setuid_drop();
4912
4913         if (err) return 1;
4914
4915         counts_seek(creature_ptr, fd, where, TRUE);
4916         fd_write(fd, (char*)(&count), sizeof(u32b));
4917
4918         /* Grab permissions */
4919         safe_setuid_grab();
4920
4921         err = fd_lock(fd, F_UNLCK);
4922
4923         /* Drop permissions */
4924         safe_setuid_drop();
4925
4926         if (err) return 1;
4927
4928         (void)fd_close(fd);
4929
4930         return 0;
4931 }
4932
4933
4934 /*!
4935  * @brief 墓のアスキーアートテンプレを読み込む
4936  * @param buf テンプレへのバッファ
4937  * @param buf_size バッファの長さ
4938  * @return なし
4939  */
4940 void read_dead_file(char *buf, size_t buf_size)
4941 {
4942         path_build(buf, buf_size, ANGBAND_DIR_FILE, _("dead_j.txt", "dead.txt"));
4943
4944         FILE *fp;
4945         fp = my_fopen(buf, "r");
4946         if (!fp) return;
4947
4948         int i = 0;
4949         while (my_fgets(fp, buf, buf_size) == 0)
4950         {
4951                 put_str(buf, i++, 0);
4952         }
4953
4954         my_fclose(fp);
4955 }