OSDN Git Service

Merge branch 'master' of https://github.com/hengband/hengband
[hengbandforosx/hengbandosx.git] / src / autopick / autopick.cpp
1 /*!
2  * @file autopick.c
3  * @brief 自動拾い機能の実装 / Object Auto-picker/Destroyer
4  * @date 2014/01/02
5  * @author
6  * Copyright (c) 2002  Mogami\n
7  *\n
8  * This software may be copied and distributed for educational, research, and\n
9  * not for profit purposes provided that this copyright and statement are\n
10  * included in all such copies.\n
11  * 2014 Deskull rearranged comment for Doxygen.\n
12  */
13
14 #include "autopick/autopick.h"
15 #include "autopick/autopick-destroyer.h"
16 #include "autopick/autopick-finder.h"
17 #include "autopick/autopick-menu-data-table.h"
18 #include "autopick/autopick-methods-table.h"
19 #include "autopick/autopick-util.h"
20 #include "core/asking-player.h"
21 #include "core/disturbance.h"
22 #include "flavor/flavor-describer.h"
23 #include "floor/floor-object.h"
24 #include "inventory/inventory-object.h"
25 #include "inventory/inventory-slot-types.h"
26 #include "inventory/player-inventory.h"
27 #include "object/object-info.h"
28 #include "object/object-mark-types.h"
29 #include "system/floor-type-definition.h"
30 #include "system/grid-type-definition.h"
31 #include "system/item-entity.h"
32 #include "system/player-type-definition.h"
33 #include "term/screen-processor.h"
34 #include "view/display-messages.h"
35 #include "window/display-sub-windows.h"
36 #include <sstream>
37
38 /*!
39  * @brief Auto-destroy marked item
40  */
41 static void autopick_delayed_alter_aux(PlayerType *player_ptr, INVENTORY_IDX item)
42 {
43     const auto *o_ptr = ref_item(player_ptr, item);
44     if (!o_ptr->is_valid() || o_ptr->marked.has_not(OmType::AUTODESTROY)) {
45         return;
46     }
47
48     const auto item_name = describe_flavor(player_ptr, o_ptr, 0);
49     if (item >= 0) {
50         inven_item_increase(player_ptr, item, -(o_ptr->number));
51         inven_item_optimize(player_ptr, item);
52     } else {
53         delete_object_idx(player_ptr, 0 - item);
54     }
55
56     msg_format(_("%sを自動破壊します。", "Auto-destroying %s."), item_name.data());
57 }
58
59 /*!
60  * @brief Auto-destroy marked items in inventry and on floor
61  * @details
62  * Scan inventry in reverse order to prevent
63  * skipping after inven_item_optimize()
64  */
65 void autopick_delayed_alter(PlayerType *player_ptr)
66 {
67     for (INVENTORY_IDX item = INVEN_TOTAL - 1; item >= 0; item--) {
68         autopick_delayed_alter_aux(player_ptr, item);
69     }
70
71     auto &grid = player_ptr->current_floor_ptr->grid_array[player_ptr->y][player_ptr->x];
72     for (auto it = grid.o_idx_list.begin(); it != grid.o_idx_list.end();) {
73         INVENTORY_IDX item = *it++;
74         autopick_delayed_alter_aux(player_ptr, -item);
75     }
76
77     // PW_FLOOR_ITEM_LISTは遅れるので即時更新
78     fix_floor_item_list(player_ptr, player_ptr->y, player_ptr->x);
79 }
80
81 /*!
82  * @brief Auto-inscription and/or destroy
83  * @details
84  * Auto-destroyer works only on inventory or on floor stack only when
85  * requested.
86  */
87 void autopick_alter_item(PlayerType *player_ptr, INVENTORY_IDX item, bool destroy)
88 {
89     ItemEntity *o_ptr;
90     o_ptr = ref_item(player_ptr, item);
91     int idx = find_autopick_list(player_ptr, o_ptr);
92     auto_inscribe_item(player_ptr, o_ptr, idx);
93     if (destroy && item <= INVEN_PACK) {
94         auto_destroy_item(player_ptr, o_ptr, idx);
95     }
96 }
97
98 /*!
99  * @brief Automatically pickup/destroy items in this grid.
100  */
101 void autopick_pickup_items(PlayerType *player_ptr, grid_type *g_ptr)
102 {
103     for (auto it = g_ptr->o_idx_list.begin(); it != g_ptr->o_idx_list.end();) {
104         OBJECT_IDX this_o_idx = *it++;
105         auto *o_ptr = &player_ptr->current_floor_ptr->o_list[this_o_idx];
106         int idx = find_autopick_list(player_ptr, o_ptr);
107         auto_inscribe_item(player_ptr, o_ptr, idx);
108         if ((idx < 0) || (autopick_list[idx].action & (DO_AUTOPICK | DO_QUERY_AUTOPICK)) == 0) {
109             auto_destroy_item(player_ptr, o_ptr, idx);
110             continue;
111         }
112
113         disturb(player_ptr, false, false);
114         if (!check_store_item_to_inventory(player_ptr, o_ptr)) {
115             const auto item_name = describe_flavor(player_ptr, o_ptr, 0);
116             msg_format(_("ザックには%sを入れる隙間がない。", "You have no room for %s."), item_name.data());
117             o_ptr->marked.set(OmType::SUPRESS_MESSAGE);
118             continue;
119         }
120
121         if (!(autopick_list[idx].action & DO_QUERY_AUTOPICK)) {
122             describe_pickup_item(player_ptr, this_o_idx);
123             continue;
124         }
125
126         if (o_ptr->marked.has(OmType::NO_QUERY)) {
127             continue;
128         }
129
130         const auto item_name = describe_flavor(player_ptr, o_ptr, 0);
131         std::stringstream ss;
132         ss << _(item_name, "Pick up ") << _("を拾いますか", item_name) << "? ";
133         if (!get_check(ss.str())) {
134             o_ptr->marked.set({ OmType::SUPRESS_MESSAGE, OmType::NO_QUERY });
135             continue;
136         }
137
138         describe_pickup_item(player_ptr, this_o_idx);
139     }
140 }