3 * @brief ファイル入出力管理 / Purpose: code dealing with files (and death)
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
17 #include "signal-handlers.h"
18 #include "view/display-player.h" // 暫定。後で消す
19 #include "view/display-util.h"
20 #include "view/status-first-page.h"
21 #include "uid-checker.h"
26 #include "character-dump.h"
29 #include "player-move.h"
30 #include "player-personality.h"
31 #include "player-effects.h"
32 #include "monster-status.h"
33 #include "view-mainwindow.h"
34 #include "objectkind.h"
38 #define PREF_TYPE_NORMAL 0
39 #define PREF_TYPE_AUTOPICK 1
40 #define PREF_TYPE_HISTPREF 2
42 concptr ANGBAND_DIR; //!< Path name: The main "lib" directory This variable is not actually used anywhere in the code
43 concptr ANGBAND_DIR_APEX; //!< High score files (binary) These files may be portable between platforms
44 concptr ANGBAND_DIR_BONE; //!< Bone files for player ghosts (ascii) These files are portable between platforms
45 concptr ANGBAND_DIR_DATA; //!< Binary image files for the "*_info" arrays (binary) These files are not portable between platforms
46 concptr ANGBAND_DIR_EDIT; //!< Textual template files for the "*_info" arrays (ascii) These files are portable between platforms
47 concptr ANGBAND_DIR_SCRIPT; //!< Script files These files are portable between platforms.
48 concptr ANGBAND_DIR_FILE; //!< Various extra files (ascii) These files may be portable between platforms
49 concptr ANGBAND_DIR_HELP; //!< Help files (normal) for the online help (ascii) These files are portable between platforms
50 concptr ANGBAND_DIR_INFO; //!< Help files (spoilers) for the online help (ascii) These files are portable between platforms
51 concptr ANGBAND_DIR_PREF; //!< Default user "preference" files (ascii) These files are rarely portable between platforms
52 concptr ANGBAND_DIR_SAVE; //!< Savefiles for current characters (binary)
53 concptr ANGBAND_DIR_USER; //!< User "preference" files (ascii) These files are rarely portable between platforms
54 concptr ANGBAND_DIR_XTRA; //!< Various extra files (binary) These files are rarely portable between platforms
57 * Buffer to hold the current savefile name
58 * 'savefile' holds full path name. 'savefile_base' holds only base name.
61 char savefile_base[40];
64 * @brief 各種データテキストをトークン単位に分解する / Extract the first few "tokens" from a buffer
65 * @param buf データテキストの参照ポインタ
67 * @param tokens トークンを保管する文字列参照ポインタ配列
72 * This function uses "colon" and "slash" as the delimeter characters.
73 * We never extract more than "num" tokens. The "last" token may include
74 * "delimeter" characters, allowing the buffer to include a "string" token.
75 * We save pointers to the tokens in "tokens", and return the number found.
76 * Hack -- Attempt to handle the 'c' character formalism
77 * Hack -- An empty buffer, or a final delimeter, yields an "empty" token.
78 * Hack -- We will always extract at least one token
81 s16b tokenize(char *buf, s16b num, char **tokens, BIT_FLAGS mode)
90 if ((*t == ':') || (*t == '/')) break;
92 if ((mode & TOKENIZE_CHECKQUOTE) && (*t == '\''))
99 if (*t != '\'') *t = '\'';
116 /* A number with a name */
117 typedef struct named_num named_num;
121 concptr name; /* The name of this thing */
122 int num; /* A number associated with it */
125 /* Index of spell type names */
126 static named_num gf_desc[] =
128 {"GF_ELEC", GF_ELEC },
129 {"GF_POIS", GF_POIS },
130 {"GF_ACID", GF_ACID },
131 {"GF_COLD", GF_COLD },
132 {"GF_FIRE", GF_FIRE },
133 {"GF_PSY_SPEAR", GF_PSY_SPEAR },
134 {"GF_MISSILE", GF_MISSILE },
135 {"GF_ARROW", GF_ARROW },
136 {"GF_PLASMA", GF_PLASMA },
137 {"GF_WATER", GF_WATER },
138 {"GF_LITE", GF_LITE },
139 {"GF_DARK", GF_DARK },
140 {"GF_LITE_WEAK", GF_LITE_WEAK },
141 {"GF_DARK_WEAK", GF_DARK_WEAK },
142 {"GF_SHARDS", GF_SHARDS },
143 {"GF_SOUND", GF_SOUND },
144 {"GF_CONFUSION", GF_CONFUSION },
145 {"GF_FORCE", GF_FORCE },
146 {"GF_INERTIA", GF_INERTIAL },
147 {"GF_MANA", GF_MANA },
148 {"GF_METEOR", GF_METEOR },
150 {"GF_CHAOS", GF_CHAOS },
151 {"GF_NETHER", GF_NETHER },
152 {"GF_DISENCHANT", GF_DISENCHANT },
153 {"GF_NEXUS", GF_NEXUS },
154 {"GF_TIME", GF_TIME },
155 {"GF_GRAVITY", GF_GRAVITY },
156 {"GF_KILL_WALL", GF_KILL_WALL },
157 {"GF_KILL_DOOR", GF_KILL_DOOR },
158 {"GF_KILL_TRAP", GF_KILL_TRAP },
159 {"GF_MAKE_WALL", GF_MAKE_WALL },
160 {"GF_MAKE_DOOR", GF_MAKE_DOOR },
161 {"GF_MAKE_TRAP", GF_MAKE_TRAP },
162 {"GF_MAKE_TREE", GF_MAKE_TREE },
163 {"GF_OLD_CLONE", GF_OLD_CLONE },
164 {"GF_OLD_POLY", GF_OLD_POLY },
165 {"GF_OLD_HEAL", GF_OLD_HEAL },
166 {"GF_OLD_SPEED", GF_OLD_SPEED },
167 {"GF_OLD_SLOW", GF_OLD_SLOW },
168 {"GF_OLD_CONF", GF_OLD_CONF },
169 {"GF_OLD_SLEEP", GF_OLD_SLEEP },
170 {"GF_HYPODYNAMIA", GF_HYPODYNAMIA },
171 {"GF_AWAY_UNDEAD", GF_AWAY_UNDEAD },
172 {"GF_AWAY_EVIL", GF_AWAY_EVIL },
173 {"GF_AWAY_ALL", GF_AWAY_ALL },
174 {"GF_TURN_UNDEAD", GF_TURN_UNDEAD },
175 {"GF_TURN_EVIL", GF_TURN_EVIL },
176 {"GF_TURN_ALL", GF_TURN_ALL },
177 {"GF_DISP_UNDEAD", GF_DISP_UNDEAD },
178 {"GF_DISP_EVIL", GF_DISP_EVIL },
179 {"GF_DISP_ALL", GF_DISP_ALL },
180 {"GF_DISP_DEMON", GF_DISP_DEMON },
181 {"GF_DISP_LIVING", GF_DISP_LIVING },
182 {"GF_ROCKET", GF_ROCKET },
183 {"GF_NUKE", GF_NUKE },
184 {"GF_MAKE_GLYPH", GF_MAKE_GLYPH },
185 {"GF_STASIS", GF_STASIS },
186 {"GF_STONE_WALL", GF_STONE_WALL },
187 {"GF_DEATH_RAY", GF_DEATH_RAY },
188 {"GF_STUN", GF_STUN },
189 {"GF_HOLY_FIRE", GF_HOLY_FIRE },
190 {"GF_HELL_FIRE", GF_HELL_FIRE },
191 {"GF_DISINTEGRATE", GF_DISINTEGRATE },
192 {"GF_CHARM", GF_CHARM },
193 {"GF_CONTROL_UNDEAD", GF_CONTROL_UNDEAD },
194 {"GF_CONTROL_ANIMAL", GF_CONTROL_ANIMAL },
196 {"GF_PSI_DRAIN", GF_PSI_DRAIN },
197 {"GF_TELEKINESIS", GF_TELEKINESIS },
198 {"GF_JAM_DOOR", GF_JAM_DOOR },
199 {"GF_DOMINATION", GF_DOMINATION },
200 {"GF_DISP_GOOD", GF_DISP_GOOD },
201 {"GF_DRAIN_MANA", GF_DRAIN_MANA },
202 {"GF_MIND_BLAST", GF_MIND_BLAST },
203 {"GF_BRAIN_SMASH", GF_BRAIN_SMASH },
204 {"GF_CAUSE_1", GF_CAUSE_1 },
205 {"GF_CAUSE_2", GF_CAUSE_2 },
206 {"GF_CAUSE_3", GF_CAUSE_3 },
207 {"GF_CAUSE_4", GF_CAUSE_4 },
208 {"GF_HAND_DOOM", GF_HAND_DOOM },
209 {"GF_CAPTURE", GF_CAPTURE },
210 {"GF_ANIM_DEAD", GF_ANIM_DEAD },
211 {"GF_CHARM_LIVING", GF_CHARM_LIVING },
212 {"GF_IDENTIFY", GF_IDENTIFY },
213 {"GF_ATTACK", GF_ATTACK },
214 {"GF_ENGETSU", GF_ENGETSU },
215 {"GF_GENOCIDE", GF_GENOCIDE },
216 {"GF_PHOTO", GF_PHOTO },
217 {"GF_CONTROL_DEMON", GF_CONTROL_DEMON },
218 {"GF_LAVA_FLOW", GF_LAVA_FLOW },
219 {"GF_BLOOD_CURSE", GF_BLOOD_CURSE },
220 {"GF_SEEKER", GF_SEEKER },
221 {"GF_SUPER_RAY", GF_SUPER_RAY },
222 {"GF_STAR_HEAL", GF_STAR_HEAL },
223 {"GF_WATER_FLOW", GF_WATER_FLOW },
224 {"GF_CRUSADE", GF_CRUSADE },
225 {"GF_STASIS_EVIL", GF_STASIS_EVIL },
226 {"GF_WOUNDS", GF_WOUNDS },
232 * @brief 設定ファイルの各行から各種テキスト情報を取得する /
233 * Parse a sub-file of the "extra info" (format shown below)
234 * @param creature_ptr プレーヤーへの参照ポインタ
235 * @param buf データテキストの参照ポインタ
239 * Each "action" line has an "action symbol" in the first column,
240 * followed by a colon, followed by some command specific info,
241 * usually in the form of "tokens" separated by colons or slashes.
242 * Blank lines, lines starting with white space, and lines starting
243 * with pound signs ("#") are ignored (as comments).
244 * Note the use of "tokenize()" to allow the use of both colons and
245 * slashes as delimeters, while still allowing final tokens which
246 * may contain any characters including "delimiters".
247 * Note the use of "strtol()" to allow all "integers" to be encoded
248 * in decimal, hexidecimal, or octal form.
249 * Note that "monster zero" is used for the "player" attr/char, "object
250 * zero" will be used for the "stack" attr/char, and "feature zero" is
251 * used for the "nothing" attr/char.
252 * Parse another file recursively, see below for details
254 * Specify the attr/char values for "monsters" by race index
255 * R:\<num\>:\<a\>:\<c\>
256 * Specify the attr/char values for "objects" by kind index
257 * K:\<num\>:\<a\>:\<c\>
258 * Specify the attr/char values for "features" by feature index
259 * F:\<num\>:\<a\>:\<c\>
260 * Specify the attr/char values for unaware "objects" by kind tval
261 * U:\<tv\>:\<a\>:\<c\>
262 * Specify the attr/char values for inventory "objects" by kind tval
263 * E:\<tv\>:\<a\>:\<c\>
264 * Define a macro action, given an encoded macro action
266 * Create a normal macro, given an encoded macro trigger
268 * Create a command macro, given an encoded macro trigger
270 * Create a keyset mapping
271 * S:\<key\>:\<key\>:\<dir\>
272 * Turn an option off, given its name
274 * Turn an option on, given its name
276 * Specify visual information, given an index, and some data
277 * V:\<num\>:\<kv\>:\<rv\>:\<gv\>:\<bv\>
278 * Specify the set of colors to use when drawing a zapped spell
280 * Specify a macro trigger template and macro trigger names.
281 * T:\<template\>:\<modifier chr\>:\<modifier name1\>:\<modifier name2\>:...
282 * T:\<trigger\>:\<keycode\>:\<shift-keycode\>
285 errr process_pref_file_command(player_type *creature_ptr, char *buf)
287 if (buf[1] != ':') return 1;
294 /* Process "H:<history>" */
295 add_history_from_pref_line(buf + 2);
300 /* Process "R:<num>:<a>/<c>" -- attr/char for monster races */
301 if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3) return 1;
304 int i = (huge)strtol(zz[0], NULL, 0);
305 TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
306 SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
307 if (i >= max_r_idx) return 1;
309 if (n1 || (!(n2 & 0x80) && n2)) r_ptr->x_attr = n1; /* Allow TERM_DARK text */
310 if (n2) r_ptr->x_char = n2;
315 /* Process "K:<num>:<a>/<c>" -- attr/char for object kinds */
316 if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3) return 1;
319 int i = (huge)strtol(zz[0], NULL, 0);
320 TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
321 SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
322 if (i >= max_k_idx) return 1;
324 if (n1 || (!(n2 & 0x80) && n2)) k_ptr->x_attr = n1; /* Allow TERM_DARK text */
325 if (n2) k_ptr->x_char = n2;
330 /* Process "F:<num>:<a>/<c>" -- attr/char for terrain features */
331 /* "F:<num>:<a>/<c>" */
332 /* "F:<num>:<a>/<c>:LIT" */
333 /* "F:<num>:<a>/<c>:<la>/<lc>:<da>/<dc>" */
335 int num = tokenize(buf + 2, F_LIT_MAX * 2 + 1, zz, TOKENIZE_CHECKQUOTE);
337 if ((num != 3) && (num != 4) && (num != F_LIT_MAX * 2 + 1)) return 1;
338 else if ((num == 4) && !streq(zz[3], "LIT")) return 1;
340 int i = (huge)strtol(zz[0], NULL, 0);
341 if (i >= max_f_idx) return 1;
344 TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
345 SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
346 if (n1 || (!(n2 & 0x80) && n2)) f_ptr->x_attr[F_LIT_STANDARD] = n1; /* Allow TERM_DARK text */
347 if (n2) f_ptr->x_char[F_LIT_STANDARD] = n2;
353 /* No lighting support */
354 n1 = f_ptr->x_attr[F_LIT_STANDARD];
355 n2 = f_ptr->x_char[F_LIT_STANDARD];
356 for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
358 f_ptr->x_attr[j] = n1;
359 f_ptr->x_char[j] = n2;
366 /* Use default lighting */
367 apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
370 case F_LIT_MAX * 2 + 1:
372 /* Use desired lighting */
373 for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
375 n1 = (TERM_COLOR)strtol(zz[j * 2 + 1], NULL, 0);
376 n2 = (SYMBOL_CODE)strtol(zz[j * 2 + 2], NULL, 0);
377 if (n1 || (!(n2 & 0x80) && n2)) f_ptr->x_attr[j] = n1; /* Allow TERM_DARK text */
378 if (n2) f_ptr->x_char[j] = n2;
389 /* Process "S:<num>:<a>/<c>" -- attr/char for special things */
390 if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3) return 1;
392 int j = (byte)strtol(zz[0], NULL, 0);
393 TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
394 SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
395 misc_to_attr[j] = n1;
396 misc_to_char[j] = n2;
401 /* Process "U:<tv>:<a>/<c>" -- attr/char for unaware items */
402 if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3) return 1;
404 int j = (huge)strtol(zz[0], NULL, 0);
405 TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
406 SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
407 for (int i = 1; i < max_k_idx; i++)
409 object_kind *k_ptr = &k_info[i];
410 if (k_ptr->tval == j)
412 if (n1) k_ptr->d_attr = n1;
413 if (n2) k_ptr->d_char = n2;
421 /* Process "E:<tv>:<a>" -- attribute for inventory objects */
422 if (tokenize(buf + 2, 2, zz, TOKENIZE_CHECKQUOTE) != 2) return 1;
424 int j = (byte)strtol(zz[0], NULL, 0) % 128;
425 TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
426 if (n1) tval_to_attr[j] = n1;
431 /* Process "A:<str>" -- save an "action" for later */
432 text_to_ascii(macro__buf, buf + 2);
437 /* Process "P:<str>" -- normal macro */
439 text_to_ascii(tmp, buf + 2);
440 macro_add(tmp, macro__buf);
445 /* Process "C:<str>" -- create keymap */
446 if (tokenize(buf + 2, 2, zz, TOKENIZE_CHECKQUOTE) != 2) return 1;
448 int mode = strtol(zz[0], NULL, 0);
449 if ((mode < 0) || (mode >= KEYMAP_MODES)) return 1;
452 text_to_ascii(tmp, zz[1]);
453 if (!tmp[0] || tmp[1]) return 1;
455 int i = (byte)(tmp[0]);
456 string_free(keymap_act[mode][i]);
457 keymap_act[mode][i] = string_make(macro__buf);
462 /* Process "V:<num>:<kv>:<rv>:<gv>:<bv>" -- visual info */
463 if (tokenize(buf + 2, 5, zz, TOKENIZE_CHECKQUOTE) != 5) return 1;
465 int i = (byte)strtol(zz[0], NULL, 0);
466 angband_color_table[i][0] = (byte)strtol(zz[1], NULL, 0);
467 angband_color_table[i][1] = (byte)strtol(zz[2], NULL, 0);
468 angband_color_table[i][2] = (byte)strtol(zz[3], NULL, 0);
469 angband_color_table[i][3] = (byte)strtol(zz[4], NULL, 0);
475 /* Process "X:<str>" -- turn option off */
476 /* Process "Y:<str>" -- turn option on */
477 for (int i = 0; option_info[i].o_desc; i++)
479 bool is_option = option_info[i].o_var != NULL;
480 is_option &= option_info[i].o_text != NULL;
481 is_option &= streq(option_info[i].o_text, buf + 2);
482 if (!is_option) continue;
484 int os = option_info[i].o_set;
485 int ob = option_info[i].o_bit;
487 if ((creature_ptr->playing || current_world_ptr->character_xtra) &&
488 (OPT_PAGE_BIRTH == option_info[i].o_page) && !current_world_ptr->wizard)
490 msg_format(_("初期オプションは変更できません! '%s'", "Birth options can not changed! '%s'"), buf);
497 option_flag[os] &= ~(1L << ob);
498 (*option_info[i].o_var) = FALSE;
502 option_flag[os] |= (1L << ob);
503 (*option_info[i].o_var) = TRUE;
507 msg_format(_("オプションの名前が正しくありません: %s", "Ignored invalid option: %s"), buf);
513 /* Process "Z:<type>:<str>" -- set spell color */
514 char *t = my_strchr(buf + 2, ':');
518 for (int i = 0; gf_desc[i].name; i++)
520 if (!streq(gf_desc[i].name, buf + 2)) continue;
522 gf_color[gf_desc[i].num] = (TERM_COLOR)quark_add(t);
530 /* Initialize macro trigger names and a template */
531 /* Process "T:<trigger>:<keycode>:<shift-keycode>" */
532 /* Process "T:<template>:<modifier chr>:<modifier name>:..." */
533 int tok = tokenize(buf + 2, 2 + MAX_MACRO_MOD, zz, 0);
535 /* Process "T:<template>:<modifier chr>:<modifier name>:..." */
538 if (macro_template != NULL)
540 int macro_modifier_length = strlen(macro_modifier_chr);
541 string_free(macro_template);
542 macro_template = NULL;
543 string_free(macro_modifier_chr);
544 for (int i = 0; i < macro_modifier_length; i++)
546 string_free(macro_modifier_name[i]);
549 for (int i = 0; i < max_macrotrigger; i++)
551 string_free(macro_trigger_name[i]);
552 string_free(macro_trigger_keycode[0][i]);
553 string_free(macro_trigger_keycode[1][i]);
556 max_macrotrigger = 0;
559 if (*zz[0] == '\0') return 0;
561 int zz_length = strlen(zz[1]);
562 zz_length = MIN(MAX_MACRO_MOD, zz_length);
563 if (2 + zz_length != tok) return 1;
565 macro_template = string_make(zz[0]);
566 macro_modifier_chr = string_make(zz[1]);
567 for (int i = 0; i < zz_length; i++)
569 macro_modifier_name[i] = string_make(zz[2 + i]);
575 /* Process "T:<trigger>:<keycode>:<shift-keycode>" */
576 if (tok < 2) return 0;
580 if (max_macrotrigger >= MAX_MACRO_TRIG)
582 msg_print(_("マクロトリガーの設定が多すぎます!", "Too many macro triggers!"));
586 int m = max_macrotrigger;
597 macro_trigger_name[m] = string_make(buf_aux);
598 macro_trigger_keycode[0][m] = string_make(zz[1]);
601 macro_trigger_keycode[1][m] = string_make(zz[2]);
605 macro_trigger_keycode[1][m] = string_make(zz[1]);
615 * @brief process_pref_fileのサブルーチンとして条件分岐処理の解釈と結果を返す /
616 * Helper function for "process_pref_file()"
617 * @param creature_ptr プレーヤーへの参照ポインタ
618 * @param sp テキスト文字列の参照ポインタ
619 * @param fp 再帰中のポインタ参照
624 * v: output buffer array
630 concptr process_pref_file_expr(player_type *creature_ptr, char **sp, char *fp)
634 while (iswspace(*s)) s++;
654 t = process_pref_file_expr(creature_ptr, &s, &f);
659 else if (streq(t, "IOR"))
662 while (*s && (f != b2))
664 t = process_pref_file_expr(creature_ptr, &s, &f);
665 if (*t && !streq(t, "0")) v = "1";
668 else if (streq(t, "AND"))
671 while (*s && (f != b2))
673 t = process_pref_file_expr(creature_ptr, &s, &f);
674 if (*t && streq(t, "0")) v = "0";
677 else if (streq(t, "NOT"))
680 while (*s && (f != b2))
682 t = process_pref_file_expr(creature_ptr, &s, &f);
683 if (*t && streq(t, "1")) v = "0";
686 else if (streq(t, "EQU"))
691 t = process_pref_file_expr(creature_ptr, &s, &f);
693 while (*s && (f != b2))
695 p = process_pref_file_expr(creature_ptr, &s, &f);
696 if (streq(t, p)) v = "1";
699 else if (streq(t, "LEQ"))
704 t = process_pref_file_expr(creature_ptr, &s, &f);
706 while (*s && (f != b2))
709 t = process_pref_file_expr(creature_ptr, &s, &f);
710 if (*t && atoi(p) > atoi(t)) v = "0";
713 else if (streq(t, "GEQ"))
718 t = process_pref_file_expr(creature_ptr, &s, &f);
720 while (*s && (f != b2))
723 t = process_pref_file_expr(creature_ptr, &s, &f);
724 if (*t && atoi(p) < atoi(t)) v = "0";
729 while (*s && (f != b2))
731 t = process_pref_file_expr(creature_ptr, &s, &f);
735 if (f != b2) v = "?x?x?";
737 if ((f = *s) != '\0') *s++ = '\0';
744 /* Accept all printables except spaces and brackets */
746 while (iskanji(*s) || (isprint(*s) && !my_strchr(" []", *s)))
748 if (iskanji(*s)) s++;
752 while (isprint(*s) && !my_strchr(" []", *s)) ++s;
755 if ((f = *s) != '\0') *s++ = '\0';
765 if (streq(b + 1, "SYS"))
769 else if (streq(b + 1, "KEYBOARD"))
771 v = ANGBAND_KEYBOARD;
773 else if (streq(b + 1, "GRAF"))
777 else if (streq(b + 1, "MONOCHROME"))
784 else if (streq(b + 1, "RACE"))
792 else if (streq(b + 1, "CLASS"))
800 else if (streq(b + 1, "PLAYER"))
802 static char tmp_player_name[32];
804 for (pn = creature_ptr->name, tpn = tmp_player_name; *pn; pn++, tpn++)
814 *tpn = my_strchr(" []", *pn) ? '_' : *pn;
820 else if (streq(b + 1, "REALM1"))
823 v = E_realm_names[creature_ptr->realm1];
825 v = realm_names[creature_ptr->realm1];
828 else if (streq(b + 1, "REALM2"))
831 v = E_realm_names[creature_ptr->realm2];
833 v = realm_names[creature_ptr->realm2];
836 else if (streq(b + 1, "LEVEL"))
838 sprintf(tmp, "%02d", creature_ptr->lev);
841 else if (streq(b + 1, "AUTOREGISTER"))
843 if (creature_ptr->autopick_autoregister)
848 else if (streq(b + 1, "MONEY"))
850 sprintf(tmp, "%09ld", (long int)creature_ptr->au);
861 * @brief process_pref_fileのサブルーチン /
862 * Open the "user pref file" and parse it.
863 * @param creature_ptr プレーヤーへの参照ポインタ
864 * @param name 読み込むファイル名
865 * @param preftype prefファイルのタイプ
870 * v: output buffer array
876 static errr process_pref_file_aux(player_type *creature_ptr, concptr name, int preftype)
879 fp = my_fopen(name, "r");
887 while (my_fgets(fp, buf, sizeof(buf)) == 0)
890 if (!buf[0]) continue;
893 if (!iskanji(buf[0]))
895 if (iswspace(buf[0])) continue;
897 if (buf[0] == '#') continue;
900 /* Process "?:<expr>" */
901 if ((buf[0] == '?') && (buf[1] == ':'))
906 concptr v = process_pref_file_expr(creature_ptr, &s, &f);
907 bypass = streq(v, "0");
911 if (bypass) continue;
913 /* Process "%:<file>" */
916 static int depth_count = 0;
917 if (depth_count > 20) continue;
922 case PREF_TYPE_AUTOPICK:
923 (void)process_autopick_file(creature_ptr, buf + 2);
925 case PREF_TYPE_HISTPREF:
926 (void)process_histpref_file(creature_ptr, buf + 2);
929 (void)process_pref_file(creature_ptr, buf + 2);
937 err = process_pref_file_command(creature_ptr, buf);
940 if (preftype != PREF_TYPE_AUTOPICK)
942 err = process_autopick_file_command(buf);
948 /* Print error message */
949 /* ToDo: Add better error messages */
950 msg_format(_("ファイル'%s'の%d行でエラー番号%dのエラー。", "Error %d in line %d of file '%s'."),
951 _(name, err), line, _(err, name));
952 msg_format(_("('%s'を解析中)", "Parsing '%s'"), old);
962 * @brief pref設定ファイルを読み込み設定を反映させる /
963 * Process the "user pref file" with the given name
964 * @param creature_ptr プレーヤーへの参照ポインタ
965 * @param name 読み込むファイル名
969 * See the functions above for a list of legal "commands".
970 * We also accept the special "?" and "%" directives, which
971 * allow conditional evaluation and filename inclusion.
974 errr process_pref_file(player_type *creature_ptr, concptr name)
977 path_build(buf, sizeof(buf), ANGBAND_DIR_PREF, name);
979 errr err1 = process_pref_file_aux(creature_ptr, buf, PREF_TYPE_NORMAL);
980 if (err1 > 0) return err1;
982 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name);
983 errr err2 = process_pref_file_aux(creature_ptr, buf, PREF_TYPE_NORMAL);
984 if (err2 < 0 && !err1)
992 * @brief プレイヤーの装備一覧をシンボルで並べる
994 * @param creature_ptr プレーヤーへの参照ポインタ
995 * @param y 表示するコンソールの行
996 * @param x 表示するコンソールの列
1000 void display_player_equippy(player_type *creature_ptr, TERM_LEN y, TERM_LEN x, BIT_FLAGS16 mode)
1002 /* Weapon flags need only two column */
1003 int max_i = (mode & DP_WP) ? INVEN_LARM + 1 : INVEN_TOTAL;
1005 /* Dump equippy chars */
1006 for (int i = INVEN_RARM; i < max_i; i++)
1009 o_ptr = &creature_ptr->inventory_list[i];
1011 TERM_COLOR a = object_attr(o_ptr);
1012 char c = object_char(o_ptr);
1014 if (!equippy_chars || !o_ptr->k_idx)
1020 Term_putch(x + i - INVEN_RARM, y, a, c);
1026 * @brief プレイヤーステータスをファイルダンプ出力する
1027 * Hack -- Dump a character description file
1028 * @param creature_ptr プレーヤーへの参照ポインタ
1029 * @param name 出力ファイル名
1032 * Allow the "full" flag to dump additional info,
1033 * and trigger its usage from various places in the code.
1035 errr file_character(player_type *creature_ptr, concptr name)
1038 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name);
1040 FILE_TYPE(FILE_TYPE_TEXT);
1042 int fd = fd_open(buf, O_RDONLY);
1047 (void)sprintf(out_val, _("現存するファイル %s に上書きしますか? ", "Replace existing file %s? "), buf);
1048 if (get_check_strict(out_val, CHECK_NO_HISTORY)) fd = -1;
1052 if (fd < 0) fff = my_fopen(buf, "w");
1056 prt(_("キャラクタ情報のファイルへの書き出しに失敗しました!", "Character dump failed!"), 0, 0);
1062 * todo view-mainwindow への依存があるが、file_character() 自体関数ポインタなのでよそから呼び出されるので何とかするのは辛い
1063 * ついでに他の関数でもview(略) は参照されているので、簡単に除去することはできない…
1065 make_character_dump(creature_ptr, fff, update_playtime, display_player);
1067 msg_print(_("キャラクタ情報のファイルへの書き出しに成功しました。", "Character dump successful."));
1074 * @brief ファイル内容の一行をコンソールに出力する
1075 * Display single line of on-line help file
1076 * @param str 出力する文字列
1082 * You can insert some special color tag to change text color.
1084 * WHITETEXT [[[[y|SOME TEXT WHICH IS DISPLAYED IN YELLOW| WHITETEXT
1085 * A colored segment is between "[[[[y|" and the last "|".
1086 * You can use any single character in place of the "|".
1089 static void show_file_aux_line(concptr str, int cy, concptr shower)
1099 Term_gotoxy(cx, cy);
1101 static const char tag_str[] = "[[[[";
1102 byte color = TERM_WHITE;
1104 for (int i = 0; str[i];)
1106 int len = strlen(&str[i]);
1107 int showercol = len + 1;
1108 int bracketcol = len + 1;
1113 ptr = my_strstr(&lcstr[i], shower);
1114 if (ptr) showercol = ptr - &lcstr[i];
1117 ptr = in_tag ? my_strchr(&str[i], in_tag) : my_strstr(&str[i], tag_str);
1118 if (ptr) bracketcol = ptr - &str[i];
1119 if (bracketcol < endcol) endcol = bracketcol;
1120 if (showercol < endcol) endcol = showercol;
1122 Term_addstr(endcol, color, &str[i]);
1126 if (endcol == showercol)
1128 int showerlen = strlen(shower);
1129 Term_addstr(showerlen, TERM_YELLOW, &str[i]);
1135 if (endcol != bracketcol) continue;
1145 i += sizeof(tag_str) - 1;
1146 color = color_char_to_attr(str[i]);
1147 if (color == 255 || str[i + 1] == '\0')
1150 Term_addstr(-1, TERM_WHITE, tag_str);
1151 cx += sizeof(tag_str) - 1;
1160 Term_erase(cx, cy, 255);
1165 * @brief ファイル内容をコンソールに出力する
1166 * Recursive file perusal.
1167 * @param creature_ptr プレーヤーへの参照ポインタ
1168 * @param show_version TRUEならばコンソール上にゲームのバージョンを表示する
1169 * @param name ファイル名の文字列
1170 * @param what 内容キャプションの文字列
1171 * @param line 表示の現在行
1176 * Process various special text in the input file, including
1177 * the "menu" structures used by the "help file" system.
1178 * Return FALSE on 'q' to exit from a deep, otherwise TRUE.
1181 bool show_file(player_type *creature_ptr, bool show_version, concptr name, concptr what, int line, BIT_FLAGS mode)
1189 concptr find = NULL;
1191 char finder_str[81];
1192 char shower_str[81];
1194 concptr shower = NULL;
1195 char filename[1024];
1200 bool reverse = (line < 0);
1202 Term_get_size(&wid, &hgt);
1205 strcpy(finder_str, "");
1206 strcpy(shower_str, "");
1207 strcpy(caption, "");
1208 for (i = 0; i < 68; i++)
1213 strcpy(filename, name);
1214 int n = strlen(filename);
1216 for (i = 0; i < n; i++)
1218 if (filename[i] == '#')
1221 tag = filename + i + 1;
1229 strcpy(caption, what);
1231 fff = my_fopen(path, "r");
1236 sprintf(caption, _("ヘルプ・ファイル'%s'", "Help file '%s'"), name);
1237 path_build(path, sizeof(path), ANGBAND_DIR_HELP, name);
1238 fff = my_fopen(path, "r");
1243 sprintf(caption, _("スポイラー・ファイル'%s'", "Info file '%s'"), name);
1244 path_build(path, sizeof(path), ANGBAND_DIR_INFO, name);
1245 fff = my_fopen(path, "r");
1250 path_build(path, sizeof(path), ANGBAND_DIR, name);
1252 for (i = 0; path[i]; i++)
1253 if ('\\' == path[i])
1254 path[i] = PATH_SEP[0];
1256 sprintf(caption, _("スポイラー・ファイル'%s'", "Info file '%s'"), name);
1257 fff = my_fopen(path, "r");
1262 msg_format(_("'%s'をオープンできません。", "Cannot open '%s'."), name);
1271 if (my_fgets(fff, buf, sizeof(buf))) break;
1272 if (!prefix(str, "***** "))
1278 if ((str[6] == '[') && isalpha(str[7]))
1280 int k = str[7] - 'A';
1282 if ((str[8] == ']') && (str[9] == ' '))
1284 strncpy(hook[k], str + 10, 31);
1291 if (str[6] != '<') continue;
1293 size_t len = strlen(str);
1294 if (str[len - 1] == '>')
1296 str[len - 1] = '\0';
1297 if (tag && streq(str + 7, tag)) line = next;
1302 if (line == -1) line = ((size - 1) / rows)*rows;
1307 if (line >= size - rows)
1309 if (line < 0) line = 0;
1314 fff = my_fopen(path, "r");
1315 if (!fff) return FALSE;
1322 if (my_fgets(fff, buf, sizeof(buf))) break;
1323 if (prefix(buf, "***** ")) continue;
1327 for (i = 0; i < rows; )
1330 if (!i) line = next;
1331 if (my_fgets(fff, buf, sizeof(buf))) break;
1332 if (prefix(buf, "***** ")) continue;
1337 strcpy(lc_buf, str);
1338 str_tolower(lc_buf);
1339 if (!my_strstr(lc_buf, find)) continue;
1343 show_file_aux_line(str, i + 2, shower);
1349 Term_erase(0, i + 2, 255);
1363 prt(format(_("[変愚蛮怒 %d.%d.%d, %s, %d/%d]", "[Hengband %d.%d.%d, %s, Line %d/%d]"),
1364 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH,
1365 caption, line, size), 0, 0);
1369 prt(format(_("[%s, %d/%d]", "[%s, Line %d/%d]"),
1370 caption, line, size), 0, 0);
1375 prt(_("[キー:(?)ヘルプ (ESC)終了]", "[Press ESC to exit.]"), hgt - 1, 0);
1381 prt("[キー:(RET/スペース)↑ (-)↓ (?)ヘルプ (ESC)終了]", hgt - 1, 0);
1383 prt("[キー:(RET/スペース)↓ (-)↑ (?)ヘルプ (ESC)終了]", hgt - 1, 0);
1385 prt("[Press Return, Space, -, =, /, |, or ESC to exit.]", hgt - 1, 0);
1389 skey = inkey_special(TRUE);
1393 if (strcmp(name, _("jhelpinfo.txt", "helpinfo.txt")) != 0)
1394 show_file(creature_ptr, TRUE, _("jhelpinfo.txt", "helpinfo.txt"), NULL, 0, mode);
1397 prt(_("強調: ", "Show: "), hgt - 1, 0);
1399 strcpy(back_str, shower_str);
1400 if (askfor(shower_str, 80))
1404 str_tolower(shower_str);
1405 shower = shower_str;
1409 else strcpy(shower_str, back_str);
1414 prt(_("検索: ", "Find: "), hgt - 1, 0);
1415 strcpy(back_str, finder_str);
1416 if (askfor(finder_str, 80))
1423 str_tolower(finder_str);
1424 shower = finder_str;
1428 else strcpy(finder_str, back_str);
1434 prt(_("行: ", "Goto Line: "), hgt - 1, 0);
1437 if (askfor(tmp, 80)) line = atoi(tmp);
1446 line = ((size - 1) / rows) * rows;
1452 prt(_("ファイル・ネーム: ", "Goto File: "), hgt - 1, 0);
1453 strcpy(tmp, _("jhelp.hlp", "help.hlp"));
1455 if (askfor(tmp, 80))
1457 if (!show_file(creature_ptr, TRUE, tmp, NULL, 0, mode)) skey = 'q';
1464 line = line + (reverse ? rows : -rows);
1465 if (line < 0) line = 0;
1470 if (line < 0) line = 0;
1475 line = line + (reverse ? -1 : 1);
1476 if (line < 0) line = 0;
1482 if (line < 0) line = 0;
1491 line = line + (reverse ? -rows : rows);
1492 if (line < 0) line = 0;
1503 if (!(skey & SKEY_MASK) && isalpha(skey))
1506 if ((key > -1) && hook[key][0])
1508 /* Recurse on that file */
1509 if (!show_file(creature_ptr, TRUE, hook[key], NULL, 0, mode))
1522 if (!get_string(_("ファイル名: ", "File name: "), xtmp, 80)) continue;
1524 path_build(buff, sizeof(buff), ANGBAND_DIR_USER, xtmp);
1526 /* Hack -- Re-Open the file */
1527 fff = my_fopen(path, "r");
1529 ffp = my_fopen(buff, "w");
1533 msg_print(_("ファイルを開けません。", "Failed to open file."));
1538 sprintf(xtmp, "%s: %s", creature_ptr->name, what ? what : caption);
1539 my_fputs(ffp, xtmp, 80);
1540 my_fputs(ffp, "\n", 80);
1542 while (!my_fgets(fff, buff, sizeof(buff)))
1543 my_fputs(ffp, buff, 80);
1546 fff = my_fopen(path, "r");
1549 if ((skey == ESCAPE) || (skey == '<')) break;
1551 if (skey == KTRL('q')) skey = 'q';
1553 if (skey == 'q') break;
1557 return (skey != 'q');
1562 * @brief ヘルプを表示するコマンドのメインルーチン
1563 * Peruse the On-Line-Help
1564 * @param creature_ptr プレーヤーへの参照ポインタ
1568 void do_cmd_help(player_type *creature_ptr)
1571 (void)show_file(creature_ptr, TRUE, _("jhelp.hlp", "help.hlp"), NULL, 0, 0);
1577 * @brief プレイヤーの名前をチェックして修正する
1578 * Process the player name.
1579 * @param player_ptr プレーヤーへの参照ポインタ
1580 * @param sf セーブファイル名に合わせた修正を行うならばTRUE
1583 * Extract a clean "base name".
1584 * Build the savefile name if needed.
1586 void process_player_name(player_type *creature_ptr, bool sf)
1588 char old_player_base[32] = "";
1589 if (current_world_ptr->character_generated)
1590 strcpy(old_player_base, creature_ptr->base_name);
1592 for (int i = 0; creature_ptr->name[i]; i++)
1595 if (iskanji(creature_ptr->name[i])) { i++; continue; }
1596 if (iscntrl((unsigned char)creature_ptr->name[i]))
1598 if (iscntrl(creature_ptr->name[i]))
1601 quit_fmt(_("'%s' という名前は不正なコントロールコードを含んでいます。", "The name '%s' contains control chars!"), creature_ptr->name);
1606 for (int i = 0; creature_ptr->name[i]; i++)
1609 unsigned char c = creature_ptr->name[i];
1611 char c = creature_ptr->name[i];
1616 if (k + 2 >= sizeof(creature_ptr->base_name) || !creature_ptr->name[i + 1])
1618 creature_ptr->base_name[k++] = c;
1620 creature_ptr->base_name[k++] = creature_ptr->name[i];
1623 else if (iskana(c)) creature_ptr->base_name[k++] = c;
1627 if (!strncmp(PATH_SEP, creature_ptr->name + i, strlen(PATH_SEP)))
1629 creature_ptr->base_name[k++] = '_';
1630 i += strlen(PATH_SEP);
1632 #if defined(WINDOWS)
1633 else if (my_strchr("\"*,/:;<>?\\|", c))
1634 creature_ptr->base_name[k++] = '_';
1636 else if (isprint(c))
1637 creature_ptr->base_name[k++] = c;
1640 creature_ptr->base_name[k] = '\0';
1641 if (!creature_ptr->base_name[0])
1642 strcpy(creature_ptr->base_name, "PLAYER");
1644 #ifdef SAVEFILE_MUTABLE
1647 if (!savefile_base[0] && savefile[0])
1649 concptr s = savefile;
1653 t = my_strstr(s, PATH_SEP);
1659 strcpy(savefile_base, s);
1662 if (!savefile_base[0] || !savefile[0])
1668 strcpy(savefile_base, creature_ptr->base_name);
1670 #ifdef SAVEFILE_USE_UID
1671 /* Rename the savefile, using the creature_ptr->player_uid and creature_ptr->base_name */
1672 (void)sprintf(temp, "%d.%s", creature_ptr->player_uid, creature_ptr->base_name);
1674 /* Rename the savefile, using the creature_ptr->base_name */
1675 (void)sprintf(temp, "%s", creature_ptr->base_name);
1677 path_build(savefile, sizeof(savefile), ANGBAND_DIR_SAVE, temp);
1680 if (current_world_ptr->character_generated && !streq(old_player_base, creature_ptr->base_name))
1682 autopick_load_pref(creature_ptr, FALSE);
1688 * @brief プレイヤーの名前を変更するコマンドのメインルーチン
1689 * Gets a name for the character, reacting to name changes.
1690 * @param creature_ptr プレーヤーへの参照ポインタ
1694 * Assumes that "display_player()" has just been called
1695 * Perhaps we should NOT ask for a name (at "birth()") on
1696 * Unix machines? XXX XXX
1697 * What a horrible name for a global function.
1700 void get_name(player_type *creature_ptr)
1703 strcpy(tmp, creature_ptr->name);
1705 if (get_string(_("キャラクターの名前を入力して下さい: ", "Enter a name for your character: "), tmp, 15))
1707 strcpy(creature_ptr->name, tmp);
1710 if (strlen(creature_ptr->name) == 0)
1712 strcpy(creature_ptr->name, "PLAYER");
1715 strcpy(tmp, ap_ptr->title);
1717 if (ap_ptr->no == 1)
1722 strcat(tmp, creature_ptr->name);
1724 Term_erase(34, 1, 255);
1725 c_put_str(TERM_L_BLUE, tmp, 1, 34);
1731 * @brief セーブするコマンドのメインルーチン
1733 * @param creature_ptr プレーヤーへの参照ポインタ
1734 * @param is_autosave オートセーブ中の処理ならばTRUE
1738 void do_cmd_save_game(player_type *creature_ptr, int is_autosave)
1742 msg_print(_("自動セーブ中", "Autosaving the game..."));
1746 disturb(creature_ptr, TRUE, TRUE);
1750 handle_stuff(creature_ptr);
1751 prt(_("ゲームをセーブしています...", "Saving game..."), 0, 0);
1753 (void)strcpy(creature_ptr->died_from, _("(セーブ)", "(saved)"));
1754 signals_ignore_tstp();
1755 if (save_player(creature_ptr))
1757 prt(_("ゲームをセーブしています... 終了", "Saving game... done."), 0, 0);
1761 prt(_("ゲームをセーブしています... 失敗!", "Saving game... failed!"), 0, 0);
1764 signals_handle_tstp();
1766 (void)strcpy(creature_ptr->died_from, _("(元気に生きている)", "(alive and well)"));
1767 current_world_ptr->is_loading_now = FALSE;
1768 update_creature(creature_ptr);
1769 mproc_init(creature_ptr->current_floor_ptr);
1770 current_world_ptr->is_loading_now = TRUE;
1775 * @brief セーブ後にゲーム中断フラグを立てる/
1776 * Save the game and exit
1780 void do_cmd_save_and_exit(player_type *creature_ptr)
1782 creature_ptr->playing = FALSE;
1783 creature_ptr->leaving = TRUE;
1784 exe_write_diary(creature_ptr, DIARY_GAMESTART, 0, _("----ゲーム中断----", "---- Save and Exit Game ----"));
1789 * @brief 異常発生時のゲーム緊急終了処理 /
1790 * Handle abrupt death of the visual system
1791 * @param creature_ptr プレーヤーへの参照ポインタ
1794 * This routine is called only in very rare situations, and only
1795 * by certain visual systems, when they experience fatal errors.
1797 void exit_game_panic(player_type *creature_ptr)
1799 if (!current_world_ptr->character_generated || current_world_ptr->character_saved)
1800 quit(_("緊急事態", "panic"));
1804 disturb(creature_ptr, TRUE, TRUE);
1805 if (creature_ptr->chp < 0) creature_ptr->is_dead = FALSE;
1807 creature_ptr->panic_save = 1;
1808 signals_ignore_tstp();
1809 (void)strcpy(creature_ptr->died_from, _("(緊急セーブ)", "(panic save)"));
1810 if (!save_player(creature_ptr)) quit(_("緊急セーブ失敗!", "panic save failed!"));
1811 quit(_("緊急セーブ成功!", "panic save succeeded!"));
1816 * @brief ファイルからランダムに行を一つ取得する /
1817 * Get a random line from a file
1818 * @param file_name ファイル名
1819 * @param entry 特定条件時のN:タグヘッダID
1820 * @param output 出力先の文字列参照ポインタ
1824 * Based on the monster speech patch by Matt Graham,
1827 errr get_rnd_line(concptr file_name, int entry, char *output)
1830 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, file_name);
1832 fp = my_fopen(buf, "r");
1839 if (my_fgets(fp, buf, sizeof(buf)) != 0)
1846 if ((buf[0] != 'N') || (buf[1] != ':')) continue;
1852 else if (buf[2] == 'M')
1854 if (r_info[entry].flags1 & RF1_MALE) break;
1856 else if (buf[2] == 'F')
1858 if (r_info[entry].flags1 & RF1_FEMALE) break;
1860 else if (sscanf(&(buf[2]), "%d", &test) != EOF)
1862 if (test == entry) break;
1865 msg_format("Error in line %d of %s!", line_num, file_name);
1871 for (counter = 0; ; counter++)
1875 test = my_fgets(fp, buf, sizeof(buf));
1878 /* Ignore lines starting with 'N:' */
1879 if ((buf[0] == 'N') && (buf[1] == ':')) continue;
1881 if (buf[0] != '#') break;
1888 if (one_in_(counter + 1)) strcpy(output, buf);
1892 return counter ? 0 : -1;
1898 * @brief ファイルからランダムに行を一つ取得する(日本語文字列のみ) /
1899 * @param file_name ファイル名
1900 * @param entry 特定条件時のN:タグヘッダID
1901 * @param output 出力先の文字列参照ポインタ
1906 errr get_rnd_line_jonly(concptr file_name, int entry, char *output, int count)
1909 for (int i = 0; i < count; i++)
1911 result = get_rnd_line(file_name, entry, output);
1914 for (int j = 0; output[j]; j++) kanji |= iskanji(output[j]);
1924 * @brief 自動拾いファイルを読み込む /
1925 * @param creature_ptr プレーヤーへの参照ポインタ
1929 errr process_autopick_file(player_type *creature_ptr, concptr name)
1932 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name);
1933 errr err = process_pref_file_aux(creature_ptr, buf, PREF_TYPE_AUTOPICK);
1939 * @brief プレイヤーの生い立ちファイルを読み込む /
1940 * Process file for player's history editor.
1941 * @param creature_ptr プレーヤーへの参照ポインタ
1946 errr process_histpref_file(player_type *creature_ptr, concptr name)
1948 bool old_character_xtra = current_world_ptr->character_xtra;
1950 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name);
1952 /* Hack -- prevent modification birth options in this file */
1953 current_world_ptr->character_xtra = TRUE;
1954 errr err = process_pref_file_aux(creature_ptr, buf, PREF_TYPE_HISTPREF);
1955 current_world_ptr->character_xtra = old_character_xtra;
1961 * @brief ファイル位置をシーク /
1962 * @param creature_ptr プレーヤーへの参照ポインタ
1963 * @param fd ファイルディスクリプタ
1964 * @param where ファイルバイト位置
1965 * @param flag FALSEならば現ファイルを超えた位置へシーク時エラー、TRUEなら足りない間を0で埋め尽くす
1969 static errr counts_seek(player_type *creature_ptr, int fd, u32b where, bool flag)
1971 char temp1[128], temp2[128];
1972 #ifdef SAVEFILE_USE_UID
1973 (void)sprintf(temp1, "%d.%s.%d%d%d", creature_ptr->player_uid, savefile_base, creature_ptr->pclass, creature_ptr->pseikaku, creature_ptr->age);
1975 (void)sprintf(temp1, "%s.%d%d%d", savefile_base, creature_ptr->pclass, creature_ptr->pseikaku, creature_ptr->age);
1977 for (int i = 0; temp1[i]; i++)
1978 temp1[i] ^= (i + 1) * 63;
1981 u32b zero_header[3] = { 0L, 0L, 0L };
1984 if (fd_seek(fd, seekpoint + 3 * sizeof(u32b)))
1986 if (fd_read(fd, (char*)(temp2), sizeof(temp2)))
1991 fd_seek(fd, seekpoint);
1992 fd_write(fd, (char*)zero_header, 3 * sizeof(u32b));
1993 fd_write(fd, (char*)(temp1), sizeof(temp1));
1997 if (strcmp(temp1, temp2) == 0)
2000 seekpoint += 128 + 3 * sizeof(u32b);
2003 return fd_seek(fd, seekpoint + where * sizeof(u32b));
2008 * @brief ファイル位置を読み込む
2009 * @param creature_ptr プレーヤーへの参照ポインタ
2010 * @param where ファイルバイト位置
2014 u32b counts_read(player_type *creature_ptr, int where)
2017 path_build(buf, sizeof(buf), ANGBAND_DIR_DATA, _("z_info_j.raw", "z_info.raw"));
2018 int fd = fd_open(buf, O_RDONLY);
2021 if (counts_seek(creature_ptr, fd, where, FALSE) ||
2022 fd_read(fd, (char*)(&count), sizeof(u32b)))
2032 * @brief ファイル位置に書き込む /
2033 * @param creature_ptr プレーヤーへの参照ポインタ
2034 * @param where ファイルバイト位置
2035 * @param count 書き込む値
2039 errr counts_write(player_type *creature_ptr, int where, u32b count)
2042 path_build(buf, sizeof(buf), ANGBAND_DIR_DATA, _("z_info_j.raw", "z_info.raw"));
2045 int fd = fd_open(buf, O_RDWR);
2049 FILE_TYPE(FILE_TYPE_DATA);
2051 fd = fd_make(buf, 0644);
2056 errr err = fd_lock(fd, F_WRLCK);
2060 counts_seek(creature_ptr, fd, where, TRUE);
2061 fd_write(fd, (char*)(&count), sizeof(u32b));
2063 err = fd_lock(fd, F_UNLCK);
2074 * @brief 墓のアスキーアートテンプレを読み込む
2075 * @param buf テンプレへのバッファ
2076 * @param buf_size バッファの長さ
2079 void read_dead_file(char *buf, size_t buf_size)
2081 path_build(buf, buf_size, ANGBAND_DIR_FILE, _("dead_j.txt", "dead.txt"));
2084 fp = my_fopen(buf, "r");
2088 while (my_fgets(fp, buf, buf_size) == 0)
2090 put_str(buf, i++, 0);