summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/effects.cc
diff options
context:
space:
mode:
authordolorous <dolorous@c06c8d41-db1a-0410-9941-cceddc491573>2009-07-28 03:39:01 +0000
committerdolorous <dolorous@c06c8d41-db1a-0410-9941-cceddc491573>2009-07-28 03:39:01 +0000
commit72c1249ae7f4841dc8b335cb3a0a5ce81cb45887 (patch)
tree6b65ec871edba333b3ea18274025f52e4b384a24 /crawl-ref/source/effects.cc
parent102ecc248252562f59d7b7baf445cd5cdb2e3162 (diff)
downloadcrawl-ref-72c1249ae7f4841dc8b335cb3a0a5ce81cb45887.tar.gz
crawl-ref-72c1249ae7f4841dc8b335cb3a0a5ce81cb45887.zip
Apply caotto's patch in [2827204] to finish the plant god, with some
cleanups added by me. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@10442 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/effects.cc')
-rw-r--r--crawl-ref/source/effects.cc307
1 files changed, 157 insertions, 150 deletions
diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc
index bc40ef4a7e..02240e1c3e 100644
--- a/crawl-ref/source/effects.cc
+++ b/crawl-ref/source/effects.cc
@@ -1992,7 +1992,6 @@ static void _set_friendly_foes(bool allow_patrol = false)
{
monsters *mon(&menv[i]);
if (!mon->alive() || !mons_near(mon) || !mons_friendly_real(mon)
- || mon->has_ench(ENCH_BERSERK)
|| mon->mons_species() == MONS_GIANT_SPORE)
{
continue;
@@ -3808,14 +3807,14 @@ template<typename T>
struct greater_second
{
// The stl priority queue is a max queue and uses < as the default
- // comparison. We want a min queue so we have to use a > operation here.
+ // comparison. We want a min queue so we have to use a > operation
+ // here.
bool operator()(const T & left, const T & right)
{
- return left.second > right.second;
+ return (left.second > right.second);
}
};
-
// Basically we want to break a circle into n_arcs equal sized arcs and find
// out which arc the input point pos falls on.
static int _arc_decomposition(const coord_def & pos, int n_arcs)
@@ -3826,196 +3825,205 @@ static int _arc_decomposition(const coord_def & pos, int n_arcs)
theta = pos.y > 0 ? PI / 2 : -PI / 2;
if (theta < 0)
- theta += 2*PI;
+ theta += 2 * PI;
- float arc_angle = 2*PI / n_arcs;
+ float arc_angle = 2 * PI / n_arcs;
theta += arc_angle / 2.0f;
- if (theta >= 2*PI)
- theta -= 2*PI;
+ if (theta >= 2 * PI)
+ theta -= 2 * PI;
return static_cast<int> (theta / arc_angle);
}
-// Place a partial ring of toadstools around the given corpse. returns the
-// number of mushrooms spawned. A return of 0 indicates no mushrooms were
-// placed -> some sort of failure mode was reached.
-static int _mushroom_ring(item_def &corpse, int & seen_count)
+int place_ring(std::vector<coord_def> & ring_points,
+ coord_def & origin,
+ mgen_data & prototype,
+ int n_arcs,
+ int arc_occupancy,
+ int & seen_count)
{
+ std::random_shuffle(ring_points.begin(),
+ ring_points.end());
- // minimum number of mushrooms spawned on a given ring
- unsigned min_spawn = 2;
+ int target_amount = ring_points.size();
+ int spawned_count = 0;
+ seen_count = 0;
- // highest radius we will allow. 8 is LOS
- const int max_radius = LOS_RADIUS;
+ std::vector<int> arc_counts(n_arcs, arc_occupancy);
- seen_count = 0;
+ for (unsigned i = 0;
+ spawned_count < target_amount && i < ring_points.size();
+ i++)
+ {
+ int direction = _arc_decomposition(ring_points.at(i)
+ - origin, n_arcs);
- // Just want to associate a point with a distance here for convenience
- typedef std::pair<coord_def, int> coord_dist;
+ if (arc_counts[direction]-- <= 0)
+ continue;
+
+ prototype.pos = ring_points.at(i);
+ const int mushroom = create_monster(prototype, false);
+
+ if (mushroom != -1)
+ {
+ spawned_count++;
+ if (see_grid(ring_points.at(i)))
+ seen_count++;
+ }
+ }
+
+ return (spawned_count);
+}
+
+// Collect lists of points that are within LOS (under the given env map),
+// unoccupied, and not solid (walls/statues).
+void collect_radius_points(std::vector<std::vector<coord_def> > &radius_points,
+ coord_def & origin, env_show_grid & losgrid)
+{
+
+ radius_points.clear();
+ radius_points.resize(LOS_RADIUS);
+
+ // Just want to associate a point with a distance here for convenience.
+ typedef std::pair<coord_def, int> coord_dist;
// Using a priority queue because squares don't make very good circles at
- // larger radii.
- // Generally we will visit points in order of distance to the origin
- // (not path distance) under distance=sqrt(x^2+y^2-1);
+ // larger radii. We will visit points in order of increasing euclidean
+ // distance from the origin (not path distance).
std::priority_queue<coord_dist,
std::vector<coord_dist>,
greater_second<coord_dist> > fringe;
- coord_dist origin(corpse.pos, 0);
-
- fringe.push(origin);
+ fringe.push(coord_dist(origin, 0));
std::set<int> visited_indices;
- int max_distance = max_radius * max_radius - 1;
+ int current_r = 1;
+ int current_thresh = current_r * (current_r + 1);
- std::vector<coord_def> radius_points[max_radius];
+ int max_distance = LOS_RADIUS * LOS_RADIUS;
- int max_visited = 0;
while (!fringe.empty())
{
coord_dist current = fringe.top();
- fringe.pop();
-
- int idx = current.first.x + current.first.y * X_WIDTH;
-
- if (!visited_indices.insert(idx).second)
- continue;
-
- // we're done here once we hit a point that is farther away from the
+ // We're done here once we hit a point that is farther away from the
// origin than our maximum permissible radius.
if (current.second > max_distance)
break;
- if (current.second > max_visited)
- max_visited = current.second;
+ fringe.pop();
- float current_distance =current.second ? sqrtf(current.second + 1) : 0;
- int bound = static_cast<int> (current_distance + 0.5);
+ int idx = current.first.x + current.first.y * X_WIDTH;
+ if (!visited_indices.insert(idx).second)
+ continue;
- // We don't include radius 0 as an option. This is also a good place
- // to check if the squares is already occupied since we want to search
- // past occupied squares but don't want to place toadstools on them.
- if (bound > 0 && !actor_at(current.first))
+ while (current.second > current_thresh)
{
- radius_points[bound - 1].push_back(current.first);
+ current_r++;
+ current_thresh = current_r * (current_r + 1);
}
+ // We don't include radius 0. This is also a good place to check if
+ // the squares are already occupied since we want to search past
+ // occupied squares but don't want to consider them valid targets.
+ if (current.second && !actor_at(current.first))
+ radius_points[current_r - 1].push_back(current.first);
+
for (adjacent_iterator i(current.first); i; ++i)
{
coord_dist temp(*i, current.second);
- coord_def local = temp.first - origin.first;
+ // If the grid is out of LOS, skip it.
+ if (!see_grid(losgrid, origin, temp.first))
+ continue;
- temp.second = local.x * local.x + local.y * local.y - 1;
+ coord_def local = temp.first - origin;
- // Don't link to nodes with a smaller absolute distance from the
- // origin than the current node. This is some sort of connectivity
- // constraint, in general we don't want parts of a ring to be
- // connected via a higher radius since rings were supposedly
- // created by outwards expansion.
- if (temp.second < max_visited)
- continue;
+ temp.second = local.abs();
idx = temp.first.x + temp.first.y * X_WIDTH;
if (visited_indices.find(idx) == visited_indices.end()
&& in_bounds(temp.first)
- && mons_class_can_pass(MONS_TOADSTOOL, grd(temp.first)))
+ && !grid_is_solid(temp.first))
{
fringe.push(temp);
}
}
}
+}
+
+// Place a partial ring of toadstools around the given corpse. Returns
+// the number of mushrooms spawned. A return of 0 indicates no
+// mushrooms were placed -> some sort of failure mode was reached.
+static int _mushroom_ring(item_def &corpse, int & seen_count)
+{
+ // minimum number of mushrooms spawned on a given ring
+ unsigned min_spawn = 2;
+
+ seen_count = 0;
+
+ std::vector<std::vector<coord_def> > radius_points;
+
+ env_show_grid losgrid;
+ losight(losgrid, grd, corpse.pos, true);
+
+ collect_radius_points(radius_points,corpse.pos, losgrid);
// So what we have done so far is collect the set of points at each radius
// reachable from the origin with (somewhat constrained) 8 connectivity,
// now we will choose one of those radii and spawn mushrooms at some
// of the points along it.
+ int chosen_idx = random2(LOS_RADIUS);
- int chosen_idx = random2(max_radius);
-
- // Excluding radius 1 rings because they don't look particularly good
- // (or at least they don't look good with target_arc_len=2sqrt(2)
- // they look ok with arc_len=2, but that doesn't seem very good for
- // higher radii, maybe there should be a more complicated relationship
- // between radius and target arc length, but whatever).
- int min_idx=1;
-
- for (int i = 2; i < max_radius; i++, chosen_idx++)
+ unsigned max_size = 0;
+ for (unsigned i = 0; i < LOS_RADIUS; ++i)
{
- chosen_idx = chosen_idx % max_radius;
-
- if (chosen_idx >= min_idx
- && radius_points[chosen_idx].size() >= min_spawn)
+ if (radius_points[i].size() >= max_size)
{
- break;
+ max_size = radius_points[i].size();
+ chosen_idx = i;
}
}
- // Couldn't find enough valid points at any radius?
- if (radius_points[chosen_idx].size() < min_spawn)
- return 0;
+ chosen_idx = random2(chosen_idx + 1);
- std::random_shuffle(radius_points[chosen_idx].begin(),
- radius_points[chosen_idx].end());
+ // Not enough valid points?
+ if (radius_points[chosen_idx].size() < min_spawn)
+ return (0);
- int target_amount = radius_points[chosen_idx].size();
- int spawned_count = 0;
+ mgen_data temp(MONS_TOADSTOOL,
+ BEH_HOSTILE, 0, 0,
+ coord_def(),
+ MHITNOT,
+ MG_FORCE_PLACE,
+ GOD_NO_GOD,
+ MONS_PROGRAM_BUG,
+ 0,
+ corpse.colour);
- float target_arc_len=2*sqrtf(2.0f);
- //float target_arc_len = 2;
+ float target_arc_len = 2 * sqrtf(2.0f);
- int n_arcs = static_cast<int> (ceilf(2*PI * (chosen_idx + 1)
+ int n_arcs = static_cast<int> (ceilf(2 * PI * (chosen_idx + 1)
/ target_arc_len));
- int mushrooms_per_arc = 1;
-
- std::vector<int> arc_counts(n_arcs, mushrooms_per_arc);
-
- for (unsigned i = 0;
- spawned_count < target_amount && i < radius_points[chosen_idx].size();
- i++)
- {
- int direction = _arc_decomposition(radius_points[chosen_idx].at(i)
- - origin.first, n_arcs);
-
- if (arc_counts[direction]-- <= 0)
- continue;
+ int spawned_count = place_ring(radius_points[chosen_idx], corpse.pos, temp,
+ n_arcs, 1, seen_count);
- const int mushroom = create_monster(
- mgen_data(MONS_TOADSTOOL,
- BEH_HOSTILE, 0, 0,
- radius_points[chosen_idx].at(i),
- MHITNOT,
- MG_FORCE_PLACE,
- GOD_NO_GOD,
- MONS_PROGRAM_BUG,
- 0,
- corpse.colour),
- false);
-
- if (mushroom != -1)
- {
- spawned_count++;
- if (see_grid(radius_points[chosen_idx].at(i)))
- seen_count++;
- }
- }
-
- return spawned_count;
+ return (spawned_count);
}
-// Try to spawn 'target_count' mushrooms around the position of 'corpse'.
-// Returns the number of mushrooms actually spawned.
-// Mushrooms radiate outwards from the corpse following bfs with 8-connectivity.
-// Could change the expansion pattern by using a priority queue for
-// sequencing (priority = distance from origin under some metric).
+// Try to spawn 'target_count' mushrooms around the position of
+// 'corpse'. Returns the number of mushrooms actually spawned.
+// Mushrooms radiate outwards from the corpse following bfs with
+// 8-connectivity. Could change the expansion pattern by using a
+// priority queue for sequencing (priority = distance from origin under
+// some metric).
int spawn_corpse_mushrooms(item_def &corpse,
int target_count,
int & seen_targets,
@@ -4025,7 +4033,7 @@ int spawn_corpse_mushrooms(item_def &corpse,
if (target_count == 0)
return 0;
- int c_size=8;
+ int c_size = 8;
int permutation[] = {0, 1, 2, 3, 4, 5, 6, 7};
int placed_targets = 0;
@@ -4034,32 +4042,32 @@ int spawn_corpse_mushrooms(item_def &corpse,
std::set<int> visited_indices;
// Slight chance of spawning a ring of mushrooms around the corpse (and
- // skeletonizing it) if the corpse square is unoccupied.
+ // skeletonising it) if the corpse square is unoccupied.
if (!actor_at(corpse.pos) && one_chance_in(100))
{
int ring_seen;
// It's possible no reasonable ring can be found, in that case we'll
- // give up and just place a toadstool on top of the corpse (probably)
- int res=_mushroom_ring(corpse, ring_seen);
+ // give up and just place a toadstool on top of the corpse (probably).
+ int res = _mushroom_ring(corpse, ring_seen);
if (res)
{
- corpse.special=0;
+ corpse.special = 0;
+
if (see_grid(corpse.pos))
mpr("A ring of toadstools grow before your very eyes.");
else if (ring_seen > 1)
mpr("Some toadstools grow in a peculiar arc.");
- else if (ring_seen >0)
+ else if (ring_seen > 0)
mpr("A toadstool grows.");
seen_targets = -1;
-
- return res;
+ return (res);
}
}
- visited_indices.insert(X_WIDTH*corpse.pos.y + corpse.pos.x);
+ visited_indices.insert(X_WIDTH * corpse.pos.y + corpse.pos.x);
fringe.push(corpse.pos);
while (!fringe.empty())
@@ -4069,7 +4077,8 @@ int spawn_corpse_mushrooms(item_def &corpse,
fringe.pop();
actor * occupant = NULL;
- // is this square occupied by a non mushroom?
+
+ // Is this square occupied by a non mushroom?
if ((occupant = actor_at(current))
&& occupant->mons_species() != MONS_TOADSTOOL)
{
@@ -4102,7 +4111,7 @@ int spawn_corpse_mushrooms(item_def &corpse,
{
coord_def offset = corpse.pos - current;
- int dist = static_cast<int> (sqrtf(offset.abs()) + 0.5);
+ int dist = static_cast<int>(sqrtf(offset.abs()) + 0.5);
int time_left = random2(8) + dist * 8 + 1;
@@ -4116,24 +4125,22 @@ int spawn_corpse_mushrooms(item_def &corpse,
placed_targets++;
if (see_grid(current))
- {
seen_targets++;
- }
}
else
continue;
}
- // We're done here if we place the desired number of mushrooms.
+ // We're done here if we placed the desired number of mushrooms.
if (placed_targets == target_count)
break;
- // wish adjacent_iterator had a random traversal
+ // Wish adjacent_iterator had a random traversal.
std::random_shuffle(permutation, permutation+c_size);
for (int count = 0; count < c_size; ++count)
{
- coord_def temp=current + Compass[permutation[count]];
+ coord_def temp = current + Compass[permutation[count]];
int index = temp.x + temp.y * X_WIDTH;
@@ -4148,12 +4155,12 @@ int spawn_corpse_mushrooms(item_def &corpse,
}
}
- return placed_targets;
+ return (placed_targets);
}
int mushroom_prob(item_def & corpse)
{
- int low_threshold = 5;
+ int low_threshold = 5;
int high_threshold = FRESHEST_CORPSE - 5;
// Expect this many trials over a corpse's lifetime since this function
@@ -4161,32 +4168,32 @@ int mushroom_prob(item_def & corpse)
int step_size = 10;
float total_trials = (high_threshold - low_threshold) / step_size;
- // chance of producing no mushrooms (not really because of weight_factor
- // below)
- float p_failure = .5;
+ // Chance of producing no mushrooms (not really because of weight_factor
+ // below).
+ float p_failure = 0.5f;
float trial_prob_f = 1 - powf(p_failure, 1.0f / total_trials);
// The chance of producing mushrooms depends on the weight of the
- // corpse involved. Humans weigh 550 so we will take that as the
+ // corpse involved. Humans weigh 550 so we will take that as the
// base factor here.
- float weight_factor = item_mass(corpse)/550.0f;
+ float weight_factor = item_mass(corpse) / 550.0f;
trial_prob_f *= weight_factor;
- int trial_prob = static_cast<int> (100* trial_prob_f );
+ int trial_prob = static_cast<int>(100 * trial_prob_f);
- return trial_prob;
+ return (trial_prob);
}
-
-// Randomly decide whether or not to spawn a mushroom over the given corpse
-// Assumption: this is called before the rotting away logic in update_corpses.
-// Some conditions in this function may set the corpse timer to 0, assuming
-// that the corpse will be turned into a skeleton/destroyed on this update.
+// Randomly decide whether or not to spawn a mushroom over the given
+// corpse. Assumption: this is called before the rotting away logic in
+// update_corpses. Some conditions in this function may set the corpse
+// timer to 0, assuming that the corpse will be turned into a
+// skeleton/destroyed on this update.
static void _maybe_spawn_mushroom(item_def & corpse, int rot_time)
{
- // We won't spawn a mushroom within 10 turns of the corpse being created
+ // We won't spawn a mushroom within 10 turns of the corpse's being created
// or rotting away.
int low_threshold = 5;
int high_threshold = FRESHEST_CORPSE - 5;