diff options
author | Robert Vollmert <rvollmert@gmx.net> | 2009-11-11 14:57:35 +0100 |
---|---|---|
committer | Robert Vollmert <rvollmert@gmx.net> | 2009-11-11 16:26:20 +0100 |
commit | f7b29b81395faf8ecbda4355bc85ef5619c7bd99 (patch) | |
tree | f3ad921bd794e7caf945cb57a61ea75f0a12f922 | |
parent | 4aebd25253db6f9509aa1ead548807abc3dbc5c3 (diff) | |
download | crawl-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.
-rw-r--r-- | crawl-ref/source/makefile.obj | 1 | ||||
-rw-r--r-- | crawl-ref/source/mon-iter.cc | 87 | ||||
-rw-r--r-- | crawl-ref/source/mon-iter.h | 49 |
3 files changed, 137 insertions, 0 deletions
diff --git a/crawl-ref/source/makefile.obj b/crawl-ref/source/makefile.obj index c85450cd5f..ccbfb75aeb 100644 --- a/crawl-ref/source/makefile.obj +++ b/crawl-ref/source/makefile.obj @@ -103,6 +103,7 @@ mon-behv.o \ mon-cast.o \ mon-gear.o \ mon-info.o \ +mon-iter.o \ mon-pick.o \ mon-util.o \ monplace.o \ 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; +} + diff --git a/crawl-ref/source/mon-iter.h b/crawl-ref/source/mon-iter.h new file mode 100644 index 0000000000..7f31831c64 --- /dev/null +++ b/crawl-ref/source/mon-iter.h @@ -0,0 +1,49 @@ +/* + * Provide a way to iterator over all monsters, + * subject to a few common restrictions. + * + * TODO: + * - Iterate over actors? + */ + +#ifndef MON_ITER_H +#define MON_ITER_H + +enum restr_type +{ + R_NONE, + R_CIRC, + R_LOS, + R_ACT +}; + +class circle_def; +class los_def; +class actor; + +class monster_iterator +{ +public: + monster_iterator(); + monster_iterator(const circle_def* circle_); + monster_iterator(const los_def* los_); + monster_iterator(const actor* act_); + + operator bool() const; + monsters* operator*() const; + monsters* operator->() const; + monster_iterator& operator++(); + monster_iterator operator++(int); + +protected: + restr_type restr; + int curr_mid; + const circle_def* circle; + const los_def* los; + const actor* act; + + bool valid(int mid) const; + void advance(bool may_stay=false); +}; + +#endif |