summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/mon-iter.cc
diff options
context:
space:
mode:
authorRobert Vollmert <rvollmert@gmx.net>2009-11-11 14:57:35 +0100
committerRobert Vollmert <rvollmert@gmx.net>2009-11-11 16:26:20 +0100
commitf7b29b81395faf8ecbda4355bc85ef5619c7bd99 (patch)
treef3ad921bd794e7caf945cb57a61ea75f0a12f922 /crawl-ref/source/mon-iter.cc
parent4aebd25253db6f9509aa1ead548807abc3dbc5c3 (diff)
downloadcrawl-ref-f7b29b81395faf8ecbda4355bc85ef5619c7bd99.tar.gz
crawl-ref-f7b29b81395faf8ecbda4355bc85ef5619c7bd99.zip
Implement monster_iterator.
monster_iterator allows iterating over live monsters in env.mgrid, possibly subject to some location/visibility restrictions. Possible restrictions: - within some radius (circle_def::contains(mon->pos()) - position inside some LOS (los_def::see_cell(mon->pos()) - visible to some actor (actor::can_see(mon)) Sample use: for (int i = 0; i < MAX_MONSTERS; ++i) { monsters* const monster = &menv[i]; if (!monster->alive()) continue; // ... // becomes for (monster_iterator mi; mi; ++mi) { // ..., replacing monster-> by mi-> // and monster by *mi If you were checking for mons_near(monster), use monster_iterator mi(&you.get_los()); if you were checking for you.can_see(monster), use monster_iterator mi(&you); if you were checking for (monster->pos()-you.pos()).abs() <= r*r+1, use monster_iterator mi(circle_def(you.pos(), r, C_ROUND)). This is not as general as one might hope, but it should allow reducing the amount of code that knows how monsters are stored.
Diffstat (limited to 'crawl-ref/source/mon-iter.cc')
-rw-r--r--crawl-ref/source/mon-iter.cc87
1 files changed, 87 insertions, 0 deletions
diff --git a/crawl-ref/source/mon-iter.cc b/crawl-ref/source/mon-iter.cc
new file mode 100644
index 0000000000..1158a9028d
--- /dev/null
+++ b/crawl-ref/source/mon-iter.cc
@@ -0,0 +1,87 @@
+#include "AppHdr.h"
+
+#include "mon-iter.h"
+
+#include "actor.h"
+#include "coord-circle.h"
+#include "env.h"
+#include "monster.h"
+
+monster_iterator::monster_iterator()
+ : restr(R_NONE), curr_mid(0)
+{
+ advance(true);
+}
+
+monster_iterator::monster_iterator(const circle_def* circle_)
+ : restr(R_CIRC), curr_mid(0), circle(circle_)
+{
+ advance(true);
+}
+
+monster_iterator::monster_iterator(const los_def* los_)
+ : restr(R_LOS), curr_mid(0), los(los_)
+{
+ advance(true);
+}
+
+monster_iterator::monster_iterator(const actor* act_)
+ : restr(R_ACT), curr_mid(0), act(act_)
+{
+ advance(true);
+}
+
+monster_iterator::operator bool() const
+{
+ return (curr_mid < MAX_MONSTERS);
+}
+
+monsters* monster_iterator::operator*() const
+{
+ return (&env.mons[curr_mid]);
+}
+
+monsters* monster_iterator::operator->() const
+{
+ return (&env.mons[curr_mid]);
+}
+
+monster_iterator& monster_iterator::operator++()
+{
+ advance();
+ return (*this);
+}
+
+monster_iterator monster_iterator::operator++(int)
+{
+ monster_iterator copy = *this;
+ ++(*this);
+ return (copy);
+}
+
+bool monster_iterator::valid(int mid) const
+{
+ monsters* mon = &env.mons[mid];
+ if (!mon->alive())
+ return (false);
+ switch (restr)
+ {
+ case R_CIRC:
+ return (circle->contains(mon->pos()));
+ case R_LOS:
+ return (los->see_cell(mon->pos()));
+ case R_ACT:
+ return (act->can_see(mon));
+ default:
+ return (true);
+ }
+}
+
+void monster_iterator::advance(bool may_stay)
+{
+ if (!may_stay)
+ ++curr_mid;
+ while (curr_mid < MAX_MONSTERS && !valid(curr_mid))
+ ++curr_mid;
+}
+