From 7053bb10bf5fdd53809b136fa5f48e5449414441 Mon Sep 17 00:00:00 2001
From: Eduardo Gonzalez <ed.gonzalez3@gmail.com>
Date: Wed, 7 May 2014 02:59:10 -0700
Subject: [PATCH 2/3] Recalculate cache of equipped unrands with world_reacts
 on save load

This allows us to more easily add or remove those hooks on existing unrands.
The data type has also been changed to FixedBitVector from unsigned short,
allowing the expanded ring slots to be referenced.
---
 crawl-ref/source/artefact.cc      |  2 +-
 crawl-ref/source/bitary.h         |  5 +++++
 crawl-ref/source/player-equip.cc  |  8 ++++----
 crawl-ref/source/player-reacts.cc |  2 +-
 crawl-ref/source/player.cc        |  2 +-
 crawl-ref/source/player.h         |  2 +-
 crawl-ref/source/tag-version.h    |  1 +
 crawl-ref/source/tags.cc          | 20 ++++++++++++++++++--
 8 files changed, 32 insertions(+), 10 deletions(-)

diff --git a/crawl-ref/source/artefact.cc b/crawl-ref/source/artefact.cc
index 56b03d1..574ccf5 100644
--- a/crawl-ref/source/artefact.cc
+++ b/crawl-ref/source/artefact.cc
@@ -2071,7 +2071,7 @@ void unrand_reacts()
 
     for (int i = 0; i < NUM_EQUIP; i++)
     {
-        if (you.unrand_reacts & (1 << i))
+        if (you.unrand_reacts[i])
         {
             item_def&        item  = you.inv[you.equip[i]];
             const unrandart_entry* entry = get_unrand_entry(item.special);
diff --git a/crawl-ref/source/bitary.h b/crawl-ref/source/bitary.h
index 8cadb3c..139950b 100644
--- a/crawl-ref/source/bitary.h
+++ b/crawl-ref/source/bitary.h
@@ -83,6 +83,11 @@ public:
         return data.count();
     }
 
+    inline bool any() const
+    {
+        return data.any();
+    }
+
     inline FixedBitVector<SIZE>& operator|=(const FixedBitVector<SIZE>&x)
     {
         data |= x.data;
diff --git a/crawl-ref/source/player-equip.cc b/crawl-ref/source/player-equip.cc
index ac505c2..7977041 100644
--- a/crawl-ref/source/player-equip.cc
+++ b/crawl-ref/source/player-equip.cc
@@ -215,8 +215,8 @@ static void _equip_artefact_effect(item_def &item, bool *show_msgs, bool unmeld)
 
         if (entry->world_reacts_func)
         {
-            equipment_type eq = get_item_slot(item.base_type, item.sub_type);
-            you.unrand_reacts |= (1 << eq);
+            equipment_type slot = get_item_slot(item.base_type, item.sub_type);
+            you.unrand_reacts.set(slot);
         }
     }
 
@@ -348,8 +348,8 @@ static void _unequip_artefact_effect(item_def &item,
 
         if (entry->world_reacts_func)
         {
-            equipment_type eq = get_item_slot(item.base_type, item.sub_type);
-            you.unrand_reacts &= ~(1 << eq);
+            equipment_type slot = get_item_slot(item.base_type, item.sub_type);
+            you.unrand_reacts.set(slot, false);
         }
     }
 }
diff --git a/crawl-ref/source/player-reacts.cc b/crawl-ref/source/player-reacts.cc
index a1fa4d9..6ce8925 100644
--- a/crawl-ref/source/player-reacts.cc
+++ b/crawl-ref/source/player-reacts.cc
@@ -1253,7 +1253,7 @@ void player_reacts()
 
     _check_equipment_conducts();
 
-    if (you.unrand_reacts != 0)
+    if (you.unrand_reacts.any())
         unrand_reacts();
 
     // Handle sound-dependent effects that are silenced
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index 8ecd791..6edbdac 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -5874,7 +5874,7 @@ void player::init()
 
     equip.init(-1);
     melded.reset();
-    unrand_reacts   = 0;
+    unrand_reacts.reset();
 
     symbol          = MONS_PLAYER;
     form            = TRAN_NONE;
diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h
index fb81221..35fc6ad 100644
--- a/crawl-ref/source/player.h
+++ b/crawl-ref/source/player.h
@@ -79,7 +79,7 @@ public:
 
   FixedVector<int8_t, NUM_EQUIP> equip;
   FixedBitVector<NUM_EQUIP> melded;
-  unsigned short unrand_reacts;
+  FixedBitVector<NUM_EQUIP> unrand_reacts;
 
   FixedArray<int, NUM_OBJECT_CLASSES, MAX_SUBTYPES> force_autopickup;
 
diff --git a/crawl-ref/source/tag-version.h b/crawl-ref/source/tag-version.h
index d4be991..7b72129 100644
--- a/crawl-ref/source/tag-version.h
+++ b/crawl-ref/source/tag-version.h
@@ -94,6 +94,7 @@ enum tag_minor_version
     TAG_MINOR_BRIBE_BRANCH,        // Bribe branch tracking
     TAG_MINOR_CLOUD_OWNER,         // Track owners of clouds in map knowledge
     TAG_MINOR_NO_DEVICE_HEAL,      // Made MUT_NO_DEVICE_HEAL a normal bad mutation.
+    TAG_MINOR_CALC_UNRAND_REACTS,  // Compute you.unrand_reacts on load
 #endif
     NUM_TAG_MINORS,
     TAG_MINOR_VERSION = NUM_TAG_MINORS - 1
diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc
index 4d7be78..30df2d1 100644
--- a/crawl-ref/source/tags.cc
+++ b/crawl-ref/source/tags.cc
@@ -1291,7 +1291,6 @@ static void tag_construct_you(writer &th)
     marshallByte(th, you.royal_jelly_dead);
     marshallByte(th, you.transform_uncancellable);
     marshallByte(th, you.is_undead);
-    marshallShort(th, you.unrand_reacts);
     marshallByte(th, you.berserk_penalty);
     marshallInt(th, you.abyss_speed);
 
@@ -2120,7 +2119,10 @@ static void tag_read_you(reader &th)
 
     you.is_undead         = static_cast<undead_state_type>(unmarshallUByte(th));
     ASSERT(you.is_undead <= US_SEMI_UNDEAD);
-    you.unrand_reacts     = unmarshallShort(th);
+#if TAG_MAJOR_VERSION == 34
+    if (th.getMinorVersion() < TAG_MINOR_CALC_UNRAND_REACTS)
+      unmarshallShort(th);
+#endif
     you.berserk_penalty   = unmarshallByte(th);
 #if TAG_MAJOR_VERSION == 34
     if (th.getMinorVersion() >= TAG_MINOR_GARGOYLE_DR
@@ -2952,6 +2954,20 @@ static void tag_read_you_items(reader &th)
     for (i = 0; i < count; ++i)
         unmarshallItem(th, you.inv[i]);
 
+    // Initialize cache of equipped unrand functions
+    for (i = 0; i < NUM_EQUIP; ++i)
+    {
+        const item_def *item = you.slot_item(static_cast<equipment_type>(i));
+
+        if (item && is_unrandom_artefact(*item))
+        {
+            const unrandart_entry *entry = get_unrand_entry(item->special);
+
+            if (entry->world_reacts_func)
+                you.unrand_reacts.set(i);
+        }
+    }
+
     unmarshallFixedBitVector<NUM_RUNE_TYPES>(th, you.runes);
     you.obtainable_runes = unmarshallByte(th);
 
-- 
1.9.1

