OSDN Git Service

[Refactor] #40413 Separated display-messages.c/h from util.c/h
[hengband/hengband.git] / src / autopick / autopick-destroyer.c
1 /*!
2  * @brief 自動破壊の実行
3  * @date 2020/04/25
4  * @author Hourier
5  */
6
7 #include "autopick/autopick-destroyer.h"
8 #include "autopick-methods-table.h"
9 #include "autopick/autopick-util.h"
10 #include "game-option/auto-destruction-options.h"
11 #include "game-option/input-options.h"
12 #include "perception/object-perception.h"
13 #include "object-enchant/object-ego.h"
14 #include "object/object-flavor.h"
15 #include "object/object-hook.h"
16 #include "object/object-mark-types.h"
17 #include "object/object-value.h"
18 #include "object-enchant/special-object-flags.h"
19 #include "sv-definition/sv-other-types.h"
20 #include "sv-definition/sv-wand-types.h"
21 #include "player/player-move.h"
22 #include "player/player-race-types.h"
23 #include "view/display-messages.h"
24
25 /*!
26  * @brief クラス依存のアイテム破壊を調べる
27  * @param player_ptr プレーヤーへの参照ポインタ
28  * @param o_ptr アイテムへの参照ポインタ
29  * @return 特別なクラス、かつそのクラス特有のアイテムであればFALSE、それ以外はTRUE
30  */
31 static bool is_leave_special_item(player_type *player_ptr, object_type *o_ptr)
32 {
33         if (!leave_special) return TRUE;
34
35         if (player_ptr->prace == RACE_BALROG)
36         {
37                 if (o_ptr->tval == TV_CORPSE &&
38                         o_ptr->sval == SV_CORPSE &&
39                         angband_strchr("pht", r_info[o_ptr->pval].d_char))
40                         return FALSE;
41         }
42         else if (player_ptr->pclass == CLASS_ARCHER)
43         {
44                 if (o_ptr->tval == TV_SKELETON ||
45                         (o_ptr->tval == TV_CORPSE && o_ptr->sval == SV_SKELETON))
46                         return FALSE;
47         }
48         else if (player_ptr->pclass == CLASS_NINJA)
49         {
50                 if (o_ptr->tval == TV_LITE &&
51                         o_ptr->name2 == EGO_LITE_DARKNESS && object_is_known(o_ptr))
52                         return FALSE;
53         }
54         else if (player_ptr->pclass == CLASS_BEASTMASTER ||
55                 player_ptr->pclass == CLASS_CAVALRY)
56         {
57                 if (o_ptr->tval == TV_WAND &&
58                         o_ptr->sval == SV_WAND_HEAL_MONSTER && object_is_aware(o_ptr))
59                         return FALSE;
60         }
61
62         return TRUE;
63 }
64
65
66 /*
67  * Automatically destroy items in this grid.
68  */
69 static bool is_opt_confirm_destroy(player_type *player_ptr, object_type *o_ptr)
70 {
71         if (!destroy_items) return FALSE;
72
73         if (leave_worth)
74                 if (object_value(o_ptr) > 0) return FALSE;
75
76         if (leave_equip)
77                 if (object_is_weapon_armour_ammo(o_ptr)) return FALSE;
78
79         if (leave_chest)
80                 if ((o_ptr->tval == TV_CHEST) && o_ptr->pval) return FALSE;
81
82         if (leave_wanted)
83                 if (object_is_bounty(o_ptr)) return FALSE;
84
85         if (leave_corpse)
86                 if (o_ptr->tval == TV_CORPSE) return FALSE;
87
88         if (leave_junk)
89                 if ((o_ptr->tval == TV_SKELETON) || (o_ptr->tval == TV_BOTTLE) || (o_ptr->tval == TV_JUNK) || (o_ptr->tval == TV_STATUE)) return FALSE;
90
91         if (!is_leave_special_item(player_ptr, o_ptr)) return FALSE;
92
93         if (o_ptr->tval == TV_GOLD) return FALSE;
94
95         return TRUE;
96 }
97
98
99 void auto_destroy_item(player_type *player_ptr, object_type *o_ptr, int autopick_idx)
100 {
101         bool destroy = FALSE;
102         if (is_opt_confirm_destroy(player_ptr, o_ptr)) destroy = TRUE;
103
104         if (autopick_idx >= 0 &&
105                 !(autopick_list[autopick_idx].action & DO_AUTODESTROY))
106                 destroy = FALSE;
107
108         if (!always_pickup)
109         {
110                 if (autopick_idx >= 0 &&
111                         (autopick_list[autopick_idx].action & DO_AUTODESTROY))
112                         destroy = TRUE;
113         }
114
115         if (!destroy) return;
116
117         disturb(player_ptr, FALSE, FALSE);
118         if (!can_player_destroy_object(o_ptr))
119         {
120                 GAME_TEXT o_name[MAX_NLEN];
121                 object_desc(player_ptr, o_name, o_ptr, 0);
122                 msg_format(_("%sは破壊不能だ。", "You cannot auto-destroy %s."), o_name);
123                 return;
124         }
125
126         (void)COPY(&autopick_last_destroyed_object, o_ptr, object_type);
127         o_ptr->marked |= OM_AUTODESTROY;
128         player_ptr->update |= PU_AUTODESTROY;
129 }