OSDN Git Service

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