git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@4127 c06c8d41-db1a-0410-9941-cceddc491573
VJDLV4PF2ZJ46NERO4LZUX5JE2CD5XBOBQCYYPTFWTHLUEYDUOYAC
B7MSPF6X2RLGWN4M6ZZF3WSOPKGYPTTD7LIJVST7DXN27DG6JHNAC
AUXVWXWIFSTWFA6VZXN2FMG7FQEKRZVV6MD32VQQ7J2RKCXHAVGAC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
475LL4U4ND6PTNV4XKC7WQAOJC7RF2VCCVX3DRILP2PKIBFYWE6QC
MSQI3TH6T62JAXQGLL52QZCWAMC372TGB6ZNNRDGUGMJKBNNV2VAC
BTO5WE4OEK64DZQVNYLOESM74KKQNE7KSNMQVF5UDB26OBKP7ORQC
45EMD3KLQPMERNMIKU5G76H6556XOMIW352TSBP7VLWJX2YYGS7AC
YYHCM4CUN6G5PFWPGOYMDYX4P3SGNYUT5SZK5AUWUL2G7RULQJDAC
EGV2HM7SD7UQSWJGLR65NQJTUBAJ7WHLM67FMH4UFP7JRSFKREPAC
VUP5G3CB6L5I5TPVWMM4KAMF6N4X6UPO4HQZKTSO2ETXZEFBMOMAC
CJWCTWT75S4P3OSCMUZ2W6UTWI6GOQMUSBUN6KEN4TVFEG4HHHGQC
// last updated 3jun2000 {dlb}
/* ***********************************************************************
* called from: acr - misc - mstuff2 - spells3
* *********************************************************************** */
int trap_at_xy(int which_x, int which_y);
// last updated 3jun2000 {dlb}
/* ***********************************************************************
* called from: acr - misc - mstuff2 - spells2 - spells3
* *********************************************************************** */
void destroy_trap( const coord_def& pos );
class radius_iterator : public std::iterator<std::bidirectional_iterator_tag,
coord_def>
{
public:
radius_iterator( const coord_def& center, int radius,
bool roguelike_metric = true,
bool require_los = true,
bool exclude_center = false );
bool done() const;
operator bool() const { return !done(); }
coord_def operator *() const;
const radius_iterator& operator ++ ();
const radius_iterator& operator -- ();
radius_iterator operator ++ (int);
radius_iterator operator -- (int);
private:
void step();
void step_back();
bool on_valid_square() const;
radius_iterator::radius_iterator( const coord_def& _center, int _radius,
bool _roguelike_metric, bool _require_los,
bool _exclude_center )
: center(_center), radius(_radius), roguelike_metric(_roguelike_metric),
require_los(_require_los), exclude_center(_exclude_center),
iter_done(false)
{
location.x = center.x - radius;
location.y = center.y - radius;
if ( !this->on_valid_square() )
++(*this);
}
bool radius_iterator::done() const
{
return iter_done;
}
coord_def radius_iterator::operator *() const
{
return location;
}
void radius_iterator::step()
{
const int minx = std::max(X_BOUND_1+1, center.x - radius);
const int maxx = std::min(X_BOUND_2-1, center.x + radius);
const int maxy = std::min(Y_BOUND_2-1, center.y + radius);
// Sweep L-R, U-D
location.x++;
if ( location.x > maxx )
{
location.x = minx;
location.y++;
if ( location.y > maxy )
iter_done = true;
}
}
void radius_iterator::step_back()
{
const int minx = std::max(X_BOUND_1+1, center.x - radius);
const int maxx = std::min(X_BOUND_2-1, center.x + radius);
const int miny = std::max(Y_BOUND_1+1, center.y - radius);
location.x--;
if ( location.x < minx )
{
location.x = maxx;
location.y--;
if ( location.y < miny )
iter_done = true; // hmm
}
}
bool radius_iterator::on_valid_square() const
{
if ( !in_bounds(location) )
return false;
if ( !roguelike_metric && (location - center).abs() > radius*radius )
return false;
if ( require_los && !see_grid(location) )
return false;
if ( exclude_center && location == center )
return false;
return true;
}
const radius_iterator& radius_iterator::operator++()
{
do {
this->step();
} while ( !this->done() && !this->on_valid_square() );
return *this;
}
const radius_iterator& radius_iterator::operator--()
{
do {
this->step_back();
} while ( !this->done() && !this->on_valid_square() );
return *this;
}
radius_iterator radius_iterator::operator++(int dummy)
{
const radius_iterator copy = *this;
++(*this);
return copy;
}
radius_iterator radius_iterator::operator--(int dummy)
{
const radius_iterator copy = *this;
--(*this);
return copy;
}
static void _create_pond(const coord_def& center, int radius, bool allow_deep)
{
radius_iterator ri(center, radius, false);
for ( ; ri; ++ri )
{
const coord_def p = *ri;
if ( p != you.pos() && coinflip() )
{
destroy_trap(p);
if ( grd(p) == DNGN_FLOOR )
{
if ( allow_deep )
grd(p) = coinflip() ? DNGN_SHALLOW_WATER : DNGN_DEEP_WATER;
else
grd(p) = DNGN_SHALLOW_WATER;
}
}
}
}
static void _deepen_water(const coord_def& center, int radius)
{
radius_iterator ri(center, radius, false);
for ( ; ri; ++ri )
{
// FIXME The iteration shouldn't affect the later squares in the
// same iteration, i.e., a newly-flooded square shouldn't count
// in the decision as to whether to make the next square flooded.
const coord_def p = *ri;
if ( grd(p) == DNGN_SHALLOW_WATER &&
p != you.pos() &&
random2(8) < 1 + count_neighbours(p.x, p.y, DNGN_DEEP_WATER) )
{
grd(p) = DNGN_DEEP_WATER;
}
if (grd(p) == DNGN_FLOOR &&
random2(3) < random2(count_neighbours(p.x,p.y,DNGN_DEEP_WATER) +
count_neighbours(p.x,p.y,DNGN_SHALLOW_WATER)))
{
grd(p) = DNGN_SHALLOW_WATER;
}
}
}
static void _pond_creature_effect( const coord_def& center, int radius )
{
radius_iterator ri(center, radius, false);
bool you_affected = false;
for ( ; ri; ++ri )
{
const coord_def p = *ri;
if ( p == you.pos() )
you_affected = true;
else if ( mgrd(p) != NON_MONSTER )
mons_check_pool( &menv[mgrd(p)], KILL_YOU );
}
if ( you_affected )
move_player_to_grid( you.x_pos, you.y_pos, false, true, true );
}
static void _water_card(int power, deck_rarity_type rarity)
{
const int power_level = get_power_level(power, rarity);
if ( power_level == 0 )
{
mpr("You create a pond!");
_create_pond(you.pos(), 4, false);
_pond_creature_effect(you.pos(), 4);
}
else if ( power_level == 1 )
{
mpr("You feel the tide rushing in!");
_create_pond(you.pos(), 6, true);
for ( int i = 0; i < 2; ++i )
_deepen_water(you.pos(), 6);
_pond_creature_effect(you.pos(), 5);
}
else
{
mpr("Water floods your area!");
// Flood all visible squares
radius_iterator ri( you.pos(), LOS_RADIUS, false );
for ( ; ri; ++ri )
{
coord_def p = *ri;
destroy_trap(p);
if ( grd(p) == DNGN_FLOOR )
{
dungeon_feature_type new_feature = DNGN_SHALLOW_WATER;
if ( p != you.pos() && coinflip() )
new_feature = DNGN_DEEP_WATER;
grd(p) = new_feature;
// In the future we might want to place all the water first,
// if monsters can scramble out.
if ( mgrd(p) != NON_MONSTER )
mons_check_pool( &menv[mgrd(p)], KILL_YOU );
}
}
move_player_to_grid( you.x_pos, you.y_pos, false, true, true );
}
}