* @author Hourier
*/
-#include "core/show-file.h"
-#include "core/sort.h"
-#include "io-dump/dump-util.h"
-#include "knowledge-items.h"
#include "system/angband.h"
+#include "game-option/cheat-options.h"
+#include "knowledge-items.h"
+#include "io-dump/dump-util.h"
+#include "util/sort.h"
+#include "core/show-file.h"
+#include "monster-race/race-flags1.h"
+#include "util/angband-files.h"
- /*
- * Display known uniques
- * With "XTRA HACK UNIQHIST" (Originally from XAngband)
+ typedef struct unique_list_type {
+ bool is_alive;
+ u16b why;
+ IDX *who;
+ int num_uniques[10];
+ int num_uniques_surface;
+ int num_uniques_over100;
+ int num_uniques_total;
+ int max_lev;
+ int n;
+ } unique_list_type;
+
+ unique_list_type *initialize_unique_lsit_type(unique_list_type *unique_list_ptr, bool is_alive)
+ {
+ unique_list_ptr->is_alive = is_alive;
+ unique_list_ptr->why = 2;
+ unique_list_ptr->num_uniques_surface = 0;
+ unique_list_ptr->num_uniques_over100 = 0;
+ unique_list_ptr->num_uniques_total = 0;
+ unique_list_ptr->max_lev = -1;
+ unique_list_ptr->n = 0;
+ for (IDX i = 0; i < 10; i++)
+ unique_list_ptr->num_uniques[i] = 0;
+
+ return unique_list_ptr;
+ }
+
+ /*!
+ * @brief モンスターリストを走査し、生きているか死んでいるユニークだけを抽出する
+ * @param r_ptr モンスター種別への参照ポインタ
+ * @param is_alive 生きているユニークのリストならばTRUE、撃破したユニークのリストならばFALSE
+ * @return is_aliveの条件に見合うユニークがいたらTRUE、それ以外はFALSE
+ * @details 闘技場のモンスターとは再戦できないので、生きているなら表示から外す
+ */
+ static bool sweep_uniques(monster_race *r_ptr, bool is_alive)
+ {
+ if (!r_ptr->name)
+ return FALSE;
+
+ if (!(r_ptr->flags1 & RF1_UNIQUE))
+
+ return FALSE;
+
+ if (!cheat_know && !r_ptr->r_sights)
+ return FALSE;
+
+ bool is_except_arena = is_alive ? (r_ptr->rarity > 100) && ((r_ptr->flags1 & RF1_QUESTOR) == 0) : FALSE;
+ if (!r_ptr->rarity || is_except_arena)
+ return FALSE;
+
+ if (is_alive) {
+ if (r_ptr->max_num == 0)
+ return FALSE;
+ } else {
+ if (r_ptr->max_num > 0)
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ static void display_uniques(unique_list_type *unique_list_ptr, FILE *fff)
+ {
+ if (unique_list_ptr->num_uniques_surface) {
+ concptr surface_desc = unique_list_ptr->is_alive ? _(" 地上 生存: %3d体\n", " Surface alive: %3d\n")
+ : _(" 地上 撃破: %3d体\n", " Surface dead: %3d\n");
+ fprintf(fff, surface_desc, unique_list_ptr->num_uniques_surface);
+ unique_list_ptr->num_uniques_total += unique_list_ptr->num_uniques_surface;
+ }
+
+ for (IDX i = 0; i <= unique_list_ptr->max_lev; i++) {
+ concptr dungeon_desc = unique_list_ptr->is_alive ? _("%3d-%3d階 生存: %3d体\n", "Level %3d-%3d alive: %3d\n")
+ : _("%3d-%3d階 撃破: %3d体\n", "Level %3d-%3d dead: %3d\n");
+ fprintf(fff, dungeon_desc, 1 + i * 10, 10 + i * 10, unique_list_ptr->num_uniques[i]);
+ unique_list_ptr->num_uniques_total += unique_list_ptr->num_uniques[i];
+ }
+
+ if (unique_list_ptr->num_uniques_over100) {
+ concptr deep_desc = unique_list_ptr->is_alive ? _("101- 階 生存: %3d体\n", "Level 101- alive: %3d\n")
+ : _("101- 階 撃破: %3d体\n", "Level 101- dead: %3d\n");
+ fprintf(fff, deep_desc, unique_list_ptr->num_uniques_over100);
+ unique_list_ptr->num_uniques_total += unique_list_ptr->num_uniques_over100;
+ }
+
+ if (unique_list_ptr->num_uniques_total) {
+ fputs(_("--------- -----------\n", "------------- ----------\n"), fff);
+ concptr total_desc = unique_list_ptr->is_alive ? _(" 合計 生存: %3d体\n\n", " Total alive: %3d\n\n")
+ : _(" 合計 撃破: %3d体\n\n", " Total dead: %3d\n\n");
+ fprintf(fff, total_desc, unique_list_ptr->num_uniques_total);
+ } else {
+ concptr no_unique_desc = unique_list_ptr->is_alive ? _("現在は既知の生存ユニークはいません。\n", "No known uniques alive.\n")
+ : _("現在は既知の撃破ユニークはいません。\n", "No known uniques dead.\n");
+ fputs(no_unique_desc, fff);
+ }
+
+ for (int k = 0; k < unique_list_ptr->n; k++) {
+ monster_race *r_ptr = &r_info[unique_list_ptr->who[k]];
+ fprintf(fff, _(" %s (レベル%d)\n", " %s (level %d)\n"), r_name + r_ptr->name, (int)r_ptr->level);
+ }
+ }
+
+ /*!
+ * @brief 既知の生きているユニークまたは撃破済ユニークの一覧を表示させる
+ * @param creature_ptr プレーヤーへの参照ポインタ
+ * @param is_alive 生きているユニークのリストならばTRUE、撃破したユニークのリストならばFALSE
+ * @return なし
*/
- void do_cmd_knowledge_uniques(player_type *creature_ptr)
+ void do_cmd_knowledge_uniques(player_type *creature_ptr, bool is_alive)
{
- u16b why = 2;
- IDX *who;
+ int n_alive[10];
- int n_alive_surface = 0;
- int n_alive_over100 = 0;
- int n_alive_total = 0;
- int max_lev = -1;
+ for (IDX i = 0; i < 10; i++)
+ n_alive[i] = 0;
+
- FILE *fff = NULL;
- GAME_TEXT file_name[FILE_NAME_SIZE];
- if (!open_temporary_file(&fff, file_name)) return;
-
- C_MAKE(who, max_r_idx, MONRACE_IDX);
- int n = 0;
- for (IDX i = 1; i < max_r_idx; i++)
- {
- monster_race *r_ptr = &r_info[i];
- if (!r_ptr->name) continue;
- if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
- if (!cheat_know && !r_ptr->r_sights) continue;
- if (!r_ptr->rarity || ((r_ptr->rarity > 100) && !(r_ptr->flags1 & RF1_QUESTOR))) continue;
- if (r_ptr->max_num == 0) continue;
-
- if (r_ptr->level)
- {
- int lev = (r_ptr->level - 1) / 10;
- if (lev < 10)
- {
- n_alive[lev]++;
- if (max_lev < lev) max_lev = lev;
- }
- else
- n_alive_over100++;
- }
- else
- n_alive_surface++;
-
- who[n++] = i;
- }
-
- ang_sort(who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook);
- if (n_alive_surface)
- {
- fprintf(fff, _(" 地上 生存: %3d体\n", " Surface alive: %3d\n"), n_alive_surface);
- n_alive_total += n_alive_surface;
- }
-
- for (IDX i = 0; i <= max_lev; i++)
- {
- fprintf(fff, _("%3d-%3d階 生存: %3d体\n", "Level %3d-%3d alive: %3d\n"), 1 + i * 10, 10 + i * 10, n_alive[i]);
- n_alive_total += n_alive[i];
- }
-
- if (n_alive_over100)
- {
- fprintf(fff, _("101- 階 生存: %3d体\n", "Level 101- alive: %3d\n"), n_alive_over100);
- n_alive_total += n_alive_over100;
- }
-
- if (n_alive_total)
- {
- fputs(_("--------- -----------\n", "------------- ----------\n"), fff);
- fprintf(fff, _(" 合計 生存: %3d体\n\n", " Total alive: %3d\n\n"), n_alive_total);
- }
- else
- {
- fputs(_("現在は既知の生存ユニークはいません。\n", "No known uniques alive.\n"), fff);
- }
-
- for (int k = 0; k < n; k++)
- {
- monster_race *r_ptr = &r_info[who[k]];
- fprintf(fff, _(" %s (レベル%d)\n", " %s (level %d)\n"), r_name + r_ptr->name, (int)r_ptr->level);
- }
-
- C_KILL(who, max_r_idx, s16b);
- angband_fclose(fff);
- (void)show_file(creature_ptr, TRUE, file_name, _("まだ生きているユニーク・モンスター", "Alive Uniques"), 0, 0);
- fd_kill(file_name);
+ unique_list_type tmp_list;
+ unique_list_type *unique_list_ptr = initialize_unique_lsit_type(&tmp_list, is_alive);
+ FILE *fff = NULL;
+ GAME_TEXT file_name[FILE_NAME_SIZE];
+ if (!open_temporary_file(&fff, file_name))
+ return;
+
+ C_MAKE(unique_list_ptr->who, max_r_idx, MONRACE_IDX);
+ for (IDX i = 1; i < max_r_idx; i++) {
+ monster_race *r_ptr = &r_info[i];
+ if (!sweep_uniques(r_ptr, unique_list_ptr->is_alive))
+ continue;
+
+ if (r_ptr->level) {
+ int lev = (r_ptr->level - 1) / 10;
+ if (lev < 10) {
+ unique_list_ptr->num_uniques[lev]++;
+ if (unique_list_ptr->max_lev < lev)
+ unique_list_ptr->max_lev = lev;
+ } else
+ unique_list_ptr->num_uniques_over100++;
+ } else
+ unique_list_ptr->num_uniques_surface++;
+
+ unique_list_ptr->who[unique_list_ptr->n++] = i;
+ }
+
+ ang_sort(unique_list_ptr->who, &unique_list_ptr->why, unique_list_ptr->n, ang_sort_comp_hook, ang_sort_swap_hook);
+ display_uniques(unique_list_ptr, fff);
+ C_KILL(unique_list_ptr->who, max_r_idx, s16b);
- my_fclose(fff);
++ angband_fclose(fff);
+ concptr title_desc
+ = unique_list_ptr->is_alive ? _("まだ生きているユニーク・モンスター", "Alive Uniques") : _("もう撃破したユニーク・モンスター", "Dead Uniques");
+ (void)show_file(creature_ptr, TRUE, file_name, title_desc, 0, 0);
+ fd_kill(file_name);
}