1 #include "window/display-sub-windows.h"
2 #include "core/window-redrawer.h"
3 #include "flavor/flavor-describer.h"
4 #include "floor/cave.h"
5 #include "game-option/option-flags.h"
6 #include "game-option/special-options.h"
7 #include "game-option/text-display-options.h"
8 #include "grid/feature.h"
9 #include "inventory/inventory-describer.h"
10 #include "inventory/inventory-slot-types.h"
11 #include "inventory/inventory-util.h"
12 #include "locale/japanese.h"
13 #include "main/sound-of-music.h"
14 #include "mind/mind-explanations-table.h"
15 #include "mind/mind-info.h"
16 #include "mind/mind-sniper.h"
17 #include "mind/mind-types.h"
18 #include "monster-race/monster-race.h"
19 #include "monster-race/race-flags1.h"
20 #include "monster/monster-flag-types.h"
21 #include "monster/monster-info.h"
22 #include "monster/monster-status.h"
23 #include "object/item-tester-hooker.h"
24 #include "object/object-info.h"
25 #include "object/object-mark-types.h"
26 #include "player-base/player-class.h"
27 #include "player-info/class-info.h"
28 #include "player/player-status-flags.h"
29 #include "player/player-status-table.h"
30 #include "player/player-status.h"
31 #include "realm/realm-names-table.h"
32 #include "spell-kind/magic-item-recharger.h"
33 #include "spell/spells-execution.h"
34 #include "spell/technic-info-table.h"
35 #include "system/baseitem-info.h"
36 #include "system/floor-type-definition.h"
37 #include "system/grid-type-definition.h"
38 #include "system/item-entity.h"
39 #include "system/monster-entity.h"
40 #include "system/monster-race-info.h"
41 #include "system/player-type-definition.h"
42 #include "system/terrain-type-definition.h"
43 #include "target/target-describer.h"
44 #include "target/target-preparation.h"
45 #include "target/target-setter.h"
46 #include "target/target-types.h"
47 #include "term/gameterm.h"
48 #include "term/screen-processor.h"
49 #include "term/term-color-types.h"
50 #include "term/z-form.h"
51 #include "timed-effect/player-hallucination.h"
52 #include "timed-effect/player-stun.h"
53 #include "timed-effect/timed-effects.h"
54 #include "util/bit-flags-calculator.h"
55 #include "util/int-char-converter.h"
56 #include "view/display-lore.h"
57 #include "view/display-map.h"
58 #include "view/display-messages.h"
59 #include "view/display-player.h"
60 #include "view/object-describer.h"
61 #include "window/main-window-equipments.h"
62 #include "window/main-window-util.h"
63 #include "world/world.h"
69 #include <util/object-sort.h>
71 /*! サブウィンドウ表示用の ItemTester オブジェクト */
72 static std::unique_ptr<ItemTester> fix_item_tester = std::make_unique<AllMatchItemTester>();
74 FixItemTesterSetter::FixItemTesterSetter(const ItemTester &item_tester)
76 fix_item_tester = item_tester.clone();
79 FixItemTesterSetter::~FixItemTesterSetter()
81 fix_item_tester = std::make_unique<AllMatchItemTester>();
85 * @brief サブウィンドウの描画を行う
87 * pw_flag で指定したウィンドウフラグが設定されているサブウィンドウに対し描画を行う。
88 * 描画は display_func で指定したコールバック関数で行う。
90 * @param pw_flag 描画を行うフラグ
91 * @param display_func 描画を行う関数
93 static void display_sub_windows(window_redraw_type pw_flag, std::invocable auto display_func)
95 auto current_term = game_term;
97 for (auto i = 0U; i < angband_terms.size(); ++i) {
98 auto term = angband_terms[i];
99 if (term == nullptr) {
103 if (none_bits(window_flag[i], pw_flag)) {
112 term_activate(current_term);
116 * @brief サブウィンドウに所持品一覧を表示する / Hack -- display inventory in sub-windows
117 * @param player_ptr プレイヤーへの参照ポインタ
119 void fix_inventory(PlayerType *player_ptr)
121 display_sub_windows(PW_INVENTORY,
123 display_inventory(player_ptr, *fix_item_tester);
128 * @brief モンスターの現在数を一行で表現する / Print monster info in line
131 * @param m_ptr 思い出を表示するモンスター情報の参照ポインタ
132 * @param n_same モンスター数の現在数
133 * @param n_awake 起きている数
137 * nnn : number or unique(U) or wanted unique(W)
138 * X : symbol of monster
139 * LV : monster lv if known
140 * name: name of monster
143 static void print_monster_line(TERM_LEN x, TERM_LEN y, MonsterEntity *m_ptr, int n_same, int n_awake)
146 MonsterRaceId r_idx = m_ptr->ap_r_idx;
147 auto *r_ptr = &monraces_info[r_idx];
149 term_erase(0, y, 255);
154 if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
155 buf = format(_("%3s(覚%2d)", "%3s(%2d)"), MonsterRace(r_idx).is_bounty(true) ? " W" : " U", n_awake);
157 buf = format(_("%3d(覚%2d)", "%3d(%2d)"), n_same, n_awake);
159 term_addstr(-1, TERM_WHITE, buf);
161 term_addstr(-1, TERM_WHITE, " ");
162 term_add_bigch(r_ptr->x_attr, r_ptr->x_char);
164 if (r_ptr->r_tkills && m_ptr->mflag2.has_not(MonsterConstantFlagType::KAGE)) {
165 buf = format(" %2d", (int)r_ptr->level);
170 term_addstr(-1, TERM_WHITE, buf);
172 term_addstr(-1, TERM_WHITE, format(" %s ", r_ptr->name.data()));
176 * @brief モンスターの出現リストを表示する / Print monster info in line
179 * @param max_lines 最大何行描画するか
181 void print_monster_list(FloorType *floor_ptr, const std::vector<MONSTER_IDX> &monster_list, TERM_LEN x, TERM_LEN y, TERM_LEN max_lines)
185 MonsterEntity *monster_entity;
186 int visible_count; // 現在数
187 int awake_count; // 起きている数
191 std::vector<info> monster_list_info;
194 for (auto monster_index : monster_list) {
195 auto m_ptr = &floor_ptr->m_list[monster_index];
197 if (m_ptr->is_pet()) {
200 if (!MonsterRace(m_ptr->r_idx).is_valid()) {
204 // ソート済みなので同じモンスターは連続する.これを利用して同じモンスターをカウント,まとめて表示する.
205 if (monster_list_info.empty() || (monster_list_info.back().monster_entity->ap_r_idx != m_ptr->ap_r_idx)) {
206 monster_list_info.push_back({ m_ptr, 0, 0 });
210 monster_list_info.back().visible_count++;
213 if (!m_ptr->is_asleep()) {
214 monster_list_info.back().awake_count++;
219 for (const auto &info : monster_list_info) {
220 print_monster_line(x, line++, info.monster_entity, info.visible_count, info.awake_count);
223 if (line - y == max_lines) {
224 // 行数が足りなかった場合、最終行にその旨表示。
225 term_addstr(-1, TERM_WHITE, "-- and more --");
230 for (; line < max_lines; line++) {
231 term_erase(0, line, 255);
236 * @brief 出現中モンスターのリストをサブウィンドウに表示する / Hack -- display monster list in sub-windows
237 * @param player_ptr プレイヤーへの参照ポインタ
239 void fix_monster_list(PlayerType *player_ptr)
241 static std::vector<MONSTER_IDX> monster_list;
244 display_sub_windows(PW_SIGHT_MONSTERS,
245 [player_ptr, &once] {
247 term_get_size(&w, &h);
248 std::call_once(once, target_sensing_monsters_prepare, player_ptr, monster_list);
249 print_monster_list(player_ptr->current_floor_ptr, monster_list, 0, 0, h);
252 if (use_music && has_monster_music) {
253 std::call_once(once, target_sensing_monsters_prepare, player_ptr, monster_list);
254 select_monster_music(player_ptr, monster_list);
259 * @brief 装備アイテム一覧を表示する /
260 * Choice window "shadow" of the "show_equip()" function
262 static void display_equipment(PlayerType *player_ptr, const ItemTester &item_tester)
264 if (!player_ptr || !player_ptr->inventory_list) {
269 term_get_size(&wid, &hgt);
270 byte attr = TERM_WHITE;
271 for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
272 int cur_row = i - INVEN_MAIN_HAND;
273 if (cur_row >= hgt) {
277 auto o_ptr = &player_ptr->inventory_list[i];
278 auto do_disp = player_ptr->select_ring_slot ? is_ring_slot(i) : item_tester.okay(o_ptr);
279 std::string tmp_val = " ";
282 tmp_val[0] = index_to_label(i);
287 term_erase(cur_col, cur_row, 255);
288 term_putstr(0, cur_row, cur_col, TERM_WHITE, tmp_val);
290 std::string item_name;
291 auto is_two_handed = (i == INVEN_MAIN_HAND) && can_attack_with_sub_hand(player_ptr);
292 is_two_handed |= (i == INVEN_SUB_HAND) && can_attack_with_main_hand(player_ptr);
293 if (is_two_handed && has_two_handed_weapons(player_ptr)) {
294 item_name = _("(武器を両手持ち)", "(wielding with two-hands)");
297 item_name = describe_flavor(player_ptr, o_ptr, 0);
298 attr = tval_to_attr[enum2i(o_ptr->bi_key.tval()) % 128];
301 int n = item_name.length();
302 if (o_ptr->timeout) {
306 if (show_item_graph) {
307 const auto a = o_ptr->get_color();
308 const auto c = o_ptr->get_symbol();
309 term_queue_bigchar(cur_col, cur_row, a, c, 0, 0);
317 term_putstr(cur_col, cur_row, n, attr, item_name);
319 int wgt = o_ptr->weight * o_ptr->number;
320 tmp_val = format(_("%3d.%1d kg", "%3d.%1d lb"), _(lb_to_kg_integer(wgt), wgt / 10), _(lb_to_kg_fraction(wgt), wgt % 10));
321 prt(tmp_val, cur_row, wid - (show_labels ? 28 : 9));
325 term_putstr(wid - 20, cur_row, -1, TERM_WHITE, " <-- ");
326 prt(mention_use(player_ptr, i), cur_row, wid - 15);
330 for (int i = INVEN_TOTAL - INVEN_MAIN_HAND; i < hgt; i++) {
331 term_erase(0, i, 255);
336 * @brief 現在の装備品をサブウィンドウに表示する /
337 * Hack -- display equipment in sub-windows
338 * @param player_ptr プレイヤーへの参照ポインタ
340 void fix_equip(PlayerType *player_ptr)
342 display_sub_windows(PW_EQUIPMENT,
344 display_equipment(player_ptr, *fix_item_tester);
349 * @brief 現在のプレイヤーステータスをサブウィンドウに表示する /
350 * @param player_ptr プレイヤーへの参照ポインタ
351 * Hack -- display character in sub-windows
353 void fix_player(PlayerType *player_ptr)
356 display_sub_windows(PW_PLAYER,
358 display_player(player_ptr, 0);
363 * @brief ゲームメッセージ履歴をサブウィンドウに表示する /
364 * Hack -- display recent messages in sub-windows
365 * Adjust for width and split messages
367 void fix_message(void)
369 display_sub_windows(PW_MESSAGE,
372 term_get_size(&w, &h);
373 for (int i = 0; i < h; i++) {
374 term_putstr(0, (h - 1) - i, -1, (byte)((i < now_message) ? TERM_WHITE : TERM_SLATE), message_str((int16_t)i));
377 term_erase(x, y, 255);
383 * @brief 簡易マップをサブウィンドウに表示する /
384 * Hack -- display overhead view in sub-windows
385 * Adjust for width and split messages
386 * @param player_ptr プレイヤーへの参照ポインタ
388 * Note that the "player" symbol does NOT appear on the map.
390 void fix_overhead(PlayerType *player_ptr)
392 display_sub_windows(PW_OVERHEAD,
395 term_get_size(&wid, &hgt);
396 if (wid > COL_MAP + 2 && hgt > ROW_MAP + 2) {
398 display_map(player_ptr, &cy, &cx);
404 * @brief 自分の周辺の地形をTermに表示する
405 * @param プレイヤー情報への参照ポインタ
407 static void display_dungeon(PlayerType *player_ptr)
412 for (TERM_LEN x = player_ptr->x - game_term->wid / 2 + 1; x <= player_ptr->x + game_term->wid / 2; x++) {
413 for (TERM_LEN y = player_ptr->y - game_term->hgt / 2 + 1; y <= player_ptr->y + game_term->hgt / 2; y++) {
416 if (!in_bounds2(player_ptr->current_floor_ptr, y, x)) {
417 auto *f_ptr = &terrains_info[feat_none];
418 a = f_ptr->x_attr[F_LIT_STANDARD];
419 c = f_ptr->x_char[F_LIT_STANDARD];
420 term_queue_char(x - player_ptr->x + game_term->wid / 2 - 1, y - player_ptr->y + game_term->hgt / 2 - 1, a, c, ta, tc);
424 map_info(player_ptr, y, x, &a, &c, &ta, &tc);
427 if (w_ptr->timewalk_m_idx) {
429 } else if (is_invuln(player_ptr) || player_ptr->timewalk) {
431 } else if (player_ptr->wraith_form) {
436 term_queue_char(x - player_ptr->x + game_term->wid / 2 - 1, y - player_ptr->y + game_term->hgt / 2 - 1, a, c, ta, tc);
442 * @brief 自分の周辺のダンジョンの地形をサブウィンドウに表示する / display dungeon view around player in a sub window
443 * @param player_ptr プレイヤーへの参照ポインタ
445 void fix_dungeon(PlayerType *player_ptr)
447 display_sub_windows(PW_DUNGEON,
449 display_dungeon(player_ptr);
454 * @brief モンスターの思い出をサブウィンドウに表示する /
455 * Hack -- display dungeon view in sub-windows
456 * @param player_ptr プレイヤーへの参照ポインタ
458 void fix_monster(PlayerType *player_ptr)
460 if (!MonsterRace(player_ptr->monster_race_idx).is_valid()) {
463 display_sub_windows(PW_MONSTER_LORE,
465 display_roff(player_ptr);
470 * @brief ベースアイテム情報をサブウィンドウに表示する /
471 * Hack -- display object recall in sub-windows
472 * @param player_ptr プレイヤーへの参照ポインタ
474 void fix_object(PlayerType *player_ptr)
476 display_sub_windows(PW_ITEM_KNOWLEDGTE,
478 display_koff(player_ptr);
483 * @brief 床上のモンスター情報を返す
484 * @param floor_ptr 階の情報への参照ポインタ
485 * @param grid_prt 座標グリッドの情報への参照ポインタ
486 * @return モンスターが見える場合にはモンスター情報への参照ポインタ、それ以外はnullptr
488 * Lookコマンドでカーソルを合わせた場合に合わせてミミックは考慮しない。
490 static const MonsterEntity *monster_on_floor_items(FloorType *floor_ptr, const grid_type *g_ptr)
492 if (g_ptr->m_idx == 0) {
496 auto m_ptr = &floor_ptr->m_list[g_ptr->m_idx];
497 if (!m_ptr->is_valid() || !m_ptr->ml) {
505 * @brief 床上のアイテム一覧を作成し、表示する
506 * @param プレイヤー情報への参照ポインタ
507 * @param y 参照する座標グリッドのy座標
508 * @param x 参照する座標グリッドのx座標
510 static void display_floor_item_list(PlayerType *player_ptr, const int y, const int x)
516 term_get_size(&term_w, &term_h);
525 auto *floor_ptr = player_ptr->current_floor_ptr;
526 const auto *g_ptr = &floor_ptr->grid_array[y][x];
530 auto is_hallucinated = player_ptr->effects()->hallucination()->is_hallucinated();
531 if (player_bold(player_ptr, y, x)) {
532 line = format(_("(X:%03d Y:%03d) あなたの足元のアイテム一覧", "Items at (%03d,%03d) under you"), x, y);
533 } else if (const auto *m_ptr = monster_on_floor_items(floor_ptr, g_ptr); m_ptr != nullptr) {
534 if (is_hallucinated) {
535 line = format(_("(X:%03d Y:%03d) 何か奇妙な物の足元の発見済みアイテム一覧", "Found items at (%03d,%03d) under something strange"), x, y);
537 const MonsterRaceInfo *const r_ptr = &monraces_info[m_ptr->ap_r_idx];
538 line = format(_("(X:%03d Y:%03d) %sの足元の発見済みアイテム一覧", "Found items at (%03d,%03d) under %s"), x, y, r_ptr->name.data());
541 const TerrainType *const f_ptr = &terrains_info[g_ptr->feat];
542 concptr fn = f_ptr->name.data();
545 if (f_ptr->flags.has(TerrainCharacteristics::STORE) || (f_ptr->flags.has(TerrainCharacteristics::BLDG) && !floor_ptr->inside_arena)) {
546 buf = format(_("%sの入口", "on the entrance of %s"), fn);
547 } else if (f_ptr->flags.has(TerrainCharacteristics::WALL)) {
548 buf = format(_("%sの中", "in %s"), fn);
550 buf = format(_("%s", "on %s"), fn);
552 line = format(_("(X:%03d Y:%03d) %sの上の発見済みアイテム一覧", "Found items at (X:%03d Y:%03d) %s"), x, y, buf.data());
554 term_addstr(-1, TERM_WHITE, line);
556 // (y,x) のアイテムを1行に1個ずつ書く。
558 for (const auto o_idx : g_ptr->o_idx_list) {
559 auto *const o_ptr = &floor_ptr->o_list[o_idx];
560 const auto tval = o_ptr->bi_key.tval();
561 if (o_ptr->marked.has_not(OmType::FOUND) || tval == ItemKindType::GOLD) {
565 // 途中で行数が足りなくなったら最終行にその旨追記して終了。
566 if (term_y >= term_h) {
567 term_addstr(-1, TERM_WHITE, "-- more --");
571 term_gotoxy(0, term_y);
573 if (is_hallucinated) {
574 term_addstr(-1, TERM_WHITE, _("何か奇妙な物", "something strange"));
576 const auto item_name = describe_flavor(player_ptr, o_ptr, 0);
577 TERM_COLOR attr = tval_to_attr[enum2i(tval) % 128];
578 term_addstr(-1, attr, item_name);
586 * @brief (y,x) のアイテム一覧をサブウィンドウに表示する / display item at (y,x) in sub-windows
588 void fix_floor_item_list(PlayerType *player_ptr, const int y, const int x)
590 display_sub_windows(PW_FLOOR_ITEMS,
592 display_floor_item_list(player_ptr, y, x);
597 * @brief 発見済みのアイテム一覧を作成し、表示する
598 * @param プレイヤー情報への参照ポインタ
600 static void display_found_item_list(PlayerType *player_ptr)
605 term_get_size(&term_w, &term_h);
611 auto *floor_ptr = player_ptr->current_floor_ptr;
614 // あらかじめfloor_ptr->o_list から↓項目を取り除く
616 // OM_FOUNDフラグが立っていない
618 std::vector<ItemEntity *> found_item_list;
619 for (auto &item : floor_ptr->o_list) {
620 auto item_entity_ptr = &item;
621 if (item_entity_ptr->is_valid() && item_entity_ptr->marked.has(OmType::FOUND) && item_entity_ptr->bi_key.tval() != ItemKindType::GOLD) {
622 found_item_list.push_back(item_entity_ptr);
627 found_item_list.begin(), found_item_list.end(),
628 [player_ptr](ItemEntity *left, ItemEntity *right) -> bool {
629 return object_sort_comp(player_ptr, left, left->get_price(), right);
636 term_addstr(-1, TERM_WHITE, _("発見済みのアイテム一覧", "Found items"));
640 for (auto item : found_item_list) {
642 if (term_y >= term_h) {
646 term_gotoxy(0, term_y);
649 const auto symbol_code = item->get_symbol();
650 const auto symbol = format(" %c ", symbol_code);
651 const auto color_code_for_symbol = item->get_color();
652 term_addstr(-1, color_code_for_symbol, symbol);
654 const auto item_name = describe_flavor(player_ptr, item, 0);
655 const auto color_code_for_item = tval_to_attr[enum2i(item->bi_key.tval()) % 128];
656 term_addstr(-1, color_code_for_item, item_name);
659 const auto item_location = format("(X:%3d Y:%3d)", item->ix, item->iy);
660 prt(item_location, term_y, term_w - item_location.length() - 1);
667 * @brief 発見済みのアイテム一覧をサブウィンドウに表示する
669 void fix_found_item_list(PlayerType *player_ptr)
671 display_sub_windows(PW_FOUND_ITEMS,
673 display_found_item_list(player_ptr);
678 * @brief プレイヤーの全既知呪文を表示する / Display all known spells in a window
679 * @param player_ptr プレイヤーへの参照ポインタ
681 * Need to analyze size of the window.
682 * Need more color coding.
684 static void display_spell_list(PlayerType *player_ptr)
688 const magic_type *s_ptr;
689 GAME_TEXT name[MAX_NLEN];
693 PlayerClass pc(player_ptr);
694 if (pc.is_every_magic()) {
698 if (pc.equals(PlayerClassType::SNIPER)) {
699 display_snipe_list(player_ptr);
703 if (pc.has_listed_magics()) {
704 PERCENTAGE minfail = 0;
705 PLAYER_LEVEL plev = player_ptr->lev;
706 PERCENTAGE chance = 0;
708 MindKindType use_mind;
715 put_str(_("名前", "Name"), y, x + 5);
716 put_str(_("Lv MP 失率 効果", "Lv Mana Fail Info"), y, x + 35);
718 switch (player_ptr->pclass) {
719 case PlayerClassType::MINDCRAFTER:
720 use_mind = MindKindType::MINDCRAFTER;
722 case PlayerClassType::FORCETRAINER:
723 use_mind = MindKindType::KI;
725 case PlayerClassType::BERSERKER:
726 use_mind = MindKindType::BERSERKER;
729 case PlayerClassType::MIRROR_MASTER:
730 use_mind = MindKindType::MIRROR_MASTER;
732 case PlayerClassType::NINJA:
733 use_mind = MindKindType::NINJUTSU;
736 case PlayerClassType::ELEMENTALIST:
737 use_mind = MindKindType::ELEMENTAL;
740 use_mind = MindKindType::MINDCRAFTER;
744 for (int i = 0; i < MAX_MIND_POWERS; i++) {
746 spell = mind_powers[static_cast<int>(use_mind)].info[i];
747 if (spell.min_lev > plev) {
752 chance -= 3 * (player_ptr->lev - spell.min_lev);
753 chance -= 3 * (adj_mag_stat[player_ptr->stat_index[mp_ptr->spell_stat]] - 1);
755 if (spell.mana_cost > player_ptr->csp) {
756 chance += 5 * (spell.mana_cost - player_ptr->csp);
760 if (spell.mana_cost > player_ptr->chp) {
766 minfail = adj_mag_fail[player_ptr->stat_index[mp_ptr->spell_stat]];
767 if (chance < minfail) {
771 auto player_stun = player_ptr->effects()->stun();
772 chance += player_stun->get_magic_chance_penalty();
777 const auto comment = mindcraft_info(player_ptr, use_mind, i);
778 constexpr auto fmt = " %c) %-30s%2d %4d %3d%%%s";
779 term_putstr(x, y + i + 1, -1, a, format(fmt, I2A(i), spell.name, spell.min_lev, spell.mana_cost, chance, comment.data()));
785 if (REALM_NONE == player_ptr->realm1) {
789 for (int j = 0; j < ((player_ptr->realm2 > REALM_NONE) ? 2 : 1); j++) {
791 y = (j < 3) ? 0 : (m[j - 3] + 2);
794 for (int i = 0; i < 32; i++) {
797 if (!is_magic((j < 1) ? player_ptr->realm1 : player_ptr->realm2)) {
798 s_ptr = &technic_info[((j < 1) ? player_ptr->realm1 : player_ptr->realm2) - MIN_TECHNIC][i % 32];
800 s_ptr = &mp_ptr->info[((j < 1) ? player_ptr->realm1 : player_ptr->realm2) - 1][i % 32];
803 const auto realm = (j < 1) ? player_ptr->realm1 : player_ptr->realm2;
804 const auto spell_name = exe_spell(player_ptr, realm, i % 32, SpellProcessType::NAME);
805 strcpy(name, spell_name->data());
807 if (s_ptr->slevel >= 99) {
808 strcpy(name, _("(判読不能)", "(illegible)"));
810 } else if ((j < 1) ? ((player_ptr->spell_forgotten1 & (1UL << i))) : ((player_ptr->spell_forgotten2 & (1UL << (i % 32))))) {
812 } else if (!((j < 1) ? (player_ptr->spell_learned1 & (1UL << i)) : (player_ptr->spell_learned2 & (1UL << (i % 32))))) {
814 } else if (!((j < 1) ? (player_ptr->spell_worked1 & (1UL << i)) : (player_ptr->spell_worked2 & (1UL << (i % 32))))) {
819 term_putstr(x, m[j], -1, a, format("%c/%c) %-20.20s", I2A(n / 8), I2A(n % 8), name));
826 * @brief 現在の習得済魔法をサブウィンドウに表示する /
827 * @param player_ptr プレイヤーへの参照ポインタ
828 * Hack -- display spells in sub-windows
830 void fix_spell(PlayerType *player_ptr)
832 display_sub_windows(PW_SPELL,
834 display_spell_list(player_ptr);
839 * @brief サブウィンドウに所持品、装備品リストの表示を行う /
840 * Flip "inven" and "equip" in any sub-windows
842 void toggle_inventory_equipment(PlayerType *player_ptr)
844 for (auto i = 0U; i < angband_terms.size(); ++i) {
845 if (!angband_terms[i]) {
849 if (window_flag[i] & (PW_INVENTORY)) {
850 window_flag[i] &= ~(PW_INVENTORY);
851 window_flag[i] |= (PW_EQUIPMENT);
852 player_ptr->window_flags |= (PW_EQUIPMENT);
856 if (window_flag[i] & PW_EQUIPMENT) {
857 window_flag[i] &= ~(PW_EQUIPMENT);
858 window_flag[i] |= PW_INVENTORY;
859 player_ptr->window_flags |= PW_INVENTORY;