OSDN Git Service

[Refactor] #37353 Separated hook-enchant.c/h from object-hook.c/h
[hengband/hengband.git] / src / autopick / autopick-matcher.c
1 /*!
2  * todo 300行以上の凶悪関数なので後で分割しておく
3  * @brief 床のアイテムが自動拾いに一致するかどうかを調べる関数だけを格納したファイル
4  * @date 2020/04/25
5  * @author Hourier
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 "monster-race/monster-race.h"
12 #include "monster-race/race-flags1.h"
13 #include "perception/object-perception.h"
14 #include "object-enchant/item-feeling.h"
15 #include "object-hook/hook-armor.h"
16 #include "object-hook/hook-bow.h"
17 #include "object-hook/hook-checker.h"
18 #include "object-hook/hook-enchant.h"
19 #include "object-hook/hook-quest.h"
20 #include "object-hook/hook-weapon.h"
21 #include "object/object-kind.h"
22 #include "object/object-stack.h"
23 #include "object/object-value.h"
24 #include "object/object-info.h"
25 #include "object-enchant/special-object-flags.h"
26 #include "util/string-processor.h"
27
28 /*
29  * A function for Auto-picker/destroyer
30  * Examine whether the object matches to the entry
31  */
32 bool is_autopick_match(player_type *player_ptr, object_type *o_ptr, autopick_type *entry, concptr o_name)
33 {
34         concptr ptr = entry->name;
35         if (IS_FLG(FLG_UNAWARE) && object_is_aware(o_ptr))
36                 return FALSE;
37
38         if (IS_FLG(FLG_UNIDENTIFIED)
39                 && (object_is_known(o_ptr) || (o_ptr->ident & IDENT_SENSE)))
40                 return FALSE;
41
42         if (IS_FLG(FLG_IDENTIFIED) && !object_is_known(o_ptr))
43                 return FALSE;
44
45         if (IS_FLG(FLG_STAR_IDENTIFIED) &&
46                 (!object_is_known(o_ptr) || !object_is_fully_known(o_ptr)))
47                 return FALSE;
48
49         if (IS_FLG(FLG_BOOSTED))
50         {
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, o_ptr))
59                 {
60                         return FALSE;
61                 }
62         }
63
64         if (IS_FLG(FLG_MORE_DICE))
65         {
66                 if (o_ptr->dd * o_ptr->ds < entry->dice)
67                         return FALSE;
68         }
69
70         if (IS_FLG(FLG_MORE_BONUS))
71         {
72                 if (!object_is_known(o_ptr)) return FALSE;
73
74                 if (o_ptr->pval)
75                 {
76                         if (o_ptr->pval < entry->bonus) return FALSE;
77                 }
78                 else
79                 {
80                         if (o_ptr->to_h < entry->bonus &&
81                                 o_ptr->to_d < entry->bonus &&
82                                 o_ptr->to_a < entry->bonus &&
83                                 o_ptr->pval < entry->bonus)
84                                 return FALSE;
85                 }
86         }
87
88         if (IS_FLG(FLG_WORTHLESS) && object_value(player_ptr, o_ptr) > 0)
89                 return FALSE;
90
91         if (IS_FLG(FLG_ARTIFACT))
92         {
93                 if (!object_is_known(o_ptr) || !object_is_artifact(o_ptr))
94                         return FALSE;
95         }
96
97         if (IS_FLG(FLG_EGO))
98         {
99                 if (!object_is_ego(o_ptr)) return FALSE;
100                 if (!object_is_known(o_ptr) &&
101                         !((o_ptr->ident & IDENT_SENSE) && o_ptr->feeling == FEEL_EXCELLENT))
102                         return FALSE;
103         }
104
105         if (IS_FLG(FLG_GOOD))
106         {
107                 if (!object_is_equipment(o_ptr)) return FALSE;
108                 if (object_is_known(o_ptr))
109                 {
110                         if (!object_is_nameless(player_ptr, o_ptr))
111                                 return FALSE;
112
113                         if (o_ptr->to_a <= 0 && (o_ptr->to_h + o_ptr->to_d) <= 0)
114                                 return FALSE;
115                 }
116                 else if (o_ptr->ident & IDENT_SENSE)
117                 {
118                         switch (o_ptr->feeling)
119                         {
120                         case FEEL_GOOD:
121                                 break;
122
123                         default:
124                                 return FALSE;
125                         }
126                 }
127                 else
128                 {
129                         return FALSE;
130                 }
131         }
132
133         if (IS_FLG(FLG_NAMELESS))
134         {
135                 if (!object_is_equipment(o_ptr)) return FALSE;
136                 if (object_is_known(o_ptr))
137                 {
138                         if (!object_is_nameless(player_ptr, o_ptr))
139                                 return FALSE;
140                 }
141                 else if (o_ptr->ident & IDENT_SENSE)
142                 {
143                         switch (o_ptr->feeling)
144                         {
145                         case FEEL_AVERAGE:
146                         case FEEL_GOOD:
147                         case FEEL_BROKEN:
148                         case FEEL_CURSED:
149                                 break;
150
151                         default:
152                                 return FALSE;
153                         }
154                 }
155                 else
156                 {
157                         return FALSE;
158                 }
159         }
160
161         if (IS_FLG(FLG_AVERAGE))
162         {
163                 if (!object_is_equipment(o_ptr)) return FALSE;
164                 if (object_is_known(o_ptr))
165                 {
166                         if (!object_is_nameless(player_ptr, o_ptr))
167                                 return FALSE;
168
169                         if (object_is_cursed(o_ptr) || object_is_broken(o_ptr))
170                                 return FALSE;
171
172                         if (o_ptr->to_a > 0 || (o_ptr->to_h + o_ptr->to_d) > 0)
173                                 return FALSE;
174                 }
175                 else if (o_ptr->ident & IDENT_SENSE)
176                 {
177                         switch (o_ptr->feeling)
178                         {
179                         case FEEL_AVERAGE:
180                                 break;
181
182                         default:
183                                 return FALSE;
184                         }
185                 }
186                 else
187                 {
188                         return FALSE;
189                 }
190         }
191
192         if (IS_FLG(FLG_RARE) && !object_is_rare(o_ptr))
193                 return FALSE;
194
195         if (IS_FLG(FLG_COMMON) && object_is_rare(o_ptr))
196                 return FALSE;
197
198         if (IS_FLG(FLG_WANTED) && !object_is_bounty(player_ptr, o_ptr))
199                 return FALSE;
200
201         if (IS_FLG(FLG_UNIQUE) &&
202                 ((o_ptr->tval != TV_CORPSE && o_ptr->tval != TV_STATUE) ||
203                         !(r_info[o_ptr->pval].flags1 & RF1_UNIQUE)))
204                 return FALSE;
205
206         if (IS_FLG(FLG_HUMAN) &&
207                 (o_ptr->tval != TV_CORPSE ||
208                         !angband_strchr("pht", r_info[o_ptr->pval].d_char)))
209                 return FALSE;
210
211         if (IS_FLG(FLG_UNREADABLE) &&
212                 (o_ptr->tval < TV_LIFE_BOOK ||
213                         check_book_realm(player_ptr, o_ptr->tval, o_ptr->sval)))
214                 return FALSE;
215
216         if (IS_FLG(FLG_REALM1) &&
217                 (REALM1_BOOK != o_ptr->tval ||
218                         player_ptr->pclass == CLASS_SORCERER ||
219                         player_ptr->pclass == CLASS_RED_MAGE))
220                 return FALSE;
221
222         if (IS_FLG(FLG_REALM2) &&
223                 (REALM2_BOOK != o_ptr->tval ||
224                         player_ptr->pclass == CLASS_SORCERER ||
225                         player_ptr->pclass == CLASS_RED_MAGE))
226                 return FALSE;
227
228         if (IS_FLG(FLG_FIRST) &&
229                 (o_ptr->tval < TV_LIFE_BOOK || 0 != o_ptr->sval))
230                 return FALSE;
231
232         if (IS_FLG(FLG_SECOND) &&
233                 (o_ptr->tval < TV_LIFE_BOOK || 1 != o_ptr->sval))
234                 return FALSE;
235
236         if (IS_FLG(FLG_THIRD) &&
237                 (o_ptr->tval < TV_LIFE_BOOK || 2 != o_ptr->sval))
238                 return FALSE;
239
240         if (IS_FLG(FLG_FOURTH) &&
241                 (o_ptr->tval < TV_LIFE_BOOK || 3 != o_ptr->sval))
242                 return FALSE;
243
244         if (IS_FLG(FLG_WEAPONS))
245         {
246                 if (!object_is_weapon(player_ptr, o_ptr))
247                         return FALSE;
248         }
249         else if (IS_FLG(FLG_FAVORITE_WEAPONS))
250         {
251                 if (!object_is_favorite(player_ptr, o_ptr))
252                         return FALSE;
253         }
254         else if (IS_FLG(FLG_ARMORS))
255         {
256                 if (!object_is_armour(player_ptr, o_ptr))
257                         return FALSE;
258         }
259         else if (IS_FLG(FLG_MISSILES))
260         {
261                 if (!object_is_ammo(o_ptr)) return FALSE;
262         }
263         else if (IS_FLG(FLG_DEVICES))
264         {
265                 switch (o_ptr->tval)
266                 {
267                 case TV_SCROLL: case TV_STAFF: case TV_WAND: case TV_ROD:
268                         break;
269                 default: return FALSE;
270                 }
271         }
272         else if (IS_FLG(FLG_LIGHTS))
273         {
274                 if (!(o_ptr->tval == TV_LITE))
275                         return FALSE;
276         }
277         else if (IS_FLG(FLG_JUNKS))
278         {
279                 switch (o_ptr->tval)
280                 {
281                 case TV_SKELETON: case TV_BOTTLE:
282                 case TV_JUNK: case TV_STATUE:
283                         break;
284                 default: return FALSE;
285                 }
286         }
287         else if (IS_FLG(FLG_CORPSES))
288         {
289                 if (o_ptr->tval != TV_CORPSE && o_ptr->tval != TV_SKELETON)
290                         return FALSE;
291         }
292         else if (IS_FLG(FLG_SPELLBOOKS))
293         {
294                 if (!(o_ptr->tval >= TV_LIFE_BOOK))
295                         return FALSE;
296         }
297         else if (IS_FLG(FLG_HAFTED))
298         {
299                 if (!(o_ptr->tval == TV_HAFTED))
300                         return FALSE;
301         }
302         else if (IS_FLG(FLG_SHIELDS))
303         {
304                 if (!(o_ptr->tval == TV_SHIELD))
305                         return FALSE;
306         }
307         else if (IS_FLG(FLG_BOWS))
308         {
309                 if (!(o_ptr->tval == TV_BOW))
310                         return FALSE;
311         }
312         else if (IS_FLG(FLG_RINGS))
313         {
314                 if (!(o_ptr->tval == TV_RING))
315                         return FALSE;
316         }
317         else if (IS_FLG(FLG_AMULETS))
318         {
319                 if (!(o_ptr->tval == TV_AMULET))
320                         return FALSE;
321         }
322         else if (IS_FLG(FLG_SUITS))
323         {
324                 if (!(o_ptr->tval == TV_DRAG_ARMOR ||
325                         o_ptr->tval == TV_HARD_ARMOR ||
326                         o_ptr->tval == TV_SOFT_ARMOR))
327                         return FALSE;
328         }
329         else if (IS_FLG(FLG_CLOAKS))
330         {
331                 if (!(o_ptr->tval == TV_CLOAK))
332                         return FALSE;
333         }
334         else if (IS_FLG(FLG_HELMS))
335         {
336                 if (!(o_ptr->tval == TV_CROWN || o_ptr->tval == TV_HELM))
337                         return FALSE;
338         }
339         else if (IS_FLG(FLG_GLOVES))
340         {
341                 if (!(o_ptr->tval == TV_GLOVES))
342                         return FALSE;
343         }
344         else if (IS_FLG(FLG_BOOTS))
345         {
346                 if (!(o_ptr->tval == TV_BOOTS))
347                         return FALSE;
348         }
349
350         if (*ptr == '^')
351         {
352                 ptr++;
353                 if (strncmp(o_name, ptr, strlen(ptr))) return FALSE;
354         }
355         else
356         {
357                 if (!angband_strstr(o_name, ptr)) return FALSE;
358         }
359
360         if (!IS_FLG(FLG_COLLECTING)) return TRUE;
361
362         for (int j = 0; j < INVEN_PACK; j++)
363         {
364                 /*
365                  * 'Collecting' means the item must be absorbed
366                  * into an inventory slot.
367                  * But an item can not be absorbed into itself!
368                  */
369                 if ((&player_ptr->inventory_list[j] != o_ptr) &&
370                         object_similar(&player_ptr->inventory_list[j], o_ptr))
371                         return TRUE;
372         }
373
374         return FALSE;
375 }