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 "uid-checker.h"
20 #include "core.h" // リファクタリングして後で消す
23 #include "character-dump.h"
26 #include "player-move.h"
27 #include "player-personality.h"
28 #include "player-effects.h"
29 #include "monster-status.h"
30 #include "view-mainwindow.h"
31 #include "objectkind.h"
34 #include "io/tokenizer.h"
35 #include "io/process-pref-file.h" // 暫定。依存性の向きがこれで良いか要確認.
37 #define PREF_TYPE_NORMAL 0
38 #define PREF_TYPE_AUTOPICK 1
39 #define PREF_TYPE_HISTPREF 2
41 concptr ANGBAND_DIR; //!< Path name: The main "lib" directory This variable is not actually used anywhere in the code
42 concptr ANGBAND_DIR_APEX; //!< High score files (binary) These files may be portable between platforms
43 concptr ANGBAND_DIR_BONE; //!< Bone files for player ghosts (ascii) These files are portable between platforms
44 concptr ANGBAND_DIR_DATA; //!< Binary image files for the "*_info" arrays (binary) These files are not portable between platforms
45 concptr ANGBAND_DIR_EDIT; //!< Textual template files for the "*_info" arrays (ascii) These files are portable between platforms
46 concptr ANGBAND_DIR_SCRIPT; //!< Script files These files are portable between platforms.
47 concptr ANGBAND_DIR_FILE; //!< Various extra files (ascii) These files may be portable between platforms
48 concptr ANGBAND_DIR_HELP; //!< Help files (normal) for the online help (ascii) These files are portable between platforms
49 concptr ANGBAND_DIR_INFO; //!< Help files (spoilers) for the online help (ascii) These files are portable between platforms
50 concptr ANGBAND_DIR_PREF; //!< Default user "preference" files (ascii) These files are rarely portable between platforms
51 concptr ANGBAND_DIR_SAVE; //!< Savefiles for current characters (binary)
52 concptr ANGBAND_DIR_USER; //!< User "preference" files (ascii) These files are rarely portable between platforms
53 concptr ANGBAND_DIR_XTRA; //!< Various extra files (binary) These files are rarely portable between platforms
56 * Buffer to hold the current savefile name
57 * 'savefile' holds full path name. 'savefile_base' holds only base name.
60 char savefile_base[40];
63 * todo サブルーチンとは言い難い。autopick.c から直接呼ばれている
64 * @brief process_pref_fileのサブルーチンとして条件分岐処理の解釈と結果を返す
65 * Helper function for "process_pref_file()"
66 * @param creature_ptr プレーヤーへの参照ポインタ
67 * @param sp テキスト文字列の参照ポインタ
68 * @param fp 再帰中のポインタ参照
73 * v: output buffer array
79 concptr process_pref_file_expr(player_type *creature_ptr, char **sp, char *fp)
83 while (iswspace(*s)) s++;
103 t = process_pref_file_expr(creature_ptr, &s, &f);
108 else if (streq(t, "IOR"))
111 while (*s && (f != b2))
113 t = process_pref_file_expr(creature_ptr, &s, &f);
114 if (*t && !streq(t, "0")) v = "1";
117 else if (streq(t, "AND"))
120 while (*s && (f != b2))
122 t = process_pref_file_expr(creature_ptr, &s, &f);
123 if (*t && streq(t, "0")) v = "0";
126 else if (streq(t, "NOT"))
129 while (*s && (f != b2))
131 t = process_pref_file_expr(creature_ptr, &s, &f);
132 if (*t && streq(t, "1")) v = "0";
135 else if (streq(t, "EQU"))
140 t = process_pref_file_expr(creature_ptr, &s, &f);
142 while (*s && (f != b2))
144 p = process_pref_file_expr(creature_ptr, &s, &f);
145 if (streq(t, p)) v = "1";
148 else if (streq(t, "LEQ"))
153 t = process_pref_file_expr(creature_ptr, &s, &f);
155 while (*s && (f != b2))
158 t = process_pref_file_expr(creature_ptr, &s, &f);
159 if (*t && atoi(p) > atoi(t)) v = "0";
162 else if (streq(t, "GEQ"))
167 t = process_pref_file_expr(creature_ptr, &s, &f);
169 while (*s && (f != b2))
172 t = process_pref_file_expr(creature_ptr, &s, &f);
173 if (*t && atoi(p) < atoi(t)) v = "0";
178 while (*s && (f != b2))
180 t = process_pref_file_expr(creature_ptr, &s, &f);
184 if (f != b2) v = "?x?x?";
186 if ((f = *s) != '\0') *s++ = '\0';
193 /* Accept all printables except spaces and brackets */
195 while (iskanji(*s) || (isprint(*s) && !my_strchr(" []", *s)))
197 if (iskanji(*s)) s++;
201 while (isprint(*s) && !my_strchr(" []", *s)) ++s;
204 if ((f = *s) != '\0') *s++ = '\0';
214 if (streq(b + 1, "SYS"))
218 else if (streq(b + 1, "KEYBOARD"))
220 v = ANGBAND_KEYBOARD;
222 else if (streq(b + 1, "GRAF"))
226 else if (streq(b + 1, "MONOCHROME"))
233 else if (streq(b + 1, "RACE"))
241 else if (streq(b + 1, "CLASS"))
249 else if (streq(b + 1, "PLAYER"))
251 static char tmp_player_name[32];
253 for (pn = creature_ptr->name, tpn = tmp_player_name; *pn; pn++, tpn++)
263 *tpn = my_strchr(" []", *pn) ? '_' : *pn;
269 else if (streq(b + 1, "REALM1"))
272 v = E_realm_names[creature_ptr->realm1];
274 v = realm_names[creature_ptr->realm1];
277 else if (streq(b + 1, "REALM2"))
280 v = E_realm_names[creature_ptr->realm2];
282 v = realm_names[creature_ptr->realm2];
285 else if (streq(b + 1, "LEVEL"))
287 sprintf(tmp, "%02d", creature_ptr->lev);
290 else if (streq(b + 1, "AUTOREGISTER"))
292 if (creature_ptr->autopick_autoregister)
297 else if (streq(b + 1, "MONEY"))
299 sprintf(tmp, "%09ld", (long int)creature_ptr->au);
310 * @brief process_pref_fileのサブルーチン /
311 * Open the "user pref file" and parse it.
312 * @param creature_ptr プレーヤーへの参照ポインタ
313 * @param name 読み込むファイル名
314 * @param preftype prefファイルのタイプ
319 * v: output buffer array
325 static errr process_pref_file_aux(player_type *creature_ptr, concptr name, int preftype)
328 fp = my_fopen(name, "r");
336 while (my_fgets(fp, buf, sizeof(buf)) == 0)
339 if (!buf[0]) continue;
342 if (!iskanji(buf[0]))
344 if (iswspace(buf[0])) continue;
346 if (buf[0] == '#') continue;
349 /* Process "?:<expr>" */
350 if ((buf[0] == '?') && (buf[1] == ':'))
355 concptr v = process_pref_file_expr(creature_ptr, &s, &f);
356 bypass = streq(v, "0");
360 if (bypass) continue;
362 /* Process "%:<file>" */
365 static int depth_count = 0;
366 if (depth_count > 20) continue;
371 case PREF_TYPE_AUTOPICK:
372 (void)process_autopick_file(creature_ptr, buf + 2);
374 case PREF_TYPE_HISTPREF:
375 (void)process_histpref_file(creature_ptr, buf + 2);
378 (void)process_pref_file(creature_ptr, buf + 2);
386 err = process_pref_file_command(creature_ptr, buf);
389 if (preftype != PREF_TYPE_AUTOPICK)
391 err = process_autopick_file_command(buf);
397 /* Print error message */
398 /* ToDo: Add better error messages */
399 msg_format(_("ファイル'%s'の%d行でエラー番号%dのエラー。", "Error %d in line %d of file '%s'."),
400 _(name, err), line, _(err, name));
401 msg_format(_("('%s'を解析中)", "Parsing '%s'"), old);
411 * @brief pref設定ファイルを読み込み設定を反映させる /
412 * Process the "user pref file" with the given name
413 * @param creature_ptr プレーヤーへの参照ポインタ
414 * @param name 読み込むファイル名
418 * See the functions above for a list of legal "commands".
419 * We also accept the special "?" and "%" directives, which
420 * allow conditional evaluation and filename inclusion.
423 errr process_pref_file(player_type *creature_ptr, concptr name)
426 path_build(buf, sizeof(buf), ANGBAND_DIR_PREF, name);
428 errr err1 = process_pref_file_aux(creature_ptr, buf, PREF_TYPE_NORMAL);
429 if (err1 > 0) return err1;
431 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name);
432 errr err2 = process_pref_file_aux(creature_ptr, buf, PREF_TYPE_NORMAL);
433 if (err2 < 0 && !err1)
441 * @brief プレイヤーステータスをファイルダンプ出力する
442 * Hack -- Dump a character description file
443 * @param creature_ptr プレーヤーへの参照ポインタ
444 * @param name 出力ファイル名
447 * Allow the "full" flag to dump additional info,
448 * and trigger its usage from various places in the code.
450 errr file_character(player_type *creature_ptr, concptr name, display_player_pf display_player, map_name_pf map_name)
453 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name);
455 FILE_TYPE(FILE_TYPE_TEXT);
457 int fd = fd_open(buf, O_RDONLY);
462 (void)sprintf(out_val, _("現存するファイル %s に上書きしますか? ", "Replace existing file %s? "), buf);
463 if (get_check_strict(out_val, CHECK_NO_HISTORY)) fd = -1;
467 if (fd < 0) fff = my_fopen(buf, "w");
471 prt(_("キャラクタ情報のファイルへの書き出しに失敗しました!", "Character dump failed!"), 0, 0);
476 make_character_dump(creature_ptr, fff, update_playtime, display_player, map_name);
478 msg_print(_("キャラクタ情報のファイルへの書き出しに成功しました。", "Character dump successful."));
485 * @brief ファイル内容の一行をコンソールに出力する
486 * Display single line of on-line help file
493 * You can insert some special color tag to change text color.
495 * WHITETEXT [[[[y|SOME TEXT WHICH IS DISPLAYED IN YELLOW| WHITETEXT
496 * A colored segment is between "[[[[y|" and the last "|".
497 * You can use any single character in place of the "|".
500 static void show_file_aux_line(concptr str, int cy, concptr shower)
512 static const char tag_str[] = "[[[[";
513 byte color = TERM_WHITE;
515 for (int i = 0; str[i];)
517 int len = strlen(&str[i]);
518 int showercol = len + 1;
519 int bracketcol = len + 1;
524 ptr = my_strstr(&lcstr[i], shower);
525 if (ptr) showercol = ptr - &lcstr[i];
528 ptr = in_tag ? my_strchr(&str[i], in_tag) : my_strstr(&str[i], tag_str);
529 if (ptr) bracketcol = ptr - &str[i];
530 if (bracketcol < endcol) endcol = bracketcol;
531 if (showercol < endcol) endcol = showercol;
533 Term_addstr(endcol, color, &str[i]);
537 if (endcol == showercol)
539 int showerlen = strlen(shower);
540 Term_addstr(showerlen, TERM_YELLOW, &str[i]);
546 if (endcol != bracketcol) continue;
556 i += sizeof(tag_str) - 1;
557 color = color_char_to_attr(str[i]);
558 if (color == 255 || str[i + 1] == '\0')
561 Term_addstr(-1, TERM_WHITE, tag_str);
562 cx += sizeof(tag_str) - 1;
571 Term_erase(cx, cy, 255);
576 * @brief ファイル内容をコンソールに出力する
577 * Recursive file perusal.
578 * @param creature_ptr プレーヤーへの参照ポインタ
579 * @param show_version TRUEならばコンソール上にゲームのバージョンを表示する
580 * @param name ファイル名の文字列
581 * @param what 内容キャプションの文字列
587 * Process various special text in the input file, including
588 * the "menu" structures used by the "help file" system.
589 * Return FALSE on 'q' to exit from a deep, otherwise TRUE.
592 bool show_file(player_type *creature_ptr, bool show_version, concptr name, concptr what, int line, BIT_FLAGS mode)
595 Term_get_size(&wid, &hgt);
598 strcpy(finder_str, "");
601 strcpy(shower_str, "");
607 for (int i = 0; i < 68; i++)
613 strcpy(filename, name);
614 int n = strlen(filename);
617 for (int i = 0; i < n; i++)
619 if (filename[i] == '#')
622 tag = filename + i + 1;
632 strcpy(caption, what);
634 fff = my_fopen(path, "r");
639 sprintf(caption, _("ヘルプ・ファイル'%s'", "Help file '%s'"), name);
640 path_build(path, sizeof(path), ANGBAND_DIR_HELP, name);
641 fff = my_fopen(path, "r");
646 sprintf(caption, _("スポイラー・ファイル'%s'", "Info file '%s'"), name);
647 path_build(path, sizeof(path), ANGBAND_DIR_INFO, name);
648 fff = my_fopen(path, "r");
653 path_build(path, sizeof(path), ANGBAND_DIR, name);
655 for (int i = 0; path[i]; i++)
657 path[i] = PATH_SEP[0];
659 sprintf(caption, _("スポイラー・ファイル'%s'", "Info file '%s'"), name);
660 fff = my_fopen(path, "r");
665 msg_format(_("'%s'をオープンできません。", "Cannot open '%s'."), name);
677 bool reverse = (line < 0);
681 if (my_fgets(fff, buf, sizeof(buf))) break;
682 if (!prefix(str, "***** "))
688 if ((str[6] == '[') && isalpha(str[7]))
690 int k = str[7] - 'A';
692 if ((str[8] == ']') && (str[9] == ' '))
694 strncpy(hook[k], str + 10, 31);
701 if (str[6] != '<') continue;
703 size_t len = strlen(str);
704 if (str[len - 1] == '>')
707 if (tag && streq(str + 7, tag)) line = next;
714 line = ((size - 1) / rows)*rows;
721 if (line >= size - rows)
723 if (line < 0) line = 0;
728 fff = my_fopen(path, "r");
729 if (!fff) return FALSE;
736 if (my_fgets(fff, buf, sizeof(buf))) break;
737 if (prefix(buf, "***** ")) continue;
742 concptr shower = NULL;
743 for (int i = 0; i < rows; i++)
747 if (my_fgets(fff, buf, sizeof(buf))) break;
748 if (prefix(buf, "***** ")) continue;
755 if (!my_strstr(lc_buf, find)) continue;
759 show_file_aux_line(str, i + 2, shower);
763 while (row_count < rows)
765 Term_erase(0, row_count + 2, 255);
779 prt(format(_("[変愚蛮怒 %d.%d.%d, %s, %d/%d]", "[Hengband %d.%d.%d, %s, Line %d/%d]"),
780 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH,
781 caption, line, size), 0, 0);
785 prt(format(_("[%s, %d/%d]", "[%s, Line %d/%d]"),
786 caption, line, size), 0, 0);
791 prt(_("[キー:(?)ヘルプ (ESC)終了]", "[Press ESC to exit.]"), hgt - 1, 0);
797 prt("[キー:(RET/スペース)↑ (-)↓ (?)ヘルプ (ESC)終了]", hgt - 1, 0);
799 prt("[キー:(RET/スペース)↓ (-)↑ (?)ヘルプ (ESC)終了]", hgt - 1, 0);
801 prt("[Press Return, Space, -, =, /, |, or ESC to exit.]", hgt - 1, 0);
805 skey = inkey_special(TRUE);
809 if (strcmp(name, _("jhelpinfo.txt", "helpinfo.txt")) != 0)
810 show_file(creature_ptr, TRUE, _("jhelpinfo.txt", "helpinfo.txt"), NULL, 0, mode);
813 prt(_("強調: ", "Show: "), hgt - 1, 0);
816 strcpy(back_str, shower_str);
817 if (askfor(shower_str, 80))
821 str_tolower(shower_str);
826 else strcpy(shower_str, back_str);
831 prt(_("検索: ", "Find: "), hgt - 1, 0);
832 strcpy(back_str, finder_str);
833 if (askfor(finder_str, 80))
840 str_tolower(finder_str);
845 else strcpy(finder_str, back_str);
851 prt(_("行: ", "Goto Line: "), hgt - 1, 0);
854 if (askfor(tmp, 80)) line = atoi(tmp);
863 line = ((size - 1) / rows) * rows;
869 prt(_("ファイル・ネーム: ", "Goto File: "), hgt - 1, 0);
870 strcpy(tmp, _("jhelp.hlp", "help.hlp"));
874 if (!show_file(creature_ptr, TRUE, tmp, NULL, 0, mode)) skey = 'q';
881 line = line + (reverse ? rows : -rows);
882 if (line < 0) line = 0;
887 if (line < 0) line = 0;
892 line = line + (reverse ? -1 : 1);
893 if (line < 0) line = 0;
899 if (line < 0) line = 0;
908 line = line + (reverse ? -rows : rows);
909 if (line < 0) line = 0;
920 if (!(skey & SKEY_MASK) && isalpha(skey))
923 if ((key > -1) && hook[key][0])
925 /* Recurse on that file */
926 if (!show_file(creature_ptr, TRUE, hook[key], NULL, 0, mode))
939 if (!get_string(_("ファイル名: ", "File name: "), xtmp, 80)) continue;
941 path_build(buff, sizeof(buff), ANGBAND_DIR_USER, xtmp);
943 /* Hack -- Re-Open the file */
944 fff = my_fopen(path, "r");
946 ffp = my_fopen(buff, "w");
950 msg_print(_("ファイルを開けません。", "Failed to open file."));
955 sprintf(xtmp, "%s: %s", creature_ptr->name, what ? what : caption);
956 my_fputs(ffp, xtmp, 80);
957 my_fputs(ffp, "\n", 80);
959 while (!my_fgets(fff, buff, sizeof(buff)))
960 my_fputs(ffp, buff, 80);
963 fff = my_fopen(path, "r");
966 if ((skey == ESCAPE) || (skey == '<')) break;
968 if (skey == KTRL('q')) skey = 'q';
970 if (skey == 'q') break;
974 return (skey != 'q');
979 * @brief セーブするコマンドのメインルーチン
981 * @param creature_ptr プレーヤーへの参照ポインタ
982 * @param is_autosave オートセーブ中の処理ならばTRUE
986 void do_cmd_save_game(player_type *creature_ptr, int is_autosave)
990 msg_print(_("自動セーブ中", "Autosaving the game..."));
994 disturb(creature_ptr, TRUE, TRUE);
998 handle_stuff(creature_ptr);
999 prt(_("ゲームをセーブしています...", "Saving game..."), 0, 0);
1001 (void)strcpy(creature_ptr->died_from, _("(セーブ)", "(saved)"));
1002 signals_ignore_tstp();
1003 if (save_player(creature_ptr))
1005 prt(_("ゲームをセーブしています... 終了", "Saving game... done."), 0, 0);
1009 prt(_("ゲームをセーブしています... 失敗!", "Saving game... failed!"), 0, 0);
1012 signals_handle_tstp();
1014 (void)strcpy(creature_ptr->died_from, _("(元気に生きている)", "(alive and well)"));
1015 current_world_ptr->is_loading_now = FALSE;
1016 update_creature(creature_ptr);
1017 mproc_init(creature_ptr->current_floor_ptr);
1018 current_world_ptr->is_loading_now = TRUE;
1023 * @brief セーブ後にゲーム中断フラグを立てる/
1024 * Save the game and exit
1028 void do_cmd_save_and_exit(player_type *creature_ptr)
1030 creature_ptr->playing = FALSE;
1031 creature_ptr->leaving = TRUE;
1032 exe_write_diary(creature_ptr, DIARY_GAMESTART, 0, _("----ゲーム中断----", "---- Save and Exit Game ----"));
1037 * @brief 異常発生時のゲーム緊急終了処理 /
1038 * Handle abrupt death of the visual system
1039 * @param creature_ptr プレーヤーへの参照ポインタ
1042 * This routine is called only in very rare situations, and only
1043 * by certain visual systems, when they experience fatal errors.
1045 void exit_game_panic(player_type *creature_ptr)
1047 if (!current_world_ptr->character_generated || current_world_ptr->character_saved)
1048 quit(_("緊急事態", "panic"));
1052 disturb(creature_ptr, TRUE, TRUE);
1053 if (creature_ptr->chp < 0) creature_ptr->is_dead = FALSE;
1055 creature_ptr->panic_save = 1;
1056 signals_ignore_tstp();
1057 (void)strcpy(creature_ptr->died_from, _("(緊急セーブ)", "(panic save)"));
1058 if (!save_player(creature_ptr)) quit(_("緊急セーブ失敗!", "panic save failed!"));
1059 quit(_("緊急セーブ成功!", "panic save succeeded!"));
1064 * @brief ファイルからランダムに行を一つ取得する /
1065 * Get a random line from a file
1066 * @param file_name ファイル名
1067 * @param entry 特定条件時のN:タグヘッダID
1068 * @param output 出力先の文字列参照ポインタ
1072 * Based on the monster speech patch by Matt Graham,
1075 errr get_rnd_line(concptr file_name, int entry, char *output)
1078 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, file_name);
1080 fp = my_fopen(buf, "r");
1087 if (my_fgets(fp, buf, sizeof(buf)) != 0)
1094 if ((buf[0] != 'N') || (buf[1] != ':')) continue;
1100 else if (buf[2] == 'M')
1102 if (r_info[entry].flags1 & RF1_MALE) break;
1104 else if (buf[2] == 'F')
1106 if (r_info[entry].flags1 & RF1_FEMALE) break;
1108 else if (sscanf(&(buf[2]), "%d", &test) != EOF)
1110 if (test == entry) break;
1113 msg_format("Error in line %d of %s!", line_num, file_name);
1119 for (counter = 0; ; counter++)
1123 test = my_fgets(fp, buf, sizeof(buf));
1126 /* Ignore lines starting with 'N:' */
1127 if ((buf[0] == 'N') && (buf[1] == ':')) continue;
1129 if (buf[0] != '#') break;
1136 if (one_in_(counter + 1)) strcpy(output, buf);
1140 return counter ? 0 : -1;
1146 * @brief ファイルからランダムに行を一つ取得する(日本語文字列のみ) /
1147 * @param file_name ファイル名
1148 * @param entry 特定条件時のN:タグヘッダID
1149 * @param output 出力先の文字列参照ポインタ
1154 errr get_rnd_line_jonly(concptr file_name, int entry, char *output, int count)
1157 for (int i = 0; i < count; i++)
1159 result = get_rnd_line(file_name, entry, output);
1162 for (int j = 0; output[j]; j++) kanji |= iskanji(output[j]);
1172 * @brief 自動拾いファイルを読み込む /
1173 * @param creature_ptr プレーヤーへの参照ポインタ
1177 errr process_autopick_file(player_type *creature_ptr, concptr name)
1180 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name);
1181 errr err = process_pref_file_aux(creature_ptr, buf, PREF_TYPE_AUTOPICK);
1187 * @brief プレイヤーの生い立ちファイルを読み込む /
1188 * Process file for player's history editor.
1189 * @param creature_ptr プレーヤーへの参照ポインタ
1194 errr process_histpref_file(player_type *creature_ptr, concptr name)
1196 bool old_character_xtra = current_world_ptr->character_xtra;
1198 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name);
1200 /* Hack -- prevent modification birth options in this file */
1201 current_world_ptr->character_xtra = TRUE;
1202 errr err = process_pref_file_aux(creature_ptr, buf, PREF_TYPE_HISTPREF);
1203 current_world_ptr->character_xtra = old_character_xtra;
1209 * @brief ファイル位置をシーク /
1210 * @param creature_ptr プレーヤーへの参照ポインタ
1211 * @param fd ファイルディスクリプタ
1212 * @param where ファイルバイト位置
1213 * @param flag FALSEならば現ファイルを超えた位置へシーク時エラー、TRUEなら足りない間を0で埋め尽くす
1217 static errr counts_seek(player_type *creature_ptr, int fd, u32b where, bool flag)
1219 char temp1[128], temp2[128];
1220 #ifdef SAVEFILE_USE_UID
1221 (void)sprintf(temp1, "%d.%s.%d%d%d", creature_ptr->player_uid, savefile_base, creature_ptr->pclass, creature_ptr->pseikaku, creature_ptr->age);
1223 (void)sprintf(temp1, "%s.%d%d%d", savefile_base, creature_ptr->pclass, creature_ptr->pseikaku, creature_ptr->age);
1225 for (int i = 0; temp1[i]; i++)
1226 temp1[i] ^= (i + 1) * 63;
1229 u32b zero_header[3] = { 0L, 0L, 0L };
1232 if (fd_seek(fd, seekpoint + 3 * sizeof(u32b)))
1234 if (fd_read(fd, (char*)(temp2), sizeof(temp2)))
1239 fd_seek(fd, seekpoint);
1240 fd_write(fd, (char*)zero_header, 3 * sizeof(u32b));
1241 fd_write(fd, (char*)(temp1), sizeof(temp1));
1245 if (strcmp(temp1, temp2) == 0)
1248 seekpoint += 128 + 3 * sizeof(u32b);
1251 return fd_seek(fd, seekpoint + where * sizeof(u32b));
1256 * @brief ファイル位置を読み込む
1257 * @param creature_ptr プレーヤーへの参照ポインタ
1258 * @param where ファイルバイト位置
1262 u32b counts_read(player_type *creature_ptr, int where)
1265 path_build(buf, sizeof(buf), ANGBAND_DIR_DATA, _("z_info_j.raw", "z_info.raw"));
1266 int fd = fd_open(buf, O_RDONLY);
1269 if (counts_seek(creature_ptr, fd, where, FALSE) ||
1270 fd_read(fd, (char*)(&count), sizeof(u32b)))
1280 * @brief ファイル位置に書き込む /
1281 * @param creature_ptr プレーヤーへの参照ポインタ
1282 * @param where ファイルバイト位置
1283 * @param count 書き込む値
1287 errr counts_write(player_type *creature_ptr, int where, u32b count)
1290 path_build(buf, sizeof(buf), ANGBAND_DIR_DATA, _("z_info_j.raw", "z_info.raw"));
1293 int fd = fd_open(buf, O_RDWR);
1297 FILE_TYPE(FILE_TYPE_DATA);
1299 fd = fd_make(buf, 0644);
1304 errr err = fd_lock(fd, F_WRLCK);
1308 counts_seek(creature_ptr, fd, where, TRUE);
1309 fd_write(fd, (char*)(&count), sizeof(u32b));
1311 err = fd_lock(fd, F_UNLCK);
1322 * @brief 墓のアスキーアートテンプレを読み込む
1323 * @param buf テンプレへのバッファ
1324 * @param buf_size バッファの長さ
1327 void read_dead_file(char *buf, size_t buf_size)
1329 path_build(buf, buf_size, ANGBAND_DIR_FILE, _("dead_j.txt", "dead.txt"));
1332 fp = my_fopen(buf, "r");
1336 while (my_fgets(fp, buf, buf_size) == 0)
1338 put_str(buf, i++, 0);