-#include "window/display-sub-windows.h"
-#include "core/window-redrawer.h"
+#include "window/display-sub-windows.h"
#include "flavor/flavor-describer.h"
#include "floor/cave.h"
#include "game-option/option-flags.h"
#include "game-option/text-display-options.h"
#include "grid/feature.h"
#include "inventory/inventory-describer.h"
-#include "inventory/inventory-slot-types.h"
#include "inventory/inventory-util.h"
#include "locale/japanese.h"
#include "main/sound-of-music.h"
+#include "mind/mind-explanations-table.h"
+#include "mind/mind-info.h"
+#include "mind/mind-sniper.h"
+#include "mind/mind-types.h"
#include "monster-race/monster-race.h"
-#include "monster-race/race-flags1.h"
-#include "monster/monster-flag-types.h"
-#include "monster/monster-info.h"
-#include "monster/monster-status.h"
+#include "monster/monster-describer.h"
+#include "monster/monster-description-types.h"
#include "object/item-tester-hooker.h"
#include "object/object-info.h"
-#include "object/object-mark-types.h"
+#include "player-base/player-class.h"
+#include "player-info/class-info.h"
#include "player/player-status-flags.h"
+#include "player/player-status-table.h"
#include "player/player-status.h"
-#include "spell-kind/magic-item-recharger.h"
-#include "system/baseitem-info.h"
+#include "realm/realm-names-table.h"
+#include "spell/spells-execution.h"
#include "system/floor-type-definition.h"
#include "system/grid-type-definition.h"
#include "system/item-entity.h"
#include "system/monster-entity.h"
#include "system/monster-race-info.h"
-#include "system/player-type-definition.h"
#include "system/terrain-type-definition.h"
-#include "target/target-describer.h"
#include "target/target-preparation.h"
-#include "target/target-setter.h"
-#include "target/target-types.h"
#include "term/gameterm.h"
#include "term/screen-processor.h"
-#include "term/term-color-types.h"
#include "timed-effect/player-hallucination.h"
+#include "timed-effect/player-stun.h"
#include "timed-effect/timed-effects.h"
-#include "util/bit-flags-calculator.h"
+#include "util/int-char-converter.h"
#include "view/display-lore.h"
#include "view/display-map.h"
#include "view/display-messages.h"
#include "window/main-window-equipments.h"
#include "window/main-window-util.h"
#include "world/world.h"
+#include <algorithm>
+#include <concepts>
#include <mutex>
#include <sstream>
#include <string>
}
/*!
- * @brief サブウィンドウに所持品一覧を表示する / Hack -- display inventory in sub-windows
- * @param player_ptr プレイヤーへの参照ポインタ
+ * @brief サブウィンドウの描画を行う
+ *
+ * pw_flag で指定したウィンドウフラグが設定されているサブウィンドウに対し描画を行う。
+ * 描画は display_func で指定したコールバック関数で行う。
+ *
+ * @param pw_flag 描画を行うフラグ
+ * @param display_func 描画を行う関数
*/
-void fix_inventory(PlayerType *player_ptr)
+static void display_sub_windows(SubWindowRedrawingFlag pw_flag, std::invocable auto display_func)
{
- for (int j = 0; j < 8; j++) {
- term_type *old = game_term;
- if (!angband_term[j]) {
+ auto current_term = game_term;
+
+ for (auto i = 0U; i < angband_terms.size(); ++i) {
+ auto term = angband_terms[i];
+ if (term == nullptr) {
continue;
}
- if (!(window_flag[j] & (PW_INVEN))) {
+ if (!g_window_flags[i].has(pw_flag)) {
continue;
}
- term_activate(angband_term[j]);
- display_inventory(player_ptr, *fix_item_tester);
+ term_activate(term);
+ display_func();
term_fresh();
- term_activate(old);
}
+
+ term_activate(current_term);
+}
+
+/*!
+ * @brief サブウィンドウに所持品一覧を表示する / Hack -- display inventory in sub-windows
+ * @param player_ptr プレイヤーへの参照ポインタ
+ */
+void fix_inventory(PlayerType *player_ptr)
+{
+ display_sub_windows(SubWindowRedrawingFlag::INVENTORY,
+ [player_ptr] {
+ display_inventory(player_ptr, *fix_item_tester);
+ });
}
/*!
*/
static void print_monster_line(TERM_LEN x, TERM_LEN y, MonsterEntity *m_ptr, int n_same, int n_awake)
{
- char buf[256];
+ std::string buf;
MonsterRaceId r_idx = m_ptr->ap_r_idx;
auto *r_ptr = &monraces_info[r_idx];
- term_erase(0, y, 255);
+ term_erase(0, y);
term_gotoxy(x, y);
if (!r_ptr) {
return;
}
if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
- sprintf(buf, _("%3s(覚%2d)", "%3s(%2d)"), MonsterRace(r_idx).is_bounty(true) ? " W" : " U", n_awake);
- term_addstr(-1, TERM_WHITE, buf);
+ buf = format(_("%3s(覚%2d)", "%3s(%2d)"), MonsterRace(r_idx).is_bounty(true) ? " W" : " U", n_awake);
} else {
- sprintf(buf, _("%3d(覚%2d)", "%3d(%2d)"), n_same, n_awake);
- term_addstr(-1, TERM_WHITE, buf);
+ buf = format(_("%3d(覚%2d)", "%3d(%2d)"), n_same, n_awake);
}
+ term_addstr(-1, TERM_WHITE, buf);
term_addstr(-1, TERM_WHITE, " ");
term_add_bigch(r_ptr->x_attr, r_ptr->x_char);
if (r_ptr->r_tkills && m_ptr->mflag2.has_not(MonsterConstantFlagType::KAGE)) {
- sprintf(buf, " %2d", (int)r_ptr->level);
+ buf = format(" %2d", (int)r_ptr->level);
} else {
- strcpy(buf, " ??");
+ buf = " ??";
}
term_addstr(-1, TERM_WHITE, buf);
- sprintf(buf, " %s ", r_ptr->name.data());
- term_addstr(-1, TERM_WHITE, buf);
+ term_addstr(-1, TERM_WHITE, format(" %s ", r_ptr->name.data()));
}
/*!
}
for (; line < max_lines; line++) {
- term_erase(0, line, 255);
+ term_erase(0, line);
+ }
+}
+
+static void print_pet_list_oneline(PlayerType *player_ptr, const MonsterEntity &monster, TERM_LEN x, TERM_LEN y, TERM_LEN width)
+{
+ const auto &monrace = monraces_info[monster.ap_r_idx];
+ const auto name = monster_desc(player_ptr, &monster, MD_ASSUME_VISIBLE | MD_INDEF_VISIBLE | MD_NO_OWNER);
+ const auto &[bar_color, bar_len] = monster.get_hp_bar_data();
+ const auto is_visible = monster.ml && !player_ptr->effects()->hallucination()->is_hallucinated();
+
+ term_erase(0, y);
+ if (is_visible) {
+ term_putstr(x, y, -1, TERM_WHITE, "[----------]");
+ term_putstr(x + 1, y, bar_len, bar_color, "**********");
+ }
+
+ term_gotoxy(x + 13, y);
+ term_add_bigch(monrace.x_attr, monrace.x_char);
+ term_addstr(-1, TERM_WHITE, " ");
+ term_addstr(-1, TERM_WHITE, name);
+
+ if (width >= 50) {
+ const auto location = format(" (X:%3d Y:%3d)", monster.fx, monster.fy);
+ prt(is_visible ? location : "", y, width - location.length());
+ }
+}
+
+static void print_pet_list(PlayerType *player_ptr, const std::vector<MONSTER_IDX> &pets, TERM_LEN x, TERM_LEN y, TERM_LEN width, TERM_LEN height)
+{
+ for (auto n = 0U; n < pets.size(); ++n) {
+ const auto &monster = player_ptr->current_floor_ptr->m_list[pets[n]];
+ const int line = y + n;
+
+ print_pet_list_oneline(player_ptr, monster, x, line, width);
+
+ if ((line == height - 2) && (n < pets.size() - 2)) {
+ term_erase(0, line + 1);
+ term_putstr(x, line + 1, -1, TERM_WHITE, "-- and more --");
+ break;
+ }
+ }
+
+ for (int n = pets.size(); n < height; ++n) {
+ term_erase(0, y + n);
}
}
static std::vector<MONSTER_IDX> monster_list;
std::once_flag once;
- for (int j = 0; j < 8; j++) {
- term_type *old = game_term;
- if (!angband_term[j]) {
- continue;
- }
- if (!(window_flag[j] & PW_MONSTER_LIST)) {
- continue;
- }
- if (angband_term[j]->never_fresh) {
- continue;
- }
-
- term_activate(angband_term[j]);
- int w, h;
- term_get_size(&w, &h);
- std::call_once(once, target_sensing_monsters_prepare, player_ptr, monster_list);
- print_monster_list(player_ptr->current_floor_ptr, monster_list, 0, 0, h);
- term_fresh();
- term_activate(old);
- }
+ display_sub_windows(SubWindowRedrawingFlag::SIGHT_MONSTERS,
+ [player_ptr, &once] {
+ const auto &[wid, hgt] = term_get_size();
+ std::call_once(once, target_sensing_monsters_prepare, player_ptr, monster_list);
+ print_monster_list(player_ptr->current_floor_ptr, monster_list, 0, 0, hgt);
+ });
if (use_music && has_monster_music) {
std::call_once(once, target_sensing_monsters_prepare, player_ptr, monster_list);
}
/*!
+ * @brief 視界内のペットのリストをサブウィンドウに表示する
+ */
+void fix_pet_list(PlayerType *player_ptr)
+{
+ display_sub_windows(SubWindowRedrawingFlag::PETS,
+ [player_ptr] {
+ const auto &[wid, hgt] = term_get_size();
+ const auto pets = target_pets_prepare(player_ptr);
+ print_pet_list(player_ptr, pets, 0, 0, wid, hgt);
+ });
+}
+
+/*!
* @brief 装備アイテム一覧を表示する /
* Choice window "shadow" of the "show_equip()" function
*/
return;
}
- TERM_LEN wid, hgt;
- term_get_size(&wid, &hgt);
-
- TERM_COLOR attr = TERM_WHITE;
- char tmp_val[80];
- GAME_TEXT o_name[MAX_NLEN];
+ const auto &[wid, hgt] = term_get_size();
+ byte attr = TERM_WHITE;
for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
int cur_row = i - INVEN_MAIN_HAND;
if (cur_row >= hgt) {
auto o_ptr = &player_ptr->inventory_list[i];
auto do_disp = player_ptr->select_ring_slot ? is_ring_slot(i) : item_tester.okay(o_ptr);
- strcpy(tmp_val, " ");
+ std::string tmp_val = " ";
if (do_disp) {
tmp_val[0] = index_to_label(i);
}
int cur_col = 3;
- term_erase(cur_col, cur_row, 255);
+ term_erase(cur_col, cur_row);
term_putstr(0, cur_row, cur_col, TERM_WHITE, tmp_val);
- if ((((i == INVEN_MAIN_HAND) && can_attack_with_sub_hand(player_ptr)) || ((i == INVEN_SUB_HAND) && can_attack_with_main_hand(player_ptr))) && has_two_handed_weapons(player_ptr)) {
- strcpy(o_name, _("(武器を両手持ち)", "(wielding with two-hands)"));
+ std::string item_name;
+ auto is_two_handed = (i == INVEN_MAIN_HAND) && can_attack_with_sub_hand(player_ptr);
+ is_two_handed |= (i == INVEN_SUB_HAND) && can_attack_with_main_hand(player_ptr);
+ if (is_two_handed && has_two_handed_weapons(player_ptr)) {
+ item_name = _("(武器を両手持ち)", "(wielding with two-hands)");
attr = TERM_WHITE;
} else {
- describe_flavor(player_ptr, o_name, o_ptr, 0);
- attr = tval_to_attr[enum2i(o_ptr->tval) % 128];
+ item_name = describe_flavor(player_ptr, o_ptr, 0);
+ attr = tval_to_attr[enum2i(o_ptr->bi_key.tval()) % 128];
}
- int n = strlen(o_name);
+ int n = item_name.length();
if (o_ptr->timeout) {
attr = TERM_L_DARK;
}
cur_col += 2;
}
- term_putstr(cur_col, cur_row, n, attr, o_name);
+ term_putstr(cur_col, cur_row, n, attr, item_name);
if (show_weights) {
int wgt = o_ptr->weight * o_ptr->number;
- sprintf(tmp_val, _("%3d.%1d kg", "%3d.%1d lb"), _(lb_to_kg_integer(wgt), wgt / 10), _(lb_to_kg_fraction(wgt), wgt % 10));
+ tmp_val = format(_("%3d.%1d kg", "%3d.%1d lb"), _(lb_to_kg_integer(wgt), wgt / 10), _(lb_to_kg_fraction(wgt), wgt % 10));
prt(tmp_val, cur_row, wid - (show_labels ? 28 : 9));
}
}
for (int i = INVEN_TOTAL - INVEN_MAIN_HAND; i < hgt; i++) {
- term_erase(0, i, 255);
+ term_erase(0, i);
}
}
*/
void fix_equip(PlayerType *player_ptr)
{
- for (int j = 0; j < 8; j++) {
- term_type *old = game_term;
- if (!angband_term[j]) {
- continue;
- }
- if (!(window_flag[j] & (PW_EQUIP))) {
- continue;
- }
-
- term_activate(angband_term[j]);
- display_equipment(player_ptr, *fix_item_tester);
- term_fresh();
- term_activate(old);
- }
+ display_sub_windows(SubWindowRedrawingFlag::EQUIPMENT,
+ [player_ptr] {
+ display_equipment(player_ptr, *fix_item_tester);
+ });
}
/*!
*/
void fix_player(PlayerType *player_ptr)
{
- for (int j = 0; j < 8; j++) {
- term_type *old = game_term;
- if (!angband_term[j]) {
- continue;
- }
-
- if (!(window_flag[j] & (PW_PLAYER))) {
- continue;
- }
-
- term_activate(angband_term[j]);
- update_playtime();
- (void)display_player(player_ptr, 0);
- term_fresh();
- term_activate(old);
- }
+ update_playtime();
+ display_sub_windows(SubWindowRedrawingFlag::PLAYER,
+ [player_ptr] {
+ display_player(player_ptr, 0);
+ });
}
/*!
*/
void fix_message(void)
{
- for (int j = 0; j < 8; j++) {
- term_type *old = game_term;
- if (!angband_term[j]) {
- continue;
- }
-
- if (!(window_flag[j] & (PW_MESSAGE))) {
- continue;
- }
-
- term_activate(angband_term[j]);
- TERM_LEN w, h;
- term_get_size(&w, &h);
- for (int i = 0; i < h; i++) {
- term_putstr(0, (h - 1) - i, -1, (byte)((i < now_message) ? TERM_WHITE : TERM_SLATE), message_str((int16_t)i));
- TERM_LEN x, y;
- term_locate(&x, &y);
- term_erase(x, y, 255);
- }
-
- term_fresh();
- term_activate(old);
- }
+ display_sub_windows(SubWindowRedrawingFlag::MESSAGE,
+ [] {
+ const auto &[wid, hgt] = term_get_size();
+ for (short i = 0; i < hgt; i++) {
+ term_putstr(0, (hgt - 1) - i, -1, (byte)((i < now_message) ? TERM_WHITE : TERM_SLATE), *message_str(i));
+ TERM_LEN x, y;
+ term_locate(&x, &y);
+ term_erase(x, y);
+ }
+ });
}
/*!
*/
void fix_overhead(PlayerType *player_ptr)
{
- for (int j = 0; j < 8; j++) {
- term_type *old = game_term;
- TERM_LEN wid, hgt;
- if (!angband_term[j]) {
- continue;
- }
-
- if (!(window_flag[j] & (PW_OVERHEAD))) {
- continue;
- }
-
- term_activate(angband_term[j]);
- term_get_size(&wid, &hgt);
- if (wid > COL_MAP + 2 && hgt > ROW_MAP + 2) {
- int cy, cx;
- display_map(player_ptr, &cy, &cx);
- term_fresh();
- }
-
- term_activate(old);
- }
+ display_sub_windows(SubWindowRedrawingFlag::OVERHEAD,
+ [player_ptr] {
+ const auto &[wid, hgt] = term_get_size();
+ if (wid > COL_MAP + 2 && hgt > ROW_MAP + 2) {
+ int cy, cx;
+ display_map(player_ptr, &cy, &cx);
+ }
+ });
}
/*!
*/
void fix_dungeon(PlayerType *player_ptr)
{
- for (int j = 0; j < 8; j++) {
- term_type *old = game_term;
- if (!angband_term[j]) {
- continue;
- }
-
- if (!(window_flag[j] & (PW_DUNGEON))) {
- continue;
- }
-
- term_activate(angband_term[j]);
- display_dungeon(player_ptr);
- term_fresh();
- term_activate(old);
- }
+ display_sub_windows(SubWindowRedrawingFlag::DUNGEON,
+ [player_ptr] {
+ display_dungeon(player_ptr);
+ });
}
/*!
*/
void fix_monster(PlayerType *player_ptr)
{
- for (int j = 0; j < 8; j++) {
- term_type *old = game_term;
- if (!angband_term[j]) {
- continue;
- }
-
- if (!(window_flag[j] & (PW_MONSTER))) {
- continue;
- }
-
- term_activate(angband_term[j]);
- if (MonsterRace(player_ptr->monster_race_idx).is_valid()) {
- display_roff(player_ptr);
- }
-
- term_fresh();
- term_activate(old);
+ if (!MonsterRace(player_ptr->monster_race_idx).is_valid()) {
+ return;
}
+ display_sub_windows(SubWindowRedrawingFlag::MONSTER_LORE,
+ [player_ptr] {
+ display_roff(player_ptr);
+ });
}
/*!
*/
void fix_object(PlayerType *player_ptr)
{
- for (int j = 0; j < 8; j++) {
- term_type *old = game_term;
- if (!angband_term[j]) {
- continue;
- }
-
- if (!(window_flag[j] & (PW_OBJECT))) {
- continue;
- }
-
- term_activate(angband_term[j]);
- if (player_ptr->baseitem_info_idx) {
- display_koff(player_ptr, player_ptr->baseitem_info_idx);
- }
-
- term_fresh();
- term_activate(old);
- }
+ display_sub_windows(SubWindowRedrawingFlag::ITEM_KNOWLEDGE,
+ [player_ptr] {
+ display_koff(player_ptr);
+ });
}
/*!
*/
static void display_floor_item_list(PlayerType *player_ptr, const int y, const int x)
{
- // Term の行数を取得。
- TERM_LEN term_h;
- {
- TERM_LEN term_w;
- term_get_size(&term_w, &term_h);
- }
- if (term_h <= 0) {
+ const auto &[wid, hgt] = term_get_size();
+ if (hgt <= 0) {
return;
}
auto *floor_ptr = player_ptr->current_floor_ptr;
const auto *g_ptr = &floor_ptr->grid_array[y][x];
- char line[1024];
+ std::string line;
// 先頭行を書く。
auto is_hallucinated = player_ptr->effects()->hallucination()->is_hallucinated();
if (player_bold(player_ptr, y, x)) {
- sprintf(line, _("(X:%03d Y:%03d) あなたの足元のアイテム一覧", "Items at (%03d,%03d) under you"), x, y);
+ line = format(_("(X:%03d Y:%03d) あなたの足元のアイテム一覧", "Items at (%03d,%03d) under you"), x, y);
} else if (const auto *m_ptr = monster_on_floor_items(floor_ptr, g_ptr); m_ptr != nullptr) {
if (is_hallucinated) {
- sprintf(line, _("(X:%03d Y:%03d) 何か奇妙な物の足元の発見済みアイテム一覧", "Found items at (%03d,%03d) under something strange"), x, y);
+ line = format(_("(X:%03d Y:%03d) 何か奇妙な物の足元の発見済みアイテム一覧", "Found items at (%03d,%03d) under something strange"), x, y);
} else {
const MonsterRaceInfo *const r_ptr = &monraces_info[m_ptr->ap_r_idx];
- sprintf(line, _("(X:%03d Y:%03d) %sの足元の発見済みアイテム一覧", "Found items at (%03d,%03d) under %s"), x, y, r_ptr->name.data());
+ line = format(_("(X:%03d Y:%03d) %sの足元の発見済みアイテム一覧", "Found items at (%03d,%03d) under %s"), x, y, r_ptr->name.data());
}
} else {
const TerrainType *const f_ptr = &terrains_info[g_ptr->feat];
concptr fn = f_ptr->name.data();
- char buf[512];
+ std::string buf;
if (f_ptr->flags.has(TerrainCharacteristics::STORE) || (f_ptr->flags.has(TerrainCharacteristics::BLDG) && !floor_ptr->inside_arena)) {
- sprintf(buf, _("%sの入口", "on the entrance of %s"), fn);
+ buf = format(_("%sの入口", "on the entrance of %s"), fn);
} else if (f_ptr->flags.has(TerrainCharacteristics::WALL)) {
- sprintf(buf, _("%sの中", "in %s"), fn);
+ buf = format(_("%sの中", "in %s"), fn);
} else {
- sprintf(buf, _("%s", "on %s"), fn);
+ buf = format(_("%s", "on %s"), fn);
}
- sprintf(line, _("(X:%03d Y:%03d) %sの上の発見済みアイテム一覧", "Found items at (X:%03d Y:%03d) %s"), x, y, buf);
+ line = format(_("(X:%03d Y:%03d) %sの上の発見済みアイテム一覧", "Found items at (X:%03d Y:%03d) %s"), x, y, buf.data());
}
term_addstr(-1, TERM_WHITE, line);
// (y,x) のアイテムを1行に1個ずつ書く。
TERM_LEN term_y = 1;
for (const auto o_idx : g_ptr->o_idx_list) {
- ItemEntity *const o_ptr = &floor_ptr->o_list[o_idx];
-
- // 未発見アイテムおよび金は対象外。
- if (o_ptr->marked.has_not(OmType::FOUND) || o_ptr->tval == ItemKindType::GOLD) {
+ auto *const o_ptr = &floor_ptr->o_list[o_idx];
+ const auto tval = o_ptr->bi_key.tval();
+ if (o_ptr->marked.has_not(OmType::FOUND) || tval == ItemKindType::GOLD) {
continue;
}
// 途中で行数が足りなくなったら最終行にその旨追記して終了。
- if (term_y >= term_h) {
+ if (term_y >= hgt) {
term_addstr(-1, TERM_WHITE, "-- more --");
break;
}
if (is_hallucinated) {
term_addstr(-1, TERM_WHITE, _("何か奇妙な物", "something strange"));
} else {
- describe_flavor(player_ptr, line, o_ptr, 0);
- TERM_COLOR attr = tval_to_attr[enum2i(o_ptr->tval) % 128];
- term_addstr(-1, attr, line);
+ const auto item_name = describe_flavor(player_ptr, o_ptr, 0);
+ TERM_COLOR attr = tval_to_attr[enum2i(tval) % 128];
+ term_addstr(-1, attr, item_name);
}
++term_y;
*/
void fix_floor_item_list(PlayerType *player_ptr, const int y, const int x)
{
- for (int j = 0; j < 8; j++) {
- if (!angband_term[j]) {
- continue;
- }
- if (angband_term[j]->never_fresh) {
- continue;
- }
- if (!(window_flag[j] & PW_FLOOR_ITEM_LIST)) {
- continue;
- }
-
- term_type *old = game_term;
- term_activate(angband_term[j]);
-
- display_floor_item_list(player_ptr, y, x);
- term_fresh();
-
- term_activate(old);
- }
+ display_sub_windows(SubWindowRedrawingFlag::FLOOR_ITEMS,
+ [player_ptr, y, x] {
+ display_floor_item_list(player_ptr, y, x);
+ });
}
/*!
*/
static void display_found_item_list(PlayerType *player_ptr)
{
- // Term の行数を取得。
- TERM_LEN term_h;
- TERM_LEN term_w;
- term_get_size(&term_w, &term_h);
-
- if (term_h <= 0) {
+ const auto &[wid, hgt] = term_get_size();
+ if (hgt <= 0) {
return;
}
// ItemKindTypeがGOLD
std::vector<ItemEntity *> found_item_list;
for (auto &item : floor_ptr->o_list) {
- auto item_entity_ptr = &item;
- if (item_entity_ptr->bi_id > 0 && item_entity_ptr->marked.has(OmType::FOUND) && item_entity_ptr->tval != ItemKindType::GOLD) {
- found_item_list.push_back(item_entity_ptr);
+ const auto is_item_to_display =
+ item.is_valid() && (item.number > 0) &&
+ item.marked.has(OmType::FOUND) && (item.bi_key.tval() != ItemKindType::GOLD);
+
+ if (is_item_to_display) {
+ found_item_list.push_back(&item);
}
}
TERM_LEN term_y = 1;
for (auto item : found_item_list) {
// 途中で行数が足りなくなったら終了。
- if (term_y >= term_h) {
+ if (term_y >= hgt) {
break;
}
// アイテムシンボル表示
const auto symbol_code = item->get_symbol();
- const std::string symbol = format(" %c ", symbol_code);
+ const auto symbol = format(" %c ", symbol_code);
const auto color_code_for_symbol = item->get_color();
- term_addstr(-1, color_code_for_symbol, symbol.data());
+ term_addstr(-1, color_code_for_symbol, symbol);
- // アイテム名表示
- char temp[512];
- describe_flavor(player_ptr, temp, item, 0);
- const std::string item_description(temp);
- const auto color_code_for_item = tval_to_attr[enum2i(item->tval) % 128];
- term_addstr(-1, color_code_for_item, item_description.data());
+ const auto item_name = describe_flavor(player_ptr, item, 0);
+ const auto color_code_for_item = tval_to_attr[enum2i(item->bi_key.tval()) % 128];
+ term_addstr(-1, color_code_for_item, item_name);
// アイテム座標表示
- const std::string item_location = format("(X:%3d Y:%3d)", item->ix, item->iy);
- prt(item_location.data(), term_y, term_w - item_location.length() - 1);
+ const auto item_location = format("(X:%3d Y:%3d)", item->ix, item->iy);
+ prt(item_location, term_y, wid - item_location.length() - 1);
++term_y;
}
*/
void fix_found_item_list(PlayerType *player_ptr)
{
- for (int j = 0; j < 8; j++) {
- if (!angband_term[j]) {
- continue;
- }
- if (angband_term[j]->never_fresh) {
- continue;
+ display_sub_windows(SubWindowRedrawingFlag::FOUND_ITEMS,
+ [player_ptr] {
+ display_found_item_list(player_ptr);
+ });
+}
+
+/*!
+ * @brief プレイヤーの全既知呪文を表示する / Display all known spells in a window
+ * @param player_ptr プレイヤーへの参照ポインタ
+ * @details
+ * Need to analyze size of the window.
+ * Need more color coding.
+ */
+static void display_spell_list(PlayerType *player_ptr)
+{
+ TERM_LEN y, x;
+ int m[9];
+ const magic_type *s_ptr;
+ GAME_TEXT name[MAX_NLEN];
+
+ clear_from(0);
+
+ PlayerClass pc(player_ptr);
+ if (pc.is_every_magic()) {
+ return;
+ }
+
+ if (pc.equals(PlayerClassType::SNIPER)) {
+ display_snipe_list(player_ptr);
+ return;
+ }
+
+ if (pc.has_listed_magics()) {
+ PERCENTAGE minfail = 0;
+ PLAYER_LEVEL plev = player_ptr->lev;
+ PERCENTAGE chance = 0;
+ mind_type spell;
+ MindKindType use_mind;
+ bool use_hp = false;
+
+ y = 1;
+ x = 1;
+
+ prt("", y, x);
+ put_str(_("名前", "Name"), y, x + 5);
+ put_str(_("Lv MP 失率 効果", "Lv Mana Fail Info"), y, x + 35);
+
+ switch (player_ptr->pclass) {
+ case PlayerClassType::MINDCRAFTER:
+ use_mind = MindKindType::MINDCRAFTER;
+ break;
+ case PlayerClassType::FORCETRAINER:
+ use_mind = MindKindType::KI;
+ break;
+ case PlayerClassType::BERSERKER:
+ use_mind = MindKindType::BERSERKER;
+ use_hp = true;
+ break;
+ case PlayerClassType::MIRROR_MASTER:
+ use_mind = MindKindType::MIRROR_MASTER;
+ break;
+ case PlayerClassType::NINJA:
+ use_mind = MindKindType::NINJUTSU;
+ use_hp = true;
+ break;
+ case PlayerClassType::ELEMENTALIST:
+ use_mind = MindKindType::ELEMENTAL;
+ break;
+ default:
+ use_mind = MindKindType::MINDCRAFTER;
+ break;
}
- if (none_bits(window_flag[j], PW_FOUND_ITEM_LIST)) {
- continue;
+
+ for (int i = 0; i < MAX_MIND_POWERS; i++) {
+ byte a = TERM_WHITE;
+ spell = mind_powers[static_cast<int>(use_mind)].info[i];
+ if (spell.min_lev > plev) {
+ break;
+ }
+
+ chance = spell.fail;
+ chance -= 3 * (player_ptr->lev - spell.min_lev);
+ chance -= 3 * (adj_mag_stat[player_ptr->stat_index[mp_ptr->spell_stat]] - 1);
+ if (!use_hp) {
+ if (spell.mana_cost > player_ptr->csp) {
+ chance += 5 * (spell.mana_cost - player_ptr->csp);
+ a = TERM_ORANGE;
+ }
+ } else {
+ if (spell.mana_cost > player_ptr->chp) {
+ chance += 100;
+ a = TERM_RED;
+ }
+ }
+
+ minfail = adj_mag_fail[player_ptr->stat_index[mp_ptr->spell_stat]];
+ if (chance < minfail) {
+ chance = minfail;
+ }
+
+ auto player_stun = player_ptr->effects()->stun();
+ chance += player_stun->get_magic_chance_penalty();
+ if (chance > 95) {
+ chance = 95;
+ }
+
+ const auto comment = mindcraft_info(player_ptr, use_mind, i);
+ constexpr auto fmt = " %c) %-30s%2d %4d %3d%%%s";
+ term_putstr(x, y + i + 1, -1, a, format(fmt, I2A(i), spell.name, spell.min_lev, spell.mana_cost, chance, comment.data()));
}
- term_type *old = game_term;
- term_activate(angband_term[j]);
+ return;
+ }
- display_found_item_list(player_ptr);
- term_fresh();
+ if (REALM_NONE == player_ptr->realm1) {
+ return;
+ }
+
+ for (int j = 0; j < ((player_ptr->realm2 > REALM_NONE) ? 2 : 1); j++) {
+ m[j] = 0;
+ y = (j < 3) ? 0 : (m[j - 3] + 2);
+ x = 27 * (j % 3);
+ int n = 0;
+ for (int i = 0; i < 32; i++) {
+ byte a = TERM_WHITE;
- term_activate(old);
+ if (!is_magic((j < 1) ? player_ptr->realm1 : player_ptr->realm2)) {
+ s_ptr = &technic_info[((j < 1) ? player_ptr->realm1 : player_ptr->realm2) - MIN_TECHNIC][i % 32];
+ } else {
+ s_ptr = &mp_ptr->info[((j < 1) ? player_ptr->realm1 : player_ptr->realm2) - 1][i % 32];
+ }
+
+ const auto realm = (j < 1) ? player_ptr->realm1 : player_ptr->realm2;
+ const auto spell_name = exe_spell(player_ptr, realm, i % 32, SpellProcessType::NAME);
+ strcpy(name, spell_name->data());
+
+ if (s_ptr->slevel >= 99) {
+ strcpy(name, _("(判読不能)", "(illegible)"));
+ a = TERM_L_DARK;
+ } else if ((j < 1) ? ((player_ptr->spell_forgotten1 & (1UL << i))) : ((player_ptr->spell_forgotten2 & (1UL << (i % 32))))) {
+ a = TERM_ORANGE;
+ } else if (!((j < 1) ? (player_ptr->spell_learned1 & (1UL << i)) : (player_ptr->spell_learned2 & (1UL << (i % 32))))) {
+ a = TERM_RED;
+ } else if (!((j < 1) ? (player_ptr->spell_worked1 & (1UL << i)) : (player_ptr->spell_worked2 & (1UL << (i % 32))))) {
+ a = TERM_YELLOW;
+ }
+
+ m[j] = y + n;
+ term_putstr(x, m[j], -1, a, format("%c/%c) %-20.20s", I2A(n / 8), I2A(n % 8), name));
+ n++;
+ }
}
}
/*!
- * @brief サブウィンドウに所持品、装備品リストの表示を行う /
- * Flip "inven" and "equip" in any sub-windows
+ * @brief 現在の習得済魔法をサブウィンドウに表示する /
+ * @param player_ptr プレイヤーへの参照ポインタ
+ * Hack -- display spells in sub-windows
+ */
+void fix_spell(PlayerType *player_ptr)
+{
+ display_sub_windows(SubWindowRedrawingFlag::SPELL,
+ [player_ptr] {
+ display_spell_list(player_ptr);
+ });
+}
+
+/*!
+ * @brief サブウィンドウに所持品、装備品リストの表示を行う
*/
-void toggle_inventory_equipment(PlayerType *player_ptr)
+void toggle_inventory_equipment()
{
- for (int j = 0; j < 8; j++) {
- if (!angband_term[j]) {
+ auto &rfu = RedrawingFlagsUpdater::get_instance();
+ for (auto i = 0U; i < angband_terms.size(); ++i) {
+ if (!angband_terms[i]) {
continue;
}
- if (window_flag[j] & (PW_INVEN)) {
- window_flag[j] &= ~(PW_INVEN);
- window_flag[j] |= (PW_EQUIP);
- player_ptr->window_flags |= (PW_EQUIP);
+ if (g_window_flags[i].has(SubWindowRedrawingFlag::INVENTORY)) {
+ g_window_flags[i].reset(SubWindowRedrawingFlag::INVENTORY);
+ g_window_flags[i].set(SubWindowRedrawingFlag::EQUIPMENT);
+ rfu.set_flag(SubWindowRedrawingFlag::EQUIPMENT);
continue;
}
- if (window_flag[j] & PW_EQUIP) {
- window_flag[j] &= ~(PW_EQUIP);
- window_flag[j] |= PW_INVEN;
- player_ptr->window_flags |= PW_INVEN;
+ if (g_window_flags[i].has(SubWindowRedrawingFlag::EQUIPMENT)) {
+ g_window_flags[i].reset(SubWindowRedrawingFlag::EQUIPMENT);
+ g_window_flags[i].set(SubWindowRedrawingFlag::INVENTORY);
+ rfu.set_flag(SubWindowRedrawingFlag::INVENTORY);
}
}
}