OSDN Git Service

Merge pull request #2052 from sikabane-works/feature/refactor-generate-fixed-room
[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-kind.h"
22 #include "object/object-stack.h"
23 #include "object/object-value.h"
24 #include "perception/object-perception.h"
25 #include "player-base/player-class.h"
26 #include "player/player-realm.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     if (IS_FLG(FLG_UNIDENTIFIED) && (o_ptr->is_known() || (o_ptr->ident & IDENT_SENSE)))
43         return false;
44
45     if (IS_FLG(FLG_IDENTIFIED) && !o_ptr->is_known())
46         return false;
47
48     if (IS_FLG(FLG_STAR_IDENTIFIED) && (!o_ptr->is_known() || !o_ptr->is_fully_known()))
49         return false;
50
51     if (IS_FLG(FLG_BOOSTED)) {
52         auto *k_ptr = &k_info[o_ptr->k_idx];
53         if (!o_ptr->is_melee_weapon())
54             return false;
55
56         if ((o_ptr->dd == k_ptr->dd) && (o_ptr->ds == k_ptr->ds))
57             return false;
58
59         if (!o_ptr->is_known() && object_is_quest_target(player_ptr->current_floor_ptr->quest_number, o_ptr)) {
60             return false;
61         }
62     }
63
64     if (IS_FLG(FLG_MORE_DICE)) {
65         if (o_ptr->dd * o_ptr->ds < entry->dice)
66             return false;
67     }
68
69     if (IS_FLG(FLG_MORE_BONUS)) {
70         if (!o_ptr->is_known())
71             return false;
72
73         if (o_ptr->pval) {
74             if (o_ptr->pval < entry->bonus)
75                 return false;
76         } else {
77             if (o_ptr->to_h < entry->bonus && o_ptr->to_d < entry->bonus && o_ptr->to_a < entry->bonus && o_ptr->pval < entry->bonus)
78                 return false;
79         }
80     }
81
82     if (IS_FLG(FLG_WORTHLESS) && object_value(o_ptr) > 0)
83         return false;
84
85     if (IS_FLG(FLG_ARTIFACT)) {
86         if (!o_ptr->is_known() || !o_ptr->is_artifact())
87             return false;
88     }
89
90     if (IS_FLG(FLG_EGO)) {
91         if (!o_ptr->is_ego())
92             return false;
93         if (!o_ptr->is_known() && !((o_ptr->ident & IDENT_SENSE) && o_ptr->feeling == FEEL_EXCELLENT))
94             return false;
95     }
96
97     if (IS_FLG(FLG_GOOD)) {
98         if (!o_ptr->is_equipment())
99             return false;
100         if (o_ptr->is_known()) {
101             if (!o_ptr->is_nameless())
102                 return false;
103
104             if (o_ptr->to_a <= 0 && (o_ptr->to_h + o_ptr->to_d) <= 0)
105                 return false;
106         } else if (o_ptr->ident & IDENT_SENSE) {
107             switch (o_ptr->feeling) {
108             case FEEL_GOOD:
109                 break;
110
111             default:
112                 return false;
113             }
114         } else {
115             return false;
116         }
117     }
118
119     if (IS_FLG(FLG_NAMELESS)) {
120         if (!o_ptr->is_equipment())
121             return false;
122         if (o_ptr->is_known()) {
123             if (!o_ptr->is_nameless())
124                 return false;
125         } else if (o_ptr->ident & IDENT_SENSE) {
126             switch (o_ptr->feeling) {
127             case FEEL_AVERAGE:
128             case FEEL_GOOD:
129             case FEEL_BROKEN:
130             case FEEL_CURSED:
131                 break;
132
133             default:
134                 return false;
135             }
136         } else {
137             return false;
138         }
139     }
140
141     if (IS_FLG(FLG_AVERAGE)) {
142         if (!o_ptr->is_equipment())
143             return false;
144         if (o_ptr->is_known()) {
145             if (!o_ptr->is_nameless())
146                 return false;
147
148             if (o_ptr->is_cursed() || o_ptr->is_broken())
149                 return false;
150
151             if (o_ptr->to_a > 0 || (o_ptr->to_h + o_ptr->to_d) > 0)
152                 return false;
153         } else if (o_ptr->ident & IDENT_SENSE) {
154             switch (o_ptr->feeling) {
155             case FEEL_AVERAGE:
156                 break;
157
158             default:
159                 return false;
160             }
161         } else {
162             return false;
163         }
164     }
165
166     if (IS_FLG(FLG_RARE) && !o_ptr->is_rare())
167         return false;
168
169     if (IS_FLG(FLG_COMMON) && o_ptr->is_rare())
170         return false;
171
172     if (IS_FLG(FLG_WANTED) && !object_is_bounty(player_ptr, o_ptr))
173         return false;
174
175     if (IS_FLG(FLG_UNIQUE) && ((o_ptr->tval != ItemKindType::CORPSE && o_ptr->tval != ItemKindType::STATUE) || r_info[o_ptr->pval].kind_flags.has_not(MonsterKindType::UNIQUE)))
176         return false;
177
178     if (IS_FLG(FLG_HUMAN) && (o_ptr->tval != ItemKindType::CORPSE || !angband_strchr("pht", r_info[o_ptr->pval].d_char)))
179         return false;
180
181     if (IS_FLG(FLG_UNREADABLE) && (o_ptr->tval < ItemKindType::LIFE_BOOK || check_book_realm(player_ptr, o_ptr->tval, o_ptr->sval)))
182         return false;
183
184     PlayerClass pc(player_ptr);
185     auto realm_except_class = pc.equals(PlayerClassType::SORCERER) || pc.equals(PlayerClassType::RED_MAGE);
186
187     if (IS_FLG(FLG_REALM1) && ((get_realm1_book(player_ptr) != o_ptr->tval) || realm_except_class))
188         return false;
189
190     if (IS_FLG(FLG_REALM2) && ((get_realm2_book(player_ptr) != o_ptr->tval) || realm_except_class))
191         return false;
192
193     if (IS_FLG(FLG_FIRST) && ((o_ptr->tval < ItemKindType::LIFE_BOOK) || (o_ptr->sval) != 0))
194         return false;
195
196     if (IS_FLG(FLG_SECOND) && ((o_ptr->tval < ItemKindType::LIFE_BOOK) || (o_ptr->sval) != 1))
197         return false;
198
199     if (IS_FLG(FLG_THIRD) && ((o_ptr->tval < ItemKindType::LIFE_BOOK) || (o_ptr->sval) != 2))
200         return false;
201
202     if (IS_FLG(FLG_FOURTH) && ((o_ptr->tval < ItemKindType::LIFE_BOOK) || (o_ptr->sval) != 3))
203         return false;
204
205     if (IS_FLG(FLG_WEAPONS)) {
206         if (!o_ptr->is_weapon())
207             return false;
208     } else if (IS_FLG(FLG_FAVORITE_WEAPONS)) {
209         if (!object_is_favorite(player_ptr, o_ptr))
210             return false;
211     } else if (IS_FLG(FLG_ARMORS)) {
212         if (!o_ptr->is_armour())
213             return false;
214     } else if (IS_FLG(FLG_MISSILES)) {
215         if (!o_ptr->is_ammo())
216             return false;
217     } else if (IS_FLG(FLG_DEVICES)) {
218         switch (o_ptr->tval) {
219         case ItemKindType::SCROLL:
220         case ItemKindType::STAFF:
221         case ItemKindType::WAND:
222         case ItemKindType::ROD:
223             break;
224         default:
225             return false;
226         }
227     } else if (IS_FLG(FLG_LIGHTS)) {
228         if (!(o_ptr->tval == ItemKindType::LITE))
229             return false;
230     } else if (IS_FLG(FLG_JUNKS)) {
231         switch (o_ptr->tval) {
232         case ItemKindType::SKELETON:
233         case ItemKindType::BOTTLE:
234         case ItemKindType::JUNK:
235         case ItemKindType::STATUE:
236             break;
237         default:
238             return false;
239         }
240     } else if (IS_FLG(FLG_CORPSES)) {
241         if (o_ptr->tval != ItemKindType::CORPSE && o_ptr->tval != ItemKindType::SKELETON)
242             return false;
243     } else if (IS_FLG(FLG_SPELLBOOKS)) {
244         if (!(o_ptr->tval >= ItemKindType::LIFE_BOOK))
245             return false;
246     } else if (IS_FLG(FLG_HAFTED)) {
247         if (!(o_ptr->tval == ItemKindType::HAFTED))
248             return false;
249     } else if (IS_FLG(FLG_SHIELDS)) {
250         if (!(o_ptr->tval == ItemKindType::SHIELD))
251             return false;
252     } else if (IS_FLG(FLG_BOWS)) {
253         if (!(o_ptr->tval == ItemKindType::BOW))
254             return false;
255     } else if (IS_FLG(FLG_RINGS)) {
256         if (!(o_ptr->tval == ItemKindType::RING))
257             return false;
258     } else if (IS_FLG(FLG_AMULETS)) {
259         if (!(o_ptr->tval == ItemKindType::AMULET))
260             return false;
261     } else if (IS_FLG(FLG_SUITS)) {
262         if (!(o_ptr->tval == ItemKindType::DRAG_ARMOR || o_ptr->tval == ItemKindType::HARD_ARMOR || o_ptr->tval == ItemKindType::SOFT_ARMOR))
263             return false;
264     } else if (IS_FLG(FLG_CLOAKS)) {
265         if (!(o_ptr->tval == ItemKindType::CLOAK))
266             return false;
267     } else if (IS_FLG(FLG_HELMS)) {
268         if (!(o_ptr->tval == ItemKindType::CROWN || o_ptr->tval == ItemKindType::HELM))
269             return false;
270     } else if (IS_FLG(FLG_GLOVES)) {
271         if (!(o_ptr->tval == ItemKindType::GLOVES))
272             return false;
273     } else if (IS_FLG(FLG_BOOTS)) {
274         if (!(o_ptr->tval == ItemKindType::BOOTS))
275             return false;
276     }
277
278     if (*ptr == '^') {
279         ptr++;
280         if (strncmp(o_name, ptr, strlen(ptr)))
281             return false;
282     } else {
283         if (!angband_strstr(o_name, ptr))
284             return false;
285     }
286
287     if (!IS_FLG(FLG_COLLECTING))
288         return true;
289
290     for (int j = 0; j < INVEN_PACK; j++) {
291         /*
292          * 'Collecting' means the item must be absorbed
293          * into an inventory slot.
294          * But an item can not be absorbed into itself!
295          */
296         if ((&player_ptr->inventory_list[j] != o_ptr) && object_similar(&player_ptr->inventory_list[j], o_ptr))
297             return true;
298     }
299
300     return false;
301 }