1 #include "io-dump/character-dump.h"
2 #include "art-definition/art-bow-types.h"
4 #include "dungeon/dungeon.h"
5 #include "dungeon/quest.h"
6 #include "floor/floor-town.h"
7 #include "floor/floor.h"
8 #include "game-option/birth-options.h"
9 #include "game-option/game-play-options.h"
10 #include "io-dump/player-status-dump.h"
11 #include "io-dump/special-class-dump.h"
12 #include "io/mutations-dump.h"
13 #include "io/write-diary.h"
14 #include "knowledge/knowledge-quests.h"
15 #include "main/init.h"
16 #include "market/arena-info-table.h"
17 #include "monster-race/race-flags1.h"
18 #include "monster/monster-describer.h"
19 #include "monster/monster-description-types.h"
20 #include "monster/monster-info.h"
21 #include "monster/monster-status.h"
22 #include "monster/smart-learn-types.h"
23 #include "object/object-flavor.h"
24 #include "object/object-info.h"
25 #include "pet/pet-util.h"
26 #include "player/avatar.h"
27 #include "player/race-info-table.h"
28 #include "store/store-util.h"
29 #include "store/store.h"
30 #include "system/angband-version.h"
31 #include "util/int-char-converter.h"
32 #include "view/display-messages.h"
33 #include "world/world.h"
36 * @brief プレイヤーのペット情報をファイルにダンプする
37 * @param creature_ptr プレーヤーへの参照ポインタ
41 static void dump_aux_pet(player_type *master_ptr, FILE *fff)
44 bool pet_settings = FALSE;
45 for (int i = master_ptr->current_floor_ptr->m_max - 1; i >= 1; i--)
47 monster_type *m_ptr = &master_ptr->current_floor_ptr->m_list[i];
49 if (!monster_is_valid(m_ptr)) continue;
50 if (!is_pet(m_ptr)) continue;
52 if (!m_ptr->nickname && (master_ptr->riding != i)) continue;
55 fprintf(fff, _("\n\n [主なペット]\n\n", "\n\n [Leading Pets]\n\n"));
59 GAME_TEXT pet_name[MAX_NLEN];
60 monster_desc(master_ptr, pet_name, m_ptr, MD_ASSUME_VISIBLE | MD_INDEF_VISIBLE);
61 fprintf(fff, "%s\n", pet_name);
64 if (!pet_settings) return;
66 fprintf(fff, _("\n\n [ペットへの命令]\n", "\n\n [Command for Pets]\n"));
68 fprintf(fff, _("\n ドアを開ける: %s", "\n Pets open doors: %s"),
69 (master_ptr->pet_extra_flags & PF_OPEN_DOORS) ? "ON" : "OFF");
71 fprintf(fff, _("\n アイテムを拾う: %s", "\n Pets pick up items: %s"),
72 (master_ptr->pet_extra_flags & PF_PICKUP_ITEMS) ? "ON" : "OFF");
74 fprintf(fff, _("\n テレポート系魔法を使う: %s", "\n Allow teleport: %s"),
75 (master_ptr->pet_extra_flags & PF_TELEPORT) ? "ON" : "OFF");
77 fprintf(fff, _("\n 攻撃魔法を使う: %s", "\n Allow cast attack spell: %s"),
78 (master_ptr->pet_extra_flags & PF_ATTACK_SPELL) ? "ON" : "OFF");
80 fprintf(fff, _("\n 召喚魔法を使う: %s", "\n Allow cast summon spell: %s"),
81 (master_ptr->pet_extra_flags & PF_SUMMON_SPELL) ? "ON" : "OFF");
83 fprintf(fff, _("\n プレイヤーを巻き込む範囲魔法を使う: %s", "\n Allow involve player in area spell: %s"),
84 (master_ptr->pet_extra_flags & PF_BALL_SPELL) ? "ON" : "OFF");
91 * @brief クエスト情報をファイルにダンプする
92 * @param creature_ptr プレーヤーへの参照ポインタ
96 static void dump_aux_quest(player_type *creature_ptr, FILE *fff)
98 fprintf(fff, _("\n\n [クエスト情報]\n", "\n\n [Quest Information]\n"));
100 C_MAKE(quest_num, max_q_idx, QUEST_IDX);
102 for (QUEST_IDX i = 1; i < max_q_idx; i++)
105 ang_sort(quest_num, &dummy, max_q_idx, ang_sort_comp_quest_num, ang_sort_swap_quest_num);
108 do_cmd_knowledge_quests_completed(creature_ptr, fff, quest_num);
110 do_cmd_knowledge_quests_failed(creature_ptr, fff, quest_num);
113 C_KILL(quest_num, max_q_idx, QUEST_IDX);
118 * @brief 死の直前メッセージ並びに遺言をファイルにダンプする
119 * @param creature_ptr プレーヤーへの参照ポインタ
120 * @param fff ファイルポインタ
123 static void dump_aux_last_message(player_type *creature_ptr, FILE *fff)
125 if (!creature_ptr->is_dead) return;
127 if (!current_world_ptr->total_winner)
129 fprintf(fff, _("\n [死ぬ直前のメッセージ]\n\n", "\n [Last Messages]\n\n"));
130 for (int i = MIN(message_num(), 30); i >= 0; i--)
132 fprintf(fff, "> %s\n", message_str((s16b)i));
139 if (creature_ptr->last_message)
141 fprintf(fff, _("\n [*勝利*メッセージ]\n\n", "\n [*Winning* Message]\n\n"));
142 fprintf(fff, " %s\n", creature_ptr->last_message);
149 * @brief 帰還場所情報をファイルにダンプする
150 * @param fff ファイルポインタ
153 static void dump_aux_recall(FILE *fff)
155 fprintf(fff, _("\n [帰還場所]\n\n", "\n [Recall Depth]\n\n"));
156 for (int y = 1; y < current_world_ptr->max_d_idx; y++)
160 if (!d_info[y].maxdepth) continue;
161 if (!max_dlv[y]) continue;
162 if (d_info[y].final_guardian)
164 if (!r_info[d_info[y].final_guardian].max_num) seiha = TRUE;
166 else if (max_dlv[y] == d_info[y].maxdepth) seiha = TRUE;
168 fprintf(fff, _(" %c%-12s: %3d 階\n", " %c%-16s: level %3d\n"),
169 seiha ? '!' : ' ', d_name + d_info[y].name, (int)max_dlv[y]);
175 * @brief オプション情報をファイルにダンプする
176 * @param fff ファイルポインタ
179 static void dump_aux_options(FILE *fff)
181 fprintf(fff, _("\n [オプション設定]\n", "\n [Option Settings]\n"));
183 fprintf(fff, _("\n 保存モード: ON", "\n Preserve Mode: ON"));
185 fprintf(fff, _("\n 保存モード: OFF", "\n Preserve Mode: OFF"));
187 if (ironman_small_levels)
188 fprintf(fff, _("\n 小さいダンジョン: ALWAYS", "\n Small Levels: ALWAYS"));
189 else if (always_small_levels)
190 fprintf(fff, _("\n 小さいダンジョン: ON", "\n Small Levels: ON"));
191 else if (small_levels)
192 fprintf(fff, _("\n 小さいダンジョン: ENABLED", "\n Small Levels: ENABLED"));
194 fprintf(fff, _("\n 小さいダンジョン: OFF", "\n Small Levels: OFF"));
197 fprintf(fff, _("\n 元祖の町のみ: ON", "\n Vanilla Town: ON"));
199 fprintf(fff, _("\n 小規模な町: ON", "\n Lite Town: ON"));
202 fprintf(fff, _("\n 店なし: ON", "\n No Shops: ON"));
204 if (ironman_downward)
205 fprintf(fff, _("\n 階段を上がれない: ON", "\n Diving Only: ON"));
208 fprintf(fff, _("\n 普通でない部屋: ON", "\n Unusual Rooms: ON"));
210 if (ironman_nightmare)
211 fprintf(fff, _("\n 悪夢モード: ON", "\n Nightmare Mode: ON"));
213 if (ironman_empty_levels)
214 fprintf(fff, _("\n アリーナ: ALWAYS", "\n Arena Levels: ALWAYS"));
215 else if (empty_levels)
216 fprintf(fff, _("\n アリーナ: ENABLED", "\n Arena Levels: ENABLED"));
218 fprintf(fff, _("\n アリーナ: OFF", "\n Arena Levels: OFF"));
222 if (current_world_ptr->noscore)
223 fprintf(fff, _("\n 何か不正なことをしてしまっています。\n", "\n You have done something illegal.\n"));
230 * @brief 闘技場の情報をファイルにダンプする
231 * @param creature_ptr プレーヤーへの参照ポインタ
232 * @param fff ファイルポインタ
235 static void dump_aux_arena(player_type *creature_ptr, FILE *fff)
237 if (lite_town || vanilla_town) return;
239 if (creature_ptr->arena_number < 0)
241 if (creature_ptr->arena_number <= ARENA_DEFEATED_OLD_VER)
243 fprintf(fff, _("\n 闘技場: 敗北\n", "\n Arena: Defeated\n"));
248 fprintf(fff, "\n 闘技場: %d回戦で%sの前に敗北\n", -creature_ptr->arena_number,
249 r_name + r_info[arena_info[-1 - creature_ptr->arena_number].r_idx].name);
251 fprintf(fff, "\n Arena: Defeated by %s in the %d%s fight\n",
252 r_name + r_info[arena_info[-1 - creature_ptr->arena_number].r_idx].name,
253 -creature_ptr->arena_number, get_ordinal_number_suffix(-creature_ptr->arena_number));
261 if (creature_ptr->arena_number > MAX_ARENA_MONS + 2)
263 fprintf(fff, _("\n 闘技場: 真のチャンピオン\n", "\n Arena: True Champion\n"));
268 if (creature_ptr->arena_number > MAX_ARENA_MONS - 1)
270 fprintf(fff, _("\n 闘技場: チャンピオン\n", "\n Arena: Champion\n"));
276 fprintf(fff, "\n 闘技場: %2d勝\n", (creature_ptr->arena_number > MAX_ARENA_MONS ? MAX_ARENA_MONS : creature_ptr->arena_number));
278 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");
285 * @brief 撃破モンスターの情報をファイルにダンプする
286 * @param fff ファイルポインタ
289 static void dump_aux_monsters(FILE *fff)
291 fprintf(fff, _("\n [倒したモンスター]\n\n", "\n [Defeated Monsters]\n\n"));
293 /* Allocate the "who" array */
296 C_MAKE(who, max_r_idx, MONRACE_IDX);
298 /* Count monster kills */
301 for (IDX k = 1; k < max_r_idx; k++)
303 /* Ignore unused index */
304 monster_race *r_ptr = &r_info[k];
305 if (!r_ptr->name) continue;
307 if (r_ptr->flags1 & RF1_UNIQUE)
309 bool dead = (r_ptr->max_num == 0);
314 /* Add a unique monster to the list */
315 who[uniq_total++] = k;
321 if (r_ptr->r_pkills > 0)
323 norm_total += r_ptr->r_pkills;
327 /* No monsters is defeated */
330 fprintf(fff, _("まだ敵を倒していません。\n", "You have defeated no enemies yet.\n"));
331 C_KILL(who, max_r_idx, s16b);
335 /* Defeated more than one normal monsters */
339 fprintf(fff, "%ld体の敵を倒しています。\n", norm_total);
341 fprintf(fff, "You have defeated %ld %s.\n", norm_total, norm_total == 1 ? "enemy" : "enemies");
343 C_KILL(who, max_r_idx, s16b);
347 /* Defeated more than one unique monsters */
349 fprintf(fff, "%ld体のユニーク・モンスターを含む、合計%ld体の敵を倒しています。\n", uniq_total, norm_total);
351 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"));
354 /* Sort the array by dungeon depth of monsters */
355 ang_sort(who, &why, uniq_total, ang_sort_comp_hook, ang_sort_swap_hook);
356 fprintf(fff, _("\n《上位%ld体のユニーク・モンスター》\n", "\n< Unique monsters top %ld >\n"), MIN(uniq_total, 10));
358 for (IDX k = uniq_total - 1; k >= 0 && k >= uniq_total - 10; k--)
360 monster_race *r_ptr = &r_info[who[k]];
361 fprintf(fff, _(" %-40s (レベル%3d)\n", " %-40s (level %3d)\n"), (r_name + r_ptr->name), (int)r_ptr->level);
364 C_KILL(who, max_r_idx, s16b);
369 * @brief 元種族情報をファイルにダンプする
370 * @param creature_ptr プレーヤーへの参照ポインタ
371 * @param fff ファイルポインタ
374 static void dump_aux_race_history(player_type *creature_ptr, FILE *fff)
376 if (!creature_ptr->old_race1 && !creature_ptr->old_race2) return;
378 fprintf(fff, _("\n\n あなたは%sとして生まれた。", "\n\n You were born as %s."), race_info[creature_ptr->start_race].title);
379 for (int i = 0; i < MAX_RACES; i++)
381 if (creature_ptr->start_race == i) continue;
384 if (!(creature_ptr->old_race1 & 1L << i)) continue;
388 if (!(creature_ptr->old_race2 & 1L << (i - 32))) continue;
391 fprintf(fff, _("\n あなたはかつて%sだった。", "\n You were a %s before."), race_info[i].title);
399 * @brief 元魔法領域情報をファイルにダンプする
400 * @param creature_ptr プレーヤーへの参照ポインタ
401 * @param fff ファイルポインタ
404 static void dump_aux_realm_history(player_type *creature_ptr, FILE *fff)
406 if (creature_ptr->old_realm) return;
409 for (int i = 0; i < MAX_MAGIC; i++)
411 if (!(creature_ptr->old_realm & 1L << i)) continue;
412 fprintf(fff, _("\n あなたはかつて%s魔法を使えた。", "\n You were able to use %s magic before."), realm_names[i + 1]);
420 * @brief 徳の情報をファイルにダンプする
421 * @param creature_ptr プレーヤーへの参照ポインタ
422 * @param fff ファイルポインタ
425 static void dump_aux_virtues(player_type *creature_ptr, FILE *fff)
427 fprintf(fff, _("\n\n [自分に関する情報]\n\n", "\n\n [HP-rate & Max stat & Virtues]\n\n"));
429 int percent = (int)(((long)creature_ptr->player_hp[PY_MAX_LEVEL - 1] * 200L) /
430 (2 * creature_ptr->hitdie +
431 ((PY_MAX_LEVEL - 1 + 3) * (creature_ptr->hitdie + 1))));
434 if (creature_ptr->knowledge & KNOW_HPRATE) fprintf(fff, "現在の体力ランク : %d/100\n\n", percent);
435 else fprintf(fff, "現在の体力ランク : ???\n\n");
436 fprintf(fff, "能力の最大値\n");
438 if (creature_ptr->knowledge & KNOW_HPRATE) fprintf(fff, "Your current Life Rating is %d/100.\n\n", percent);
439 else fprintf(fff, "Your current Life Rating is ???.\n\n");
440 fprintf(fff, "Limits of maximum stats\n");
442 for (int v_nr = 0; v_nr < A_MAX; v_nr++)
444 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);
445 else fprintf(fff, "%s ???\n", stat_names[v_nr]);
448 fprintf(fff, _("\n属性 : %s\n", "\nYour alignment : %s\n"), your_alignment(creature_ptr));
450 dump_virtues(creature_ptr, fff);
455 * @brief 突然変異の情報をファイルにダンプする
456 * @param creature_ptr プレーヤーへの参照ポインタ
457 * @param fff ファイルポインタ
460 static void dump_aux_mutations(player_type *creature_ptr, FILE *fff)
462 if (creature_ptr->muta1 || creature_ptr->muta2 || creature_ptr->muta3)
464 fprintf(fff, _("\n\n [突然変異]\n\n", "\n\n [Mutations]\n\n"));
465 dump_mutations(creature_ptr, fff);
471 * @brief 所持品の情報をファイルにダンプする
472 * @param creature_ptr プレーヤーへの参照ポインタ
473 * @param fff ファイルポインタ
476 static void dump_aux_equipment_inventory(player_type *creature_ptr, FILE *fff)
478 GAME_TEXT o_name[MAX_NLEN];
479 if (creature_ptr->equip_cnt)
481 fprintf(fff, _(" [キャラクタの装備]\n\n", " [Character Equipment]\n\n"));
482 for (int i = INVEN_RARM; i < INVEN_TOTAL; i++)
484 object_desc(creature_ptr, o_name, &creature_ptr->inventory_list[i], 0);
485 if ((((i == INVEN_RARM) && creature_ptr->hidarite) || ((i == INVEN_LARM) && creature_ptr->migite)) && creature_ptr->ryoute)
486 strcpy(o_name, _("(武器を両手持ち)", "(wielding with two-hands)"));
488 fprintf(fff, "%c) %s\n",
489 index_to_label(i), o_name);
492 fprintf(fff, "\n\n");
495 fprintf(fff, _(" [キャラクタの持ち物]\n\n", " [Character Inventory]\n\n"));
497 for (int i = 0; i < INVEN_PACK; i++)
499 if (!creature_ptr->inventory_list[i].k_idx) break;
500 object_desc(creature_ptr, o_name, &creature_ptr->inventory_list[i], 0);
501 fprintf(fff, "%c) %s\n", index_to_label(i), o_name);
504 fprintf(fff, "\n\n");
509 * @brief 我が家と博物館のオブジェクト情報をファイルにダンプする
510 * @param fff ファイルポインタ
513 static void dump_aux_home_museum(player_type *creature_ptr, FILE *fff)
515 store_type *store_ptr;
516 store_ptr = &town_info[1].store[STORE_HOME];
518 GAME_TEXT o_name[MAX_NLEN];
519 if (store_ptr->stock_num)
521 fprintf(fff, _(" [我が家のアイテム]\n", " [Home Inventory]\n"));
524 for (int i = 0; i < store_ptr->stock_num; i++)
527 fprintf(fff, _("\n ( %d ページ )\n", "\n ( page %d )\n"), x++);
528 object_desc(creature_ptr, o_name, &store_ptr->stock[i], 0);
529 fprintf(fff, "%c) %s\n", I2A(i % 12), o_name);
532 fprintf(fff, "\n\n");
535 store_ptr = &town_info[1].store[STORE_MUSEUM];
537 if (store_ptr->stock_num == 0) return;
539 fprintf(fff, _(" [博物館のアイテム]\n", " [Museum]\n"));
542 for (int i = 0; i < store_ptr->stock_num; i++)
545 if ((i % 12) == 0) fprintf(fff, "\n ( %d ページ )\n", x++);
546 object_desc(creature_ptr, o_name, &store_ptr->stock[i], 0);
547 fprintf(fff, "%c) %s\n", I2A(i % 12), o_name);
549 if ((i % 12) == 0) fprintf(fff, "\n ( page %d )\n", x++);
550 object_desc(creature_ptr, o_name, &st_ptr->stock[i], 0);
551 fprintf(fff, "%c) %s\n", I2A(i % 12), o_name);
555 fprintf(fff, "\n\n");
560 * @brief ダンプ出力のメインルーチン
561 * Output the character dump to a file
562 * @param creature_ptr プレーヤーへの参照ポインタ
563 * @param fff ファイルポインタ
566 void make_character_dump(player_type *creature_ptr, FILE *fff, void(*update_playtime)(void), display_player_pf display_player, map_name_pf map_name)
568 fprintf(fff, _(" [変愚蛮怒 %d.%d.%d キャラクタ情報]\n\n", " [Hengband %d.%d.%d Character Dump]\n\n"),
569 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH);
570 (*update_playtime)();
572 dump_aux_player_status(creature_ptr, fff, display_player, map_name);
573 dump_aux_last_message(creature_ptr, fff);
574 dump_aux_options(fff);
575 dump_aux_recall(fff);
576 dump_aux_quest(creature_ptr, fff);
577 dump_aux_arena(creature_ptr, fff);
578 dump_aux_monsters(fff);
579 dump_aux_virtues(creature_ptr, fff);
580 dump_aux_race_history(creature_ptr, fff);
581 dump_aux_realm_history(creature_ptr, fff);
582 dump_aux_class_special(creature_ptr, fff);
583 dump_aux_mutations(creature_ptr, fff);
584 dump_aux_pet(creature_ptr, fff);
586 dump_aux_equipment_inventory(creature_ptr, fff);
587 dump_aux_home_museum(creature_ptr, fff);
589 fprintf(fff, _(" [チェックサム: \"%s\"]\n\n", " [Check Sum: \"%s\"]\n\n"), get_check_sum());