7 #include "perception/simple-perception.h"
8 #include "autopick/autopick.h"
9 #include "avatar/avatar.h"
10 #include "core/disturbance.h"
11 #include "core/player-update-types.h"
12 #include "core/window-redrawer.h"
13 #include "flavor/flag-inscriptions-table.h"
14 #include "flavor/flavor-describer.h"
15 #include "flavor/object-flavor-types.h"
16 #include "game-option/auto-destruction-options.h"
17 #include "game-option/disturbance-options.h"
18 #include "inventory/inventory-describer.h"
19 #include "inventory/inventory-slot-types.h"
20 #include "mutation/mutation-flag-types.h"
21 #include "object-enchant/special-object-flags.h"
22 #include "object/object-info.h"
23 #include "perception/object-perception.h"
24 #include "player/player-status-flags.h"
25 #include "system/item-entity.h"
26 #include "system/player-type-definition.h"
27 #include "timed-effect/player-confusion.h"
28 #include "timed-effect/timed-effects.h"
29 #include "view/display-messages.h"
32 * @brief 擬似鑑定を実際に行い判定を反映する
33 * @param slot 擬似鑑定を行うプレイヤーの所持リストID
34 * @param player_ptr プレイヤーへの参照ポインタ
35 * @param heavy 重度の擬似鑑定を行うならばTRUE
37 static void sense_inventory_aux(PlayerType *player_ptr, INVENTORY_IDX slot, bool heavy)
39 auto *o_ptr = &player_ptr->inventory_list[slot];
40 if (o_ptr->ident & (IDENT_SENSE)) {
43 if (o_ptr->is_known()) {
47 item_feel_type feel = (heavy ? pseudo_value_check_heavy(o_ptr) : pseudo_value_check_light(o_ptr));
52 if ((player_ptr->muta.has(PlayerMutationType::BAD_LUCK)) && !randint0(13)) {
58 case FEEL_WORTHLESS: {
59 feel = FEEL_EXCELLENT;
64 feel = randint0(3) ? FEEL_GOOD : FEEL_AVERAGE;
71 feel = randint0(2) ? FEEL_CURSED : FEEL_GOOD;
76 feel = randint0(3) ? FEEL_CURSED : FEEL_AVERAGE;
82 case FEEL_EXCELLENT: {
83 feel = FEEL_WORTHLESS;
97 disturb(player_ptr, false, false);
100 const auto item_name = describe_flavor(player_ptr, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
101 if (slot >= INVEN_MAIN_HAND) {
103 msg_format("%s%s(%c)は%sという感じがする...", describe_use(player_ptr, slot), item_name.data(), index_to_label(slot), game_inscriptions[feel]);
105 msg_format("You feel the %s (%c) you are %s %s %s...", item_name.data(), index_to_label(slot), describe_use(player_ptr, slot),
106 ((o_ptr->number == 1) ? "is" : "are"), game_inscriptions[feel]);
111 msg_format("ザックの中の%s(%c)は%sという感じがする...", item_name.data(), index_to_label(slot), game_inscriptions[feel]);
113 msg_format("You feel the %s (%c) in your pack %s %s...", item_name.data(), index_to_label(slot), ((o_ptr->number == 1) ? "is" : "are"), game_inscriptions[feel]);
117 o_ptr->ident |= (IDENT_SENSE);
118 o_ptr->feeling = feel;
120 autopick_alter_item(player_ptr, slot, destroy_feeling);
121 player_ptr->update |= (PU_COMBINE | PU_REORDER);
122 player_ptr->window_flags |= (PW_INVEN | PW_EQUIP);
126 * @brief 1プレイヤーターン毎に武器、防具の擬似鑑定が行われるかを判定する。
128 * Sense the inventory\n
130 * Class 0 = Warrior --> fast and heavy\n
131 * Class 1 = Mage --> slow and light\n
132 * Class 2 = Priest --> fast but light\n
133 * Class 3 = Rogue --> okay and heavy\n
134 * Class 4 = Ranger --> slow but heavy (changed!)\n
135 * Class 5 = Paladin --> slow but heavy\n
137 void sense_inventory1(PlayerType *player_ptr)
139 PLAYER_LEVEL plev = player_ptr->lev;
142 if (player_ptr->effects()->confusion()->is_confused()) {
146 switch (player_ptr->pclass) {
147 case PlayerClassType::WARRIOR:
148 case PlayerClassType::ARCHER:
149 case PlayerClassType::SAMURAI:
150 case PlayerClassType::CAVALRY: {
151 if (0 != randint0(9000L / (plev * plev + 40))) {
158 case PlayerClassType::SMITH: {
159 if (0 != randint0(6000L / (plev * plev + 50))) {
166 case PlayerClassType::MAGE:
167 case PlayerClassType::HIGH_MAGE:
168 case PlayerClassType::SORCERER:
169 case PlayerClassType::MAGIC_EATER:
170 case PlayerClassType::ELEMENTALIST: {
171 if (0 != randint0(240000L / (plev + 5))) {
177 case PlayerClassType::PRIEST:
178 case PlayerClassType::BARD: {
179 if (0 != randint0(10000L / (plev * plev + 40))) {
185 case PlayerClassType::ROGUE:
186 case PlayerClassType::NINJA: {
187 if (0 != randint0(20000L / (plev * plev + 40))) {
194 case PlayerClassType::RANGER: {
195 if (0 != randint0(95000L / (plev * plev + 40))) {
202 case PlayerClassType::PALADIN:
203 case PlayerClassType::SNIPER: {
204 if (0 != randint0(77777L / (plev * plev + 40))) {
211 case PlayerClassType::WARRIOR_MAGE:
212 case PlayerClassType::RED_MAGE: {
213 if (0 != randint0(75000L / (plev * plev + 40))) {
219 case PlayerClassType::MINDCRAFTER:
220 case PlayerClassType::IMITATOR:
221 case PlayerClassType::BLUE_MAGE:
222 case PlayerClassType::MIRROR_MASTER: {
223 if (0 != randint0(55000L / (plev * plev + 40))) {
229 case PlayerClassType::CHAOS_WARRIOR: {
230 if (0 != randint0(80000L / (plev * plev + 40))) {
237 case PlayerClassType::MONK:
238 case PlayerClassType::FORCETRAINER: {
239 if (0 != randint0(20000L / (plev * plev + 40))) {
245 case PlayerClassType::TOURIST: {
246 if (0 != randint0(20000L / ((plev + 50) * (plev + 50)))) {
253 case PlayerClassType::BEASTMASTER: {
254 if (0 != randint0(65000L / (plev * plev + 40))) {
260 case PlayerClassType::BERSERKER: {
265 case PlayerClassType::MAX:
269 if (compare_virtue(player_ptr, Virtue::KNOWLEDGE, 100, VIRTUE_LARGE)) {
273 for (INVENTORY_IDX i = 0; i < INVEN_TOTAL; i++) {
274 o_ptr = &player_ptr->inventory_list[i];
281 switch (o_ptr->bi_key.tval()) {
282 case ItemKindType::SHOT:
283 case ItemKindType::ARROW:
284 case ItemKindType::BOLT:
285 case ItemKindType::BOW:
286 case ItemKindType::DIGGING:
287 case ItemKindType::HAFTED:
288 case ItemKindType::POLEARM:
289 case ItemKindType::SWORD:
290 case ItemKindType::BOOTS:
291 case ItemKindType::GLOVES:
292 case ItemKindType::HELM:
293 case ItemKindType::CROWN:
294 case ItemKindType::SHIELD:
295 case ItemKindType::CLOAK:
296 case ItemKindType::SOFT_ARMOR:
297 case ItemKindType::HARD_ARMOR:
298 case ItemKindType::DRAG_ARMOR:
299 case ItemKindType::CARD:
310 if ((i < INVEN_MAIN_HAND) && (0 != randint0(5))) {
314 if (has_good_luck(player_ptr) && !randint0(13)) {
318 sense_inventory_aux(player_ptr, i, heavy);
323 * @brief 1プレイヤーターン毎に武器、防具以外の擬似鑑定が行われるかを判定する。
325 void sense_inventory2(PlayerType *player_ptr)
327 PLAYER_LEVEL plev = player_ptr->lev;
330 if (player_ptr->effects()->confusion()->is_confused()) {
334 switch (player_ptr->pclass) {
335 case PlayerClassType::WARRIOR:
336 case PlayerClassType::ARCHER:
337 case PlayerClassType::SAMURAI:
338 case PlayerClassType::CAVALRY:
339 case PlayerClassType::BERSERKER:
340 case PlayerClassType::SNIPER: {
343 case PlayerClassType::SMITH:
344 case PlayerClassType::PALADIN:
345 case PlayerClassType::CHAOS_WARRIOR:
346 case PlayerClassType::IMITATOR:
347 case PlayerClassType::BEASTMASTER:
348 case PlayerClassType::NINJA: {
349 if (0 != randint0(240000L / (plev + 5))) {
355 case PlayerClassType::RANGER:
356 case PlayerClassType::WARRIOR_MAGE:
357 case PlayerClassType::RED_MAGE:
358 case PlayerClassType::MONK: {
359 if (0 != randint0(95000L / (plev * plev + 40))) {
365 case PlayerClassType::PRIEST:
366 case PlayerClassType::BARD:
367 case PlayerClassType::ROGUE:
368 case PlayerClassType::FORCETRAINER:
369 case PlayerClassType::MINDCRAFTER: {
370 if (0 != randint0(20000L / (plev * plev + 40))) {
376 case PlayerClassType::MAGE:
377 case PlayerClassType::HIGH_MAGE:
378 case PlayerClassType::SORCERER:
379 case PlayerClassType::MAGIC_EATER:
380 case PlayerClassType::MIRROR_MASTER:
381 case PlayerClassType::BLUE_MAGE:
382 case PlayerClassType::ELEMENTALIST: {
383 if (0 != randint0(9000L / (plev * plev + 40))) {
389 case PlayerClassType::TOURIST: {
390 if (0 != randint0(20000L / ((plev + 50) * (plev + 50)))) {
397 case PlayerClassType::MAX:
401 for (INVENTORY_IDX i = 0; i < INVEN_TOTAL; i++) {
403 o_ptr = &player_ptr->inventory_list[i];
408 switch (o_ptr->bi_key.tval()) {
409 case ItemKindType::RING:
410 case ItemKindType::AMULET:
411 case ItemKindType::LITE:
412 case ItemKindType::FIGURINE: {
425 if ((i < INVEN_MAIN_HAND) && (0 != randint0(5))) {
429 sense_inventory_aux(player_ptr, i, true);
434 * @brief 重度擬似鑑定の判断処理 / Return a "feeling" (or nullptr) about an item. Method 1 (Heavy).
435 * @param o_ptr 擬似鑑定を行うオブジェクトの参照ポインタ。
436 * @return 擬似鑑定結果のIDを返す。
438 item_feel_type pseudo_value_check_heavy(ItemEntity *o_ptr)
440 if (o_ptr->is_fixed_or_random_artifact()) {
441 if (o_ptr->is_cursed() || o_ptr->is_broken()) {
442 return FEEL_TERRIBLE;
448 if (o_ptr->is_ego()) {
449 if (o_ptr->is_cursed() || o_ptr->is_broken()) {
450 return FEEL_WORTHLESS;
453 return FEEL_EXCELLENT;
456 if (o_ptr->is_cursed()) {
460 if (o_ptr->is_broken()) {
464 const auto tval = o_ptr->bi_key.tval();
465 if ((tval == ItemKindType::RING) || (tval == ItemKindType::AMULET)) {
469 if (o_ptr->to_a > 0) {
473 if (o_ptr->to_h + o_ptr->to_d > 0) {
481 * @brief 軽度擬似鑑定の判断処理 / Return a "feeling" (or nullptr) about an item. Method 2 (Light).
482 * @param o_ptr 擬似鑑定を行うオブジェクトの参照ポインタ。
483 * @return 擬似鑑定結果のIDを返す。
485 item_feel_type pseudo_value_check_light(ItemEntity *o_ptr)
487 if (o_ptr->is_cursed()) {
491 if (o_ptr->is_broken()) {
495 if (o_ptr->is_fixed_or_random_artifact()) {
496 return FEEL_UNCURSED;
499 if (o_ptr->is_ego()) {
500 return FEEL_UNCURSED;
503 if (o_ptr->to_a > 0) {
504 return FEEL_UNCURSED;
507 if (o_ptr->to_h + o_ptr->to_d > 0) {
508 return FEEL_UNCURSED;