2 * @brief ファイル入出力管理 / Purpose: code dealing with files (and death)
6 * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
7 * This software may be copied and distributed for educational, research,
8 * and not for profit purposes provided that this copyright and statement
9 * are included in all such copies. Other copyrights may also apply.
10 * 2014 Deskull rearranged comment for Doxygen.\n
14 #include "system/angband.h"
15 #include "io/uid-checker.h"
16 #include "io/files-util.h"
17 #include "system/system-variables.h" // 暫定。後で消す.
18 #include "io/character-dump.h"
20 concptr ANGBAND_DIR; //!< Path name: The main "lib" directory This variable is not actually used anywhere in the code
21 concptr ANGBAND_DIR_APEX; //!< High score files (binary) These files may be portable between platforms
22 concptr ANGBAND_DIR_BONE; //!< Bone files for player ghosts (ascii) These files are portable between platforms
23 concptr ANGBAND_DIR_DATA; //!< Binary image files for the "*_info" arrays (binary) These files are not portable between platforms
24 concptr ANGBAND_DIR_EDIT; //!< Textual template files for the "*_info" arrays (ascii) These files are portable between platforms
25 concptr ANGBAND_DIR_SCRIPT; //!< Script files These files are portable between platforms.
26 concptr ANGBAND_DIR_FILE; //!< Various extra files (ascii) These files may be portable between platforms
27 concptr ANGBAND_DIR_HELP; //!< Help files (normal) for the online help (ascii) These files are portable between platforms
28 concptr ANGBAND_DIR_INFO; //!< Help files (spoilers) for the online help (ascii) These files are portable between platforms
29 concptr ANGBAND_DIR_PREF; //!< Default user "preference" files (ascii) These files are rarely portable between platforms
30 concptr ANGBAND_DIR_SAVE; //!< Savefiles for current characters (binary)
31 concptr ANGBAND_DIR_USER; //!< User "preference" files (ascii) These files are rarely portable between platforms
32 concptr ANGBAND_DIR_XTRA; //!< Various extra files (binary) These files are rarely portable between platforms
35 * Buffer to hold the current savefile name
36 * 'savefile' holds full path name. 'savefile_base' holds only base name.
39 char savefile_base[40];
42 * todo サブルーチンとは言い難い。autopick.c から直接呼ばれている
43 * @brief process_pref_fileのサブルーチンとして条件分岐処理の解釈と結果を返す
44 * Helper function for "process_pref_file()"
45 * @param creature_ptr プレーヤーへの参照ポインタ
46 * @param sp テキスト文字列の参照ポインタ
47 * @param fp 再帰中のポインタ参照
52 * v: output buffer array
58 concptr process_pref_file_expr(player_type *creature_ptr, char **sp, char *fp)
62 while (iswspace(*s)) s++;
82 t = process_pref_file_expr(creature_ptr, &s, &f);
87 else if (streq(t, "IOR"))
90 while (*s && (f != b2))
92 t = process_pref_file_expr(creature_ptr, &s, &f);
93 if (*t && !streq(t, "0")) v = "1";
96 else if (streq(t, "AND"))
99 while (*s && (f != b2))
101 t = process_pref_file_expr(creature_ptr, &s, &f);
102 if (*t && streq(t, "0")) v = "0";
105 else if (streq(t, "NOT"))
108 while (*s && (f != b2))
110 t = process_pref_file_expr(creature_ptr, &s, &f);
111 if (*t && streq(t, "1")) v = "0";
114 else if (streq(t, "EQU"))
119 t = process_pref_file_expr(creature_ptr, &s, &f);
121 while (*s && (f != b2))
123 p = process_pref_file_expr(creature_ptr, &s, &f);
124 if (streq(t, p)) v = "1";
127 else if (streq(t, "LEQ"))
132 t = process_pref_file_expr(creature_ptr, &s, &f);
134 while (*s && (f != b2))
137 t = process_pref_file_expr(creature_ptr, &s, &f);
138 if (*t && atoi(p) > atoi(t)) v = "0";
141 else if (streq(t, "GEQ"))
146 t = process_pref_file_expr(creature_ptr, &s, &f);
148 while (*s && (f != b2))
151 t = process_pref_file_expr(creature_ptr, &s, &f);
152 if (*t && atoi(p) < atoi(t)) v = "0";
157 while (*s && (f != b2))
159 t = process_pref_file_expr(creature_ptr, &s, &f);
163 if (f != b2) v = "?x?x?";
165 if ((f = *s) != '\0') *s++ = '\0';
172 /* Accept all printables except spaces and brackets */
174 while (iskanji(*s) || (isprint(*s) && !my_strchr(" []", *s)))
176 if (iskanji(*s)) s++;
180 while (isprint(*s) && !my_strchr(" []", *s)) ++s;
183 if ((f = *s) != '\0') *s++ = '\0';
193 if (streq(b + 1, "SYS"))
197 else if (streq(b + 1, "KEYBOARD"))
199 v = ANGBAND_KEYBOARD;
201 else if (streq(b + 1, "GRAF"))
205 else if (streq(b + 1, "MONOCHROME"))
212 else if (streq(b + 1, "RACE"))
220 else if (streq(b + 1, "CLASS"))
228 else if (streq(b + 1, "PLAYER"))
230 static char tmp_player_name[32];
232 for (pn = creature_ptr->name, tpn = tmp_player_name; *pn; pn++, tpn++)
242 *tpn = my_strchr(" []", *pn) ? '_' : *pn;
248 else if (streq(b + 1, "REALM1"))
251 v = E_realm_names[creature_ptr->realm1];
253 v = realm_names[creature_ptr->realm1];
256 else if (streq(b + 1, "REALM2"))
259 v = E_realm_names[creature_ptr->realm2];
261 v = realm_names[creature_ptr->realm2];
264 else if (streq(b + 1, "LEVEL"))
266 sprintf(tmp, "%02d", creature_ptr->lev);
269 else if (streq(b + 1, "AUTOREGISTER"))
271 if (creature_ptr->autopick_autoregister)
276 else if (streq(b + 1, "MONEY"))
278 sprintf(tmp, "%09ld", (long int)creature_ptr->au);
289 * @brief プレイヤーステータスをファイルダンプ出力する
290 * Hack -- Dump a character description file
291 * @param creature_ptr プレーヤーへの参照ポインタ
292 * @param name 出力ファイル名
295 * Allow the "full" flag to dump additional info,
296 * and trigger its usage from various places in the code.
298 errr file_character(player_type *creature_ptr, concptr name, update_playtime_pf update_playtime, display_player_pf display_player, map_name_pf map_name)
301 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name);
303 FILE_TYPE(FILE_TYPE_TEXT);
305 int fd = fd_open(buf, O_RDONLY);
310 (void)sprintf(out_val, _("現存するファイル %s に上書きしますか? ", "Replace existing file %s? "), buf);
311 if (get_check_strict(out_val, CHECK_NO_HISTORY)) fd = -1;
315 if (fd < 0) fff = my_fopen(buf, "w");
319 prt(_("キャラクタ情報のファイルへの書き出しに失敗しました!", "Character dump failed!"), 0, 0);
324 make_character_dump(creature_ptr, fff, update_playtime, display_player, map_name);
326 msg_print(_("キャラクタ情報のファイルへの書き出しに成功しました。", "Character dump successful."));
333 * @brief ファイルからランダムに行を一つ取得する /
334 * Get a random line from a file
335 * @param file_name ファイル名
336 * @param entry 特定条件時のN:タグヘッダID
337 * @param output 出力先の文字列参照ポインタ
341 * Based on the monster speech patch by Matt Graham,
344 errr get_rnd_line(concptr file_name, int entry, char *output)
347 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, file_name);
349 fp = my_fopen(buf, "r");
356 if (my_fgets(fp, buf, sizeof(buf)) != 0)
363 if ((buf[0] != 'N') || (buf[1] != ':')) continue;
369 else if (buf[2] == 'M')
371 if (r_info[entry].flags1 & RF1_MALE) break;
373 else if (buf[2] == 'F')
375 if (r_info[entry].flags1 & RF1_FEMALE) break;
377 else if (sscanf(&(buf[2]), "%d", &test) != EOF)
379 if (test == entry) break;
383 msg_format("Error in line %d of %s!", line_num, file_name);
390 for (counter = 0; ; counter++)
394 test = my_fgets(fp, buf, sizeof(buf));
397 /* Ignore lines starting with 'N:' */
398 if ((buf[0] == 'N') && (buf[1] == ':')) continue;
400 if (buf[0] != '#') break;
407 if (one_in_(counter + 1)) strcpy(output, buf);
411 return counter ? 0 : -1;
417 * @brief ファイルからランダムに行を一つ取得する(日本語文字列のみ) /
418 * @param file_name ファイル名
419 * @param entry 特定条件時のN:タグヘッダID
420 * @param output 出力先の文字列参照ポインタ
425 errr get_rnd_line_jonly(concptr file_name, int entry, char *output, int count)
428 for (int i = 0; i < count; i++)
430 result = get_rnd_line(file_name, entry, output);
433 for (int j = 0; output[j]; j++) kanji |= iskanji(output[j]);
443 * @brief ファイル位置をシーク /
444 * @param creature_ptr プレーヤーへの参照ポインタ
445 * @param fd ファイルディスクリプタ
446 * @param where ファイルバイト位置
447 * @param flag FALSEならば現ファイルを超えた位置へシーク時エラー、TRUEなら足りない間を0で埋め尽くす
451 static errr counts_seek(player_type *creature_ptr, int fd, u32b where, bool flag)
453 char temp1[128], temp2[128];
454 #ifdef SAVEFILE_USE_UID
455 (void)sprintf(temp1, "%d.%s.%d%d%d", creature_ptr->player_uid, savefile_base, creature_ptr->pclass, creature_ptr->pseikaku, creature_ptr->age);
457 (void)sprintf(temp1, "%s.%d%d%d", savefile_base, creature_ptr->pclass, creature_ptr->pseikaku, creature_ptr->age);
459 for (int i = 0; temp1[i]; i++)
460 temp1[i] ^= (i + 1) * 63;
463 u32b zero_header[3] = { 0L, 0L, 0L };
466 if (fd_seek(fd, seekpoint + 3 * sizeof(u32b)))
468 if (fd_read(fd, (char*)(temp2), sizeof(temp2)))
473 fd_seek(fd, seekpoint);
474 fd_write(fd, (char*)zero_header, 3 * sizeof(u32b));
475 fd_write(fd, (char*)(temp1), sizeof(temp1));
479 if (strcmp(temp1, temp2) == 0)
482 seekpoint += 128 + 3 * sizeof(u32b);
485 return fd_seek(fd, seekpoint + where * sizeof(u32b));
491 * @param creature_ptr プレーヤーへの参照ポインタ
492 * @param where ファイルバイト位置
496 u32b counts_read(player_type *creature_ptr, int where)
499 path_build(buf, sizeof(buf), ANGBAND_DIR_DATA, _("z_info_j.raw", "z_info.raw"));
500 int fd = fd_open(buf, O_RDONLY);
503 if (counts_seek(creature_ptr, fd, where, FALSE) ||
504 fd_read(fd, (char*)(&count), sizeof(u32b)))
514 * @brief ファイル位置に書き込む /
515 * @param creature_ptr プレーヤーへの参照ポインタ
516 * @param where ファイルバイト位置
521 errr counts_write(player_type *creature_ptr, int where, u32b count)
524 path_build(buf, sizeof(buf), ANGBAND_DIR_DATA, _("z_info_j.raw", "z_info.raw"));
527 int fd = fd_open(buf, O_RDWR);
531 FILE_TYPE(FILE_TYPE_DATA);
533 fd = fd_make(buf, 0644);
538 errr err = fd_lock(fd, F_WRLCK);
542 counts_seek(creature_ptr, fd, where, TRUE);
543 fd_write(fd, (char*)(&count), sizeof(u32b));
545 err = fd_lock(fd, F_UNLCK);
556 * @brief 墓のアスキーアートテンプレを読み込む
557 * @param buf テンプレへのバッファ
558 * @param buf_size バッファの長さ
561 void read_dead_file(char *buf, size_t buf_size)
563 path_build(buf, buf_size, ANGBAND_DIR_FILE, _("dead_j.txt", "dead.txt"));
566 fp = my_fopen(buf, "r");
570 while (my_fgets(fp, buf, buf_size) == 0)
572 put_str(buf, i++, 0);