OSDN Git Service

Merge pull request #2692 from Hourier/Move-Object-Kind-to-System
[hengbandforosx/hengbandosx.git] / src / autopick / autopick-matcher.cpp
1 /*!
2  * @brief 床のアイテムが自動拾いに一致するかどうかを調べる関数だけを格納したファイル
3  * @date 2020/04/25
4  * @author Hourier
5  * @todo 300行以上の凶悪関数なので後で分割しておく
6  */
7
8 #include "autopick/autopick-matcher.h"
9 #include "autopick/autopick-flags-table.h"
10 #include "autopick/autopick-key-flag-process.h"
11 #include "autopick/autopick-util.h"
12 #include "inventory/inventory-slot-types.h"
13 #include "monster-race/monster-race.h"
14 #include "monster-race/race-flags1.h"
15 #include "object-enchant/item-feeling.h"
16 #include "object-enchant/special-object-flags.h"
17 #include "object-hook/hook-armor.h"
18 #include "object-hook/hook-quest.h"
19 #include "object-hook/hook-weapon.h"
20 #include "object/object-info.h"
21 #include "object/object-stack.h"
22 #include "object/object-value.h"
23 #include "perception/object-perception.h"
24 #include "player-base/player-class.h"
25 #include "player/player-realm.h"
26 #include "system/baseitem-info-definition.h"
27 #include "system/floor-type-definition.h"
28 #include "system/monster-race-definition.h"
29 #include "system/object-type-definition.h"
30 #include "system/player-type-definition.h"
31 #include "util/string-processor.h"
32
33 /*!
34  * @brief A function for Auto-picker/destroyer Examine whether the object matches to the entry
35  */
36 bool is_autopick_match(PlayerType *player_ptr, ObjectType *o_ptr, autopick_type *entry, concptr o_name)
37 {
38     concptr ptr = entry->name.c_str();
39     if (IS_FLG(FLG_UNAWARE) && o_ptr->is_aware()) {
40         return false;
41     }
42
43     if (IS_FLG(FLG_UNIDENTIFIED) && (o_ptr->is_known() || (o_ptr->ident & IDENT_SENSE))) {
44         return false;
45     }
46
47     if (IS_FLG(FLG_IDENTIFIED) && !o_ptr->is_known()) {
48         return false;
49     }
50
51     if (IS_FLG(FLG_STAR_IDENTIFIED) && (!o_ptr->is_known() || !o_ptr->is_fully_known())) {
52         return false;
53     }
54
55     if (IS_FLG(FLG_BOOSTED)) {
56         auto *k_ptr = &k_info[o_ptr->k_idx];
57         if (!o_ptr->is_melee_weapon()) {
58             return false;
59         }
60
61         if ((o_ptr->dd == k_ptr->dd) && (o_ptr->ds == k_ptr->ds)) {
62             return false;
63         }
64
65         if (!o_ptr->is_known() && object_is_quest_target(player_ptr->current_floor_ptr->quest_number, o_ptr)) {
66             return false;
67         }
68     }
69
70     if (IS_FLG(FLG_MORE_DICE)) {
71         if (o_ptr->dd * o_ptr->ds < entry->dice) {
72             return false;
73         }
74     }
75
76     if (IS_FLG(FLG_MORE_BONUS)) {
77         if (!o_ptr->is_known()) {
78             return false;
79         }
80
81         if (o_ptr->pval) {
82             if (o_ptr->pval < entry->bonus) {
83                 return false;
84             }
85         } else {
86             if (o_ptr->to_h < entry->bonus && o_ptr->to_d < entry->bonus && o_ptr->to_a < entry->bonus && o_ptr->pval < entry->bonus) {
87                 return false;
88             }
89         }
90     }
91
92     if (IS_FLG(FLG_WORTHLESS) && object_value(o_ptr) > 0) {
93         return false;
94     }
95
96     if (IS_FLG(FLG_ARTIFACT)) {
97         if (!o_ptr->is_known() || !o_ptr->is_artifact()) {
98             return false;
99         }
100     }
101
102     if (IS_FLG(FLG_EGO)) {
103         if (!o_ptr->is_ego()) {
104             return false;
105         }
106         if (!o_ptr->is_known() && !((o_ptr->ident & IDENT_SENSE) && o_ptr->feeling == FEEL_EXCELLENT)) {
107             return false;
108         }
109     }
110
111     if (IS_FLG(FLG_GOOD)) {
112         if (!o_ptr->is_equipment()) {
113             return false;
114         }
115         if (o_ptr->is_known()) {
116             if (!o_ptr->is_nameless()) {
117                 return false;
118             }
119
120             if (o_ptr->to_a <= 0 && (o_ptr->to_h + o_ptr->to_d) <= 0) {
121                 return false;
122             }
123         } else if (o_ptr->ident & IDENT_SENSE) {
124             switch (o_ptr->feeling) {
125             case FEEL_GOOD:
126                 break;
127
128             default:
129                 return false;
130             }
131         } else {
132             return false;
133         }
134     }
135
136     if (IS_FLG(FLG_NAMELESS)) {
137         if (!o_ptr->is_equipment()) {
138             return false;
139         }
140         if (o_ptr->is_known()) {
141             if (!o_ptr->is_nameless()) {
142                 return false;
143             }
144         } else if (o_ptr->ident & IDENT_SENSE) {
145             switch (o_ptr->feeling) {
146             case FEEL_AVERAGE:
147             case FEEL_GOOD:
148             case FEEL_BROKEN:
149             case FEEL_CURSED:
150                 break;
151
152             default:
153                 return false;
154             }
155         } else {
156             return false;
157         }
158     }
159
160     if (IS_FLG(FLG_AVERAGE)) {
161         if (!o_ptr->is_equipment()) {
162             return false;
163         }
164         if (o_ptr->is_known()) {
165             if (!o_ptr->is_nameless()) {
166                 return false;
167             }
168
169             if (o_ptr->is_cursed() || o_ptr->is_broken()) {
170                 return false;
171             }
172
173             if (o_ptr->to_a > 0 || (o_ptr->to_h + o_ptr->to_d) > 0) {
174                 return false;
175             }
176         } else if (o_ptr->ident & IDENT_SENSE) {
177             switch (o_ptr->feeling) {
178             case FEEL_AVERAGE:
179                 break;
180
181             default:
182                 return false;
183             }
184         } else {
185             return false;
186         }
187     }
188
189     if (IS_FLG(FLG_RARE) && !o_ptr->is_rare()) {
190         return false;
191     }
192
193     if (IS_FLG(FLG_COMMON) && o_ptr->is_rare()) {
194         return false;
195     }
196
197     if (IS_FLG(FLG_WANTED) && !object_is_bounty(player_ptr, o_ptr)) {
198         return false;
199     }
200
201     const auto r_idx = i2enum<MonsterRaceId>(o_ptr->pval);
202     if (IS_FLG(FLG_UNIQUE) && ((o_ptr->tval != ItemKindType::CORPSE && o_ptr->tval != ItemKindType::STATUE) || r_info[r_idx].kind_flags.has_not(MonsterKindType::UNIQUE))) {
203         return false;
204     }
205
206     if (IS_FLG(FLG_HUMAN) && (o_ptr->tval != ItemKindType::CORPSE || !angband_strchr("pht", r_info[r_idx].d_char))) {
207         return false;
208     }
209
210     if (IS_FLG(FLG_UNREADABLE) && (o_ptr->tval < ItemKindType::LIFE_BOOK || check_book_realm(player_ptr, o_ptr->tval, o_ptr->sval))) {
211         return false;
212     }
213
214     PlayerClass pc(player_ptr);
215     auto realm_except_class = pc.equals(PlayerClassType::SORCERER) || pc.equals(PlayerClassType::RED_MAGE);
216
217     if (IS_FLG(FLG_REALM1) && ((get_realm1_book(player_ptr) != o_ptr->tval) || realm_except_class)) {
218         return false;
219     }
220
221     if (IS_FLG(FLG_REALM2) && ((get_realm2_book(player_ptr) != o_ptr->tval) || realm_except_class)) {
222         return false;
223     }
224
225     if (IS_FLG(FLG_FIRST) && ((o_ptr->tval < ItemKindType::LIFE_BOOK) || (o_ptr->sval) != 0)) {
226         return false;
227     }
228
229     if (IS_FLG(FLG_SECOND) && ((o_ptr->tval < ItemKindType::LIFE_BOOK) || (o_ptr->sval) != 1)) {
230         return false;
231     }
232
233     if (IS_FLG(FLG_THIRD) && ((o_ptr->tval < ItemKindType::LIFE_BOOK) || (o_ptr->sval) != 2)) {
234         return false;
235     }
236
237     if (IS_FLG(FLG_FOURTH) && ((o_ptr->tval < ItemKindType::LIFE_BOOK) || (o_ptr->sval) != 3)) {
238         return false;
239     }
240
241     if (IS_FLG(FLG_WEAPONS)) {
242         if (!o_ptr->is_weapon()) {
243             return false;
244         }
245     } else if (IS_FLG(FLG_FAVORITE_WEAPONS)) {
246         if (!object_is_favorite(player_ptr, o_ptr)) {
247             return false;
248         }
249     } else if (IS_FLG(FLG_ARMORS)) {
250         if (!o_ptr->is_armour()) {
251             return false;
252         }
253     } else if (IS_FLG(FLG_MISSILES)) {
254         if (!o_ptr->is_ammo()) {
255             return false;
256         }
257     } else if (IS_FLG(FLG_DEVICES)) {
258         switch (o_ptr->tval) {
259         case ItemKindType::SCROLL:
260         case ItemKindType::STAFF:
261         case ItemKindType::WAND:
262         case ItemKindType::ROD:
263             break;
264         default:
265             return false;
266         }
267     } else if (IS_FLG(FLG_LIGHTS)) {
268         if (!(o_ptr->tval == ItemKindType::LITE)) {
269             return false;
270         }
271     } else if (IS_FLG(FLG_JUNKS)) {
272         switch (o_ptr->tval) {
273         case ItemKindType::SKELETON:
274         case ItemKindType::BOTTLE:
275         case ItemKindType::JUNK:
276         case ItemKindType::STATUE:
277             break;
278         default:
279             return false;
280         }
281     } else if (IS_FLG(FLG_CORPSES)) {
282         if (o_ptr->tval != ItemKindType::CORPSE && o_ptr->tval != ItemKindType::SKELETON) {
283             return false;
284         }
285     } else if (IS_FLG(FLG_SPELLBOOKS)) {
286         if (!(o_ptr->tval >= ItemKindType::LIFE_BOOK)) {
287             return false;
288         }
289     } else if (IS_FLG(FLG_HAFTED)) {
290         if (!(o_ptr->tval == ItemKindType::HAFTED)) {
291             return false;
292         }
293     } else if (IS_FLG(FLG_SHIELDS)) {
294         if (!(o_ptr->tval == ItemKindType::SHIELD)) {
295             return false;
296         }
297     } else if (IS_FLG(FLG_BOWS)) {
298         if (!(o_ptr->tval == ItemKindType::BOW)) {
299             return false;
300         }
301     } else if (IS_FLG(FLG_RINGS)) {
302         if (!(o_ptr->tval == ItemKindType::RING)) {
303             return false;
304         }
305     } else if (IS_FLG(FLG_AMULETS)) {
306         if (!(o_ptr->tval == ItemKindType::AMULET)) {
307             return false;
308         }
309     } else if (IS_FLG(FLG_SUITS)) {
310         if (!(o_ptr->tval == ItemKindType::DRAG_ARMOR || o_ptr->tval == ItemKindType::HARD_ARMOR || o_ptr->tval == ItemKindType::SOFT_ARMOR)) {
311             return false;
312         }
313     } else if (IS_FLG(FLG_CLOAKS)) {
314         if (!(o_ptr->tval == ItemKindType::CLOAK)) {
315             return false;
316         }
317     } else if (IS_FLG(FLG_HELMS)) {
318         if (!(o_ptr->tval == ItemKindType::CROWN || o_ptr->tval == ItemKindType::HELM)) {
319             return false;
320         }
321     } else if (IS_FLG(FLG_GLOVES)) {
322         if (!(o_ptr->tval == ItemKindType::GLOVES)) {
323             return false;
324         }
325     } else if (IS_FLG(FLG_BOOTS)) {
326         if (!(o_ptr->tval == ItemKindType::BOOTS)) {
327             return false;
328         }
329     }
330
331     if (*ptr == '^') {
332         ptr++;
333         if (strncmp(o_name, ptr, strlen(ptr))) {
334             return false;
335         }
336     } else {
337         if (!angband_strstr(o_name, ptr)) {
338             return false;
339         }
340     }
341
342     if (!IS_FLG(FLG_COLLECTING)) {
343         return true;
344     }
345
346     for (int j = 0; j < INVEN_PACK; j++) {
347         /*
348          * 'Collecting' means the item must be absorbed
349          * into an inventory slot.
350          * But an item can not be absorbed into itself!
351          */
352         if ((&player_ptr->inventory_list[j] != o_ptr) && object_similar(&player_ptr->inventory_list[j], o_ptr)) {
353             return true;
354         }
355     }
356
357     return false;
358 }