From f13fb6fd227d1bf21cbef7542c487271a178a77c Mon Sep 17 00:00:00 2001 From: haranp Date: Mon, 16 Jun 2008 06:11:50 +0000 Subject: Finally implemented stack_iterator(), a way to iterate over objects in a stack without all that o = mitm[o].link stuff. Redid Ely's destroy weapons power to use it. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@5875 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/religion.cc | 28 ++++++++++--------------- crawl-ref/source/stuff.cc | 49 ++++++++++++++++++++++++++++++++++++++++++++ crawl-ref/source/stuff.h | 21 +++++++++++++++++++ 3 files changed, 81 insertions(+), 17 deletions(-) diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 0bbdd9de6f..df5340db9d 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -3021,35 +3021,30 @@ bool ely_destroy_weapons() god_acting gdact; bool success = false; - int i = igrd[you.x_pos][you.y_pos]; - while (i != NON_ITEM) + for ( stack_iterator si(you.pos()); si; ++si ) { - const int next = mitm[i].link; // In case we can't get it later. - - if (mitm[i].base_type != OBJ_WEAPONS - && mitm[i].base_type != OBJ_MISSILES - || item_is_stationary(mitm[i])) // Held in a net? + item_def& item(*si); + if ( (item.base_type != OBJ_WEAPONS + && item.base_type != OBJ_MISSILES) + || item_is_stationary(item)) // Held in a net? { - i = next; continue; } - if (!check_warning_inscriptions(mitm[i], OPER_DESTROY)) + if (!check_warning_inscriptions(item, OPER_DESTROY)) { mpr("Won't destroy {!D} inscribed item."); - i = next; continue; } - const int value = item_value( mitm[i], true ); + const int value = item_value( item, true ); #ifdef DEBUG_DIAGNOSTICS mprf(MSGCH_DIAGNOSTICS, "Destroyed weapon value: %d", value); #endif piety_gain_t pgain = PIETY_NONE; - bool is_evil_weapon = is_evil_item(mitm[i]); - if (is_evil_weapon - || _destroyed_valuable_weapon(value, mitm[i].base_type)) + const bool is_evil_weapon = is_evil_item(item); + if (is_evil_weapon || _destroyed_valuable_weapon(value, item.base_type)) { pgain = PIETY_SOME; gain_piety(1); @@ -3057,7 +3052,7 @@ bool ely_destroy_weapons() // Elyvilon doesn't care about item sacrifices at altars, so // I'm stealing _Sacrifice_Messages. - _print_sacrifice_message(GOD_ELYVILON, mitm[i], pgain); + _print_sacrifice_message(GOD_ELYVILON, item, pgain); if (is_evil_weapon) { // Print this is addition to the above! @@ -3065,9 +3060,8 @@ bool ely_destroy_weapons() GOD_ELYVILON); } - destroy_item(i); + destroy_item( si.link() ); success = true; - i = next; } if (!success) diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc index d2e1fbb52e..ea171db473 100644 --- a/crawl-ref/source/stuff.cc +++ b/crawl-ref/source/stuff.cc @@ -77,6 +77,55 @@ #include "tutorial.h" #include "view.h" +stack_iterator::stack_iterator(const coord_def& pos) +{ + cur_link = igrd(pos); + if ( cur_link != NON_ITEM ) + next_link = mitm[cur_link].link; + else + next_link = NON_ITEM; +} + +stack_iterator::stack_iterator(int start_link) +{ + cur_link = start_link; + if ( cur_link != NON_ITEM ) + next_link = mitm[cur_link].link; + else + next_link = NON_ITEM; +} + +stack_iterator::operator bool() const +{ + return ( cur_link != NON_ITEM ); +} + +item_def& stack_iterator::operator*() const +{ + ASSERT( cur_link != NON_ITEM ); + return mitm[cur_link]; +} + +int stack_iterator::link() const +{ + return cur_link; +} + +const stack_iterator& stack_iterator::operator ++ () +{ + cur_link = next_link; + if ( cur_link != NON_ITEM ) + next_link = mitm[cur_link].link; + return *this; +} + +stack_iterator stack_iterator::operator++(int dummy) +{ + const stack_iterator copy = *this; + ++(*this); + return copy; +} + radius_iterator::radius_iterator( const coord_def& _center, int _radius, bool _roguelike_metric, bool _require_los, bool _exclude_center ) diff --git a/crawl-ref/source/stuff.h b/crawl-ref/source/stuff.h index 66e492c7ca..3bb0221fca 100644 --- a/crawl-ref/source/stuff.h +++ b/crawl-ref/source/stuff.h @@ -48,6 +48,27 @@ int roll_dice( int num, int size ); int roll_dice( const struct dice_def &dice ); void scale_dice( dice_def &dice, int threshold = 24 ); +// stack_iterator guarantees validity so long as you don't manually +// mess with item_def.link: i.e., you can kill the item you're +// examining but you can't kill the item linked to it. +class stack_iterator : public std::iterator +{ +public: + stack_iterator( const coord_def& pos ); + stack_iterator( int start_link ); + + operator bool() const; + item_def& operator *() const; + int link() const; + + const stack_iterator& operator ++ (); + stack_iterator operator ++ (int); +private: + int cur_link; + int next_link; +}; + class radius_iterator : public std::iterator { -- cgit v1.2.3-54-g00ecf