diff options
-rw-r--r-- | src/dungeon.cc | 109 | ||||
-rw-r--r-- | src/dungeon.hpp | 3 | ||||
-rw-r--r-- | src/object1.cc | 58 |
3 files changed, 94 insertions, 76 deletions
diff --git a/src/dungeon.cc b/src/dungeon.cc index abcc6cae..34dd781d 100644 --- a/src/dungeon.cc +++ b/src/dungeon.cc @@ -70,11 +70,15 @@ #define AUTO_CURSE_CHANCE 15 #define CHAINSWORD_NOISE 100 +/** + * Type of a "sense" function + */ +typedef byte (*sense_function_t)(object_type const *o_ptr); /* * Return a "feeling" (or NULL) about an item. Method 1 (Heavy). */ -static byte value_check_aux1(object_type *o_ptr) +static byte value_check_aux1(object_type const *o_ptr) { /* Artifacts */ if (artifact_p(o_ptr)) @@ -109,7 +113,7 @@ static byte value_check_aux1(object_type *o_ptr) return (SENSE_AVERAGE); } -static byte value_check_aux1_magic(object_type *o_ptr) +static byte value_check_aux1_magic(object_type const *o_ptr) { object_kind *k_ptr = &k_info[o_ptr->k_idx]; @@ -176,7 +180,7 @@ static byte value_check_aux1_magic(object_type *o_ptr) /* * Return a "feeling" (or NULL) about an item. Method 2 (Light). */ -static byte value_check_aux2(object_type *o_ptr) +static byte value_check_aux2(object_type const *o_ptr) { /* Cursed items (all of them) */ if (cursed_p(o_ptr)) return (SENSE_CURSED); @@ -198,7 +202,7 @@ static byte value_check_aux2(object_type *o_ptr) } -static byte value_check_aux2_magic(object_type *o_ptr) +static byte value_check_aux2_magic(object_type const *o_ptr) { object_kind *k_ptr = &k_info[o_ptr->k_idx]; @@ -278,9 +282,8 @@ static bool_ granted_resurrection(void) return (FALSE); } -static byte select_sense(object_type *o_ptr) +static sense_function_t select_sense(object_type *o_ptr, sense_function_t combat, sense_function_t magic) { - /* Valid "tval" codes */ switch (o_ptr->tval) { case TV_SHOT: @@ -305,8 +308,7 @@ static byte select_sense(object_type *o_ptr) case TV_BOOMERANG: case TV_TRAPKIT: { - return 1; - break; + return combat; } case TV_POTION: @@ -317,22 +319,21 @@ static byte select_sense(object_type *o_ptr) case TV_ROD: case TV_ROD_MAIN: { - return 2; - break; + return magic; } /* Dual use? */ case TV_DAEMON_BOOK: { - return 1; - break; + return combat; } } - return 0; + + return nullptr; } /* - * Sense the inventory + * Sense quality of specific list of objects. * * Combat items (weapons and armour) - Fast, weak if combat skill < 10, strong * otherwise. @@ -344,21 +345,8 @@ static byte select_sense(object_type *o_ptr) * they learn one form of ID or another, and because most magic items are * easy_know. */ -void sense_inventory(void) +void sense_objects(std::vector<int> const &object_idxs) { - int i, combat_lev, magic_lev; - - bool_ heavy_combat, heavy_magic; - - byte feel; - - object_type *o_ptr; - - char o_name[80]; - - - /*** Check for "sensing" ***/ - /* No sensing when confused */ if (p_ptr->confused) return; @@ -388,24 +376,21 @@ void sense_inventory(void) */ /* The combat skill affects weapon/armour pseudo-ID */ - combat_lev = get_skill(SKILL_COMBAT); + int combat_lev = get_skill(SKILL_COMBAT); /* The magic skill affects magic item pseudo-ID */ - magic_lev = get_skill(SKILL_MAGIC); + int magic_lev = get_skill(SKILL_MAGIC); /* Higher skill levels give the player better sense of items */ - heavy_combat = (combat_lev > 10) ? TRUE : FALSE; - heavy_magic = (magic_lev > 10) ? TRUE : FALSE; - + auto feel_combat = (combat_lev > 10) ? value_check_aux1 : value_check_aux2; + auto feel_magic = (magic_lev > 10) ? value_check_aux1_magic : value_check_aux2_magic; /*** Sense everything ***/ /* Check everything */ - for (i = 0; i < INVEN_TOTAL; i++) + for (auto i : object_idxs) { - byte okay = 0; - - o_ptr = &p_ptr->inventory[i]; + object_type *o_ptr = get_object(i); /* Skip empty slots */ if (!o_ptr->k_idx) continue; @@ -416,37 +401,39 @@ void sense_inventory(void) /* It is fully known, no information needed */ if (object_known_p(o_ptr)) continue; - /* Valid "tval" codes */ - okay = select_sense(o_ptr); + /* Select appropriate sensing function, if any */ + sense_function_t sense = select_sense(o_ptr, feel_combat, feel_magic); - /* Skip non-sense machines */ - if (!okay) continue; - - /* Check for a feeling */ - if (okay == 1) - { - feel = (heavy_combat ? value_check_aux1(o_ptr) : value_check_aux2(o_ptr)); - } - else + /* Skip non-sensed items */ + if (!sense) { - feel = (heavy_magic ? value_check_aux1_magic(o_ptr) : value_check_aux2_magic(o_ptr)); + continue; } + /* Check for a feeling */ + byte feel = sense(o_ptr); + /* Skip non-feelings */ - if (feel == SENSE_NONE) continue; + if (feel == SENSE_NONE) + { + continue; + } /* Get an object description */ + char o_name[80]; object_desc(o_name, o_ptr, FALSE, 0); - /* Message (equipment) */ - if (i >= INVEN_WIELD) + /* Messages */ + if (i < 0) { + // We get a message from the floor handling code, so + // it would be overkill to have a message here too. + } + else if (i >= INVEN_WIELD) { msg_format("You feel the %s (%c) you are %s %s %s...", o_name, index_to_label(i), describe_use(i), ((o_ptr->number == 1) ? "is" : "are"), sense_desc[feel]); } - - /* Message (inventory) */ else { msg_format("You feel the %s (%c) in your pack %s %s...", @@ -471,6 +458,20 @@ void sense_inventory(void) squeltch_inventory(); } +void sense_inventory(void) +{ + static std::vector<int> idxs; + // Initialize static vector if necessary + if (idxs.empty()) + { + idxs.reserve(INVEN_TOTAL); + for (int i = 0; i < INVEN_TOTAL; i++) + { + idxs.push_back(i); + } + } + sense_objects(idxs); +} /* * Go to any level (ripped off from wiz_jump) diff --git a/src/dungeon.hpp b/src/dungeon.hpp index 37d54d39..bbe6da87 100644 --- a/src/dungeon.hpp +++ b/src/dungeon.hpp @@ -1,3 +1,6 @@ #pragma once +#include <vector> + extern void sense_inventory(); +extern void sense_objects(std::vector<int> const &object_idxs); diff --git a/src/object1.cc b/src/object1.cc index cb1a6604..25b848a0 100644 --- a/src/object1.cc +++ b/src/object1.cc @@ -4229,7 +4229,7 @@ static cptr mention_use(int i) */ cptr describe_use(int i) { - cptr p; + cptr p = nullptr; switch (i) { @@ -6113,48 +6113,57 @@ void object_pickup(int this_o_idx) void py_pickup_floor(int pickup) { - s16b this_o_idx, next_o_idx = 0; - - char o_name[80] = ""; - object_type *o_ptr = 0; - - int floor_num = 0, floor_o_idx = 0; - - bool_ do_pickup = TRUE; - - bool_ do_ask = TRUE; - /* Hack -- ignore monster traps */ if (cave[p_ptr->py][p_ptr->px].feat == FEAT_MON_TRAP) return; /* Try to grab ammo */ pickup_ammo(); + /* Build a list of the floor objects. */ + std::vector<int> floor_object_idxs; + { + s16b this_o_idx = cave[p_ptr->py][p_ptr->px].o_idx; + /* Reserve a number of slots if at least one is needed */ + if (this_o_idx) + { + floor_object_idxs.reserve(16); // Avoid resizing in the common case + } + /* Fill in the indexes */ + for (; this_o_idx; this_o_idx = o_list[this_o_idx].next_o_idx) + { + // Note the "-"! We need it for get_object() + // lookups to function correctly. + floor_object_idxs.push_back(0 - this_o_idx); + } + } + /* Mega Hack -- If we have auto-Id, do an ID sweep *before* squleching, * so that we don't have to walk over things twice to get them * squelched. --dsb */ if (p_ptr->auto_id) { - this_o_idx = cave[p_ptr->py][p_ptr->px].o_idx; - - for (; this_o_idx; this_o_idx = next_o_idx) + for (auto const o_idx : floor_object_idxs) { - /* Aquire the object */ - o_ptr = &o_list[this_o_idx]; - - /* Acquire the next object index */ - next_o_idx = o_ptr->next_o_idx; - - /* Identify Object */ + object_type *o_ptr = get_object(o_idx); object_aware(o_ptr); object_known(o_ptr); } } + /* Sense floor tile */ + sense_objects(floor_object_idxs); + /* Squeltch the floor */ squeltch_grid(); /* Scan the pile of objects */ + s16b next_o_idx = 0; + char o_name[80] = ""; + object_type *o_ptr = 0; + int floor_num = 0; + int floor_o_idx = 0; + + s16b this_o_idx; for (this_o_idx = cave[p_ptr->py][p_ptr->px].o_idx; this_o_idx; this_o_idx = next_o_idx) { /* Acquire object */ @@ -6190,6 +6199,7 @@ void py_pickup_floor(int pickup) continue; } + /* Describe */ { char testdesc[80]; @@ -6234,6 +6244,10 @@ void py_pickup_floor(int pickup) return; } + /* Are we actually going to pick up and/or ask about which item to pick up? */ + bool_ do_pickup = TRUE; + bool_ do_ask = TRUE; + /* One item */ if (floor_num == 1) { |