OSDN Git Service

[Fix] #40945 Resolved the issue that out-of-array access occurs when an item was...
[hengband/hengband.git] / src / autopick / autopick.c
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 "core/asking-player.h"
20 #include "core/disturbance.h"
21 #include "flavor/flavor-describer.h"
22 #include "floor/floor-object.h"
23 #include "inventory/inventory-object.h"
24 #include "inventory/inventory-slot-types.h"
25 #include "inventory/player-inventory.h"
26 #include "object/object-info.h"
27 #include "object/object-mark-types.h"
28 #include "system/floor-type-definition.h"
29 #include "term/screen-processor.h"
30 #include "view/display-messages.h"
31
32 /*
33  *  Auto-destroy marked item
34  */
35 static void autopick_delayed_alter_aux(player_type *player_ptr, INVENTORY_IDX item)
36 {
37     object_type *o_ptr;
38     o_ptr = ref_item(player_ptr, item);
39
40     if (o_ptr->k_idx == 0 || !(o_ptr->marked & OM_AUTODESTROY))
41         return;
42
43     GAME_TEXT o_name[MAX_NLEN];
44     describe_flavor(player_ptr, o_name, o_ptr, 0);
45     if (item >= 0) {
46         inven_item_increase(player_ptr, item, -(o_ptr->number));
47         inven_item_optimize(player_ptr, item);
48     } else {
49         delete_object_idx(player_ptr, 0 - item);
50     }
51
52     msg_format(_("%sを自動破壊します。", "Auto-destroying %s."), o_name);
53 }
54
55 /*
56  *  Auto-destroy marked items in inventry and on floor
57  */
58 void autopick_delayed_alter(player_type *owner_ptr)
59 {
60     INVENTORY_IDX item;
61
62     /*
63      * Scan inventry in reverse order to prevent
64      * skipping after inven_item_optimize()
65      */
66     for (item = INVEN_TOTAL - 1; item >= 0; item--)
67         autopick_delayed_alter_aux(owner_ptr, item);
68
69     floor_type *floor_ptr = owner_ptr->current_floor_ptr;
70     item = floor_ptr->grid_array[owner_ptr->y][owner_ptr->x].o_idx;
71     while (item) {
72         OBJECT_IDX next = floor_ptr->o_list[item].next_o_idx;
73         autopick_delayed_alter_aux(owner_ptr, -item);
74         item = next;
75     }
76 }
77
78 /*
79  * Auto-inscription and/or destroy
80  *
81  * Auto-destroyer works only on inventory or on floor stack only when
82  * requested.
83  */
84 void autopick_alter_item(player_type *player_ptr, INVENTORY_IDX item, bool destroy)
85 {
86     object_type *o_ptr;
87     o_ptr = ref_item(player_ptr, item);
88     int idx = find_autopick_list(player_ptr, o_ptr);
89     auto_inscribe_item(player_ptr, o_ptr, idx);
90     if (destroy && item <= INVEN_PACK)
91         auto_destroy_item(player_ptr, o_ptr, idx);
92 }
93
94 /*
95  * Automatically pickup/destroy items in this grid.
96  */
97 void autopick_pickup_items(player_type *player_ptr, grid_type *g_ptr)
98 {
99     OBJECT_IDX this_o_idx, next_o_idx = 0;
100     for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) {
101         object_type *o_ptr = &player_ptr->current_floor_ptr->o_list[this_o_idx];
102         next_o_idx = o_ptr->next_o_idx;
103         int idx = find_autopick_list(player_ptr, o_ptr);
104         auto_inscribe_item(player_ptr, o_ptr, idx);
105         if ((idx < 0) || (autopick_list[idx].action & (DO_AUTOPICK | DO_QUERY_AUTOPICK)) == 0) {
106             auto_destroy_item(player_ptr, o_ptr, idx);
107             continue;
108         }
109
110         disturb(player_ptr, FALSE, FALSE);
111         if (!check_store_item_to_inventory(player_ptr, o_ptr)) {
112             GAME_TEXT o_name[MAX_NLEN];
113             describe_flavor(player_ptr, o_name, o_ptr, 0);
114             msg_format(_("ザックには%sを入れる隙間がない。", "You have no room for %s."), o_name);
115             o_ptr->marked |= OM_NOMSG;
116             continue;
117         }
118
119         if (!(autopick_list[idx].action & DO_QUERY_AUTOPICK)) {
120             describe_pickup_item(player_ptr, this_o_idx);
121             continue;
122         }
123
124         char out_val[MAX_NLEN + 20];
125         GAME_TEXT o_name[MAX_NLEN];
126         if (o_ptr->marked & OM_NO_QUERY) {
127             continue;
128         }
129
130         describe_flavor(player_ptr, o_name, o_ptr, 0);
131         sprintf(out_val, _("%sを拾いますか? ", "Pick up %s? "), o_name);
132         if (!get_check(out_val)) {
133             o_ptr->marked |= OM_NOMSG | OM_NO_QUERY;
134             continue;
135         }
136
137         describe_pickup_item(player_ptr, this_o_idx);
138     }
139 }