OSDN Git Service

Merge pull request #765 from sikabane-works/release/3.0.0Alpha17
[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 "inventory/inventory-slot-types.h"
12 #include "monster-race/monster-race.h"
13 #include "monster-race/race-flags1.h"
14 #include "object-enchant/item-feeling.h"
15 #include "object-enchant/special-object-flags.h"
16 #include "object-hook/hook-armor.h"
17 #include "object-hook/hook-bow.h"
18 #include "object-hook/hook-checker.h"
19 #include "object-hook/hook-enchant.h"
20 #include "object-hook/hook-quest.h"
21 #include "object-hook/hook-weapon.h"
22 #include "object/object-info.h"
23 #include "object/object-kind.h"
24 #include "object/object-stack.h"
25 #include "object/object-value.h"
26 #include "perception/object-perception.h"
27 #include "player/player-realm.h"
28 #include "system/floor-type-definition.h"
29 #include "util/string-processor.h"
30
31 /*
32  * A function for Auto-picker/destroyer
33  * Examine whether the object matches to the entry
34  */
35 bool is_autopick_match(player_type *player_ptr, object_type *o_ptr, autopick_type *entry, concptr o_name)
36 {
37     concptr ptr = entry->name;
38     if (IS_FLG(FLG_UNAWARE) && object_is_aware(o_ptr))
39         return FALSE;
40
41     if (IS_FLG(FLG_UNIDENTIFIED) && (object_is_known(o_ptr) || (o_ptr->ident & IDENT_SENSE)))
42         return FALSE;
43
44     if (IS_FLG(FLG_IDENTIFIED) && !object_is_known(o_ptr))
45         return FALSE;
46
47     if (IS_FLG(FLG_STAR_IDENTIFIED) && (!object_is_known(o_ptr) || !object_is_fully_known(o_ptr)))
48         return FALSE;
49
50     if (IS_FLG(FLG_BOOSTED)) {
51         object_kind *k_ptr = &k_info[o_ptr->k_idx];
52         if (!object_is_melee_weapon(o_ptr))
53             return FALSE;
54
55         if ((o_ptr->dd == k_ptr->dd) && (o_ptr->ds == k_ptr->ds))
56             return FALSE;
57
58         if (!object_is_known(o_ptr) && object_is_quest_target(player_ptr->current_floor_ptr->inside_quest, o_ptr)) {
59             return FALSE;
60         }
61     }
62
63     if (IS_FLG(FLG_MORE_DICE)) {
64         if (o_ptr->dd * o_ptr->ds < entry->dice)
65             return FALSE;
66     }
67
68     if (IS_FLG(FLG_MORE_BONUS)) {
69         if (!object_is_known(o_ptr))
70             return FALSE;
71
72         if (o_ptr->pval) {
73             if (o_ptr->pval < entry->bonus)
74                 return FALSE;
75         } else {
76             if (o_ptr->to_h < entry->bonus && o_ptr->to_d < entry->bonus && o_ptr->to_a < entry->bonus && o_ptr->pval < entry->bonus)
77                 return FALSE;
78         }
79     }
80
81     if (IS_FLG(FLG_WORTHLESS) && object_value(player_ptr, o_ptr) > 0)
82         return FALSE;
83
84     if (IS_FLG(FLG_ARTIFACT)) {
85         if (!object_is_known(o_ptr) || !object_is_artifact(o_ptr))
86             return FALSE;
87     }
88
89     if (IS_FLG(FLG_EGO)) {
90         if (!object_is_ego(o_ptr))
91             return FALSE;
92         if (!object_is_known(o_ptr) && !((o_ptr->ident & IDENT_SENSE) && o_ptr->feeling == FEEL_EXCELLENT))
93             return FALSE;
94     }
95
96     if (IS_FLG(FLG_GOOD)) {
97         if (!object_is_equipment(o_ptr))
98             return FALSE;
99         if (object_is_known(o_ptr)) {
100             if (!object_is_nameless(player_ptr, o_ptr))
101                 return FALSE;
102
103             if (o_ptr->to_a <= 0 && (o_ptr->to_h + o_ptr->to_d) <= 0)
104                 return FALSE;
105         } else if (o_ptr->ident & IDENT_SENSE) {
106             switch (o_ptr->feeling) {
107             case FEEL_GOOD:
108                 break;
109
110             default:
111                 return FALSE;
112             }
113         } else {
114             return FALSE;
115         }
116     }
117
118     if (IS_FLG(FLG_NAMELESS)) {
119         if (!object_is_equipment(o_ptr))
120             return FALSE;
121         if (object_is_known(o_ptr)) {
122             if (!object_is_nameless(player_ptr, o_ptr))
123                 return FALSE;
124         } else if (o_ptr->ident & IDENT_SENSE) {
125             switch (o_ptr->feeling) {
126             case FEEL_AVERAGE:
127             case FEEL_GOOD:
128             case FEEL_BROKEN:
129             case FEEL_CURSED:
130                 break;
131
132             default:
133                 return FALSE;
134             }
135         } else {
136             return FALSE;
137         }
138     }
139
140     if (IS_FLG(FLG_AVERAGE)) {
141         if (!object_is_equipment(o_ptr))
142             return FALSE;
143         if (object_is_known(o_ptr)) {
144             if (!object_is_nameless(player_ptr, o_ptr))
145                 return FALSE;
146
147             if (object_is_cursed(o_ptr) || object_is_broken(o_ptr))
148                 return FALSE;
149
150             if (o_ptr->to_a > 0 || (o_ptr->to_h + o_ptr->to_d) > 0)
151                 return FALSE;
152         } else if (o_ptr->ident & IDENT_SENSE) {
153             switch (o_ptr->feeling) {
154             case FEEL_AVERAGE:
155                 break;
156
157             default:
158                 return FALSE;
159             }
160         } else {
161             return FALSE;
162         }
163     }
164
165     if (IS_FLG(FLG_RARE) && !object_is_rare(o_ptr))
166         return FALSE;
167
168     if (IS_FLG(FLG_COMMON) && object_is_rare(o_ptr))
169         return FALSE;
170
171     if (IS_FLG(FLG_WANTED) && !object_is_bounty(player_ptr, o_ptr))
172         return FALSE;
173
174     if (IS_FLG(FLG_UNIQUE) && ((o_ptr->tval != TV_CORPSE && o_ptr->tval != TV_STATUE) || !(r_info[o_ptr->pval].flags1 & RF1_UNIQUE)))
175         return FALSE;
176
177     if (IS_FLG(FLG_HUMAN) && (o_ptr->tval != TV_CORPSE || !angband_strchr("pht", r_info[o_ptr->pval].d_char)))
178         return FALSE;
179
180     if (IS_FLG(FLG_UNREADABLE) && (o_ptr->tval < TV_LIFE_BOOK || check_book_realm(player_ptr, o_ptr->tval, o_ptr->sval)))
181         return FALSE;
182
183     bool realm_except_class = player_ptr->pclass == CLASS_SORCERER || player_ptr->pclass == CLASS_RED_MAGE;
184
185     if (IS_FLG(FLG_REALM1) && (get_realm1_book(player_ptr) != o_ptr->tval || realm_except_class))
186         return FALSE;
187
188     if (IS_FLG(FLG_REALM2) && (get_realm2_book(player_ptr) != o_ptr->tval || realm_except_class))
189         return FALSE;
190
191     if (IS_FLG(FLG_FIRST) && (o_ptr->tval < TV_LIFE_BOOK || 0 != o_ptr->sval))
192         return FALSE;
193
194     if (IS_FLG(FLG_SECOND) && (o_ptr->tval < TV_LIFE_BOOK || 1 != o_ptr->sval))
195         return FALSE;
196
197     if (IS_FLG(FLG_THIRD) && (o_ptr->tval < TV_LIFE_BOOK || 2 != o_ptr->sval))
198         return FALSE;
199
200     if (IS_FLG(FLG_FOURTH) && (o_ptr->tval < TV_LIFE_BOOK || 3 != o_ptr->sval))
201         return FALSE;
202
203     if (IS_FLG(FLG_WEAPONS)) {
204         if (!object_is_weapon(player_ptr, o_ptr))
205             return FALSE;
206     } else if (IS_FLG(FLG_FAVORITE_WEAPONS)) {
207         if (!object_is_favorite(player_ptr, o_ptr))
208             return FALSE;
209     } else if (IS_FLG(FLG_ARMORS)) {
210         if (!object_is_armour(player_ptr, o_ptr))
211             return FALSE;
212     } else if (IS_FLG(FLG_MISSILES)) {
213         if (!object_is_ammo(o_ptr))
214             return FALSE;
215     } else if (IS_FLG(FLG_DEVICES)) {
216         switch (o_ptr->tval) {
217         case TV_SCROLL:
218         case TV_STAFF:
219         case TV_WAND:
220         case TV_ROD:
221             break;
222         default:
223             return FALSE;
224         }
225     } else if (IS_FLG(FLG_LIGHTS)) {
226         if (!(o_ptr->tval == TV_LITE))
227             return FALSE;
228     } else if (IS_FLG(FLG_JUNKS)) {
229         switch (o_ptr->tval) {
230         case TV_SKELETON:
231         case TV_BOTTLE:
232         case TV_JUNK:
233         case TV_STATUE:
234             break;
235         default:
236             return FALSE;
237         }
238     } else if (IS_FLG(FLG_CORPSES)) {
239         if (o_ptr->tval != TV_CORPSE && o_ptr->tval != TV_SKELETON)
240             return FALSE;
241     } else if (IS_FLG(FLG_SPELLBOOKS)) {
242         if (!(o_ptr->tval >= TV_LIFE_BOOK))
243             return FALSE;
244     } else if (IS_FLG(FLG_HAFTED)) {
245         if (!(o_ptr->tval == TV_HAFTED))
246             return FALSE;
247     } else if (IS_FLG(FLG_SHIELDS)) {
248         if (!(o_ptr->tval == TV_SHIELD))
249             return FALSE;
250     } else if (IS_FLG(FLG_BOWS)) {
251         if (!(o_ptr->tval == TV_BOW))
252             return FALSE;
253     } else if (IS_FLG(FLG_RINGS)) {
254         if (!(o_ptr->tval == TV_RING))
255             return FALSE;
256     } else if (IS_FLG(FLG_AMULETS)) {
257         if (!(o_ptr->tval == TV_AMULET))
258             return FALSE;
259     } else if (IS_FLG(FLG_SUITS)) {
260         if (!(o_ptr->tval == TV_DRAG_ARMOR || o_ptr->tval == TV_HARD_ARMOR || o_ptr->tval == TV_SOFT_ARMOR))
261             return FALSE;
262     } else if (IS_FLG(FLG_CLOAKS)) {
263         if (!(o_ptr->tval == TV_CLOAK))
264             return FALSE;
265     } else if (IS_FLG(FLG_HELMS)) {
266         if (!(o_ptr->tval == TV_CROWN || o_ptr->tval == TV_HELM))
267             return FALSE;
268     } else if (IS_FLG(FLG_GLOVES)) {
269         if (!(o_ptr->tval == TV_GLOVES))
270             return FALSE;
271     } else if (IS_FLG(FLG_BOOTS)) {
272         if (!(o_ptr->tval == TV_BOOTS))
273             return FALSE;
274     }
275
276     if (*ptr == '^') {
277         ptr++;
278         if (strncmp(o_name, ptr, strlen(ptr)))
279             return FALSE;
280     } else {
281         if (!angband_strstr(o_name, ptr))
282             return FALSE;
283     }
284
285     if (!IS_FLG(FLG_COLLECTING))
286         return TRUE;
287
288     for (int j = 0; j < INVEN_PACK; j++) {
289         /*
290          * 'Collecting' means the item must be absorbed
291          * into an inventory slot.
292          * But an item can not be absorbed into itself!
293          */
294         if ((&player_ptr->inventory_list[j] != o_ptr) && object_similar(&player_ptr->inventory_list[j], o_ptr))
295             return TRUE;
296     }
297
298     return FALSE;
299 }