Hero waves break in where the warning shows: they round the realm to the marked entry; the entry tile glows red

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-06 16:08:28 +01:00
1 parent dab31579df
commit bd3f42b8b8
3 files changed
+73 -4

No files matched your search

+25 -3
View File
@@ -4903,6 +4903,13 @@ impl Game {
if (e.x - wx as f32 - 0.5).abs() < 2.5 && (e.y - wy as f32 - 0.5).abs() < 2.5 {
e.waypoint = None; // broke into the realm: now for the core
e.path.clear();
} else if let Some(&next) = e.path.first() {
// the realm grew into the way (imps claim fast): round it again
let realm = self.map.t[idx(wx, wy)].owner;
if self.map.t[next].owner == realm && next != idx(wx, wy) && self.map.t[e.tile()].owner != realm {
e.path.clear();
e.repath = 0.0;
}
}
}
if e.path.is_empty() && e.repath <= 0.0 {
@@ -4910,7 +4917,8 @@ impl Game {
let path = match e.waypoint {
Some((wx, wy)) => {
let goal = idx(wx, wy);
let p = self.map.search(cur, self.map.hero_cost(), |i| i == goal, true);
// round the realm from outside: in through the marked entry, not before
let p = self.entry_path(cur, goal).or_else(|| self.map.search(cur, self.map.hero_cost(), |i| i == goal, true));
if p.is_none() {
e.waypoint = None;
}
@@ -4975,14 +4983,28 @@ impl Game {
scored.push(((x, y), score));
}
scored.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal));
let first = scored[0].0;
// only places the heroes can reach from the gate without crossing the realm first
let gate = idx(gx, gy);
let mut tried = 0;
let mut ok = |g: &Game, p: (i32, i32)| {
tried += 1;
tried > 12 || g.entry_path(gate, idx(p.0, p.1)).is_some()
};
let Some(first) = scored.iter().map(|s| s.0).find(|&p| ok(self, p)) else { return };
self.planned_entries.push(first);
// second entry point at least 10 tiles away (used by waves of 6+ heroes)
if let Some(&(second, _)) = scored.iter().find(|((x, y), _)| (x - first.0).pow(2) + (y - first.1).pow(2) >= 100) {
if let Some(second) = scored.iter().map(|s| s.0).filter(|&(x, y)| (x - first.0).pow(2) + (y - first.1).pow(2) >= 100).find(|&p| ok(self, p)) {
self.planned_entries.push(second);
}
}
// a hero's way to an entry tile that stays off the realm (the master's ground) until the entry
pub(crate) fn entry_path(&self, from: usize, goal: usize) -> Option<Vec<usize>> {
let owner = self.map.t[goal].owner;
let cost = self.map.hero_cost();
self.map.search(from, |i| if i != goal && i != from && self.map.t[i].owner == owner { None } else { cost(i) }, |i| i == goal, true)
}
// compass direction of a tile as seen from the core (language key)
pub fn direction_key(&self, (x, y): (i32, i32)) -> &'static str {
let (cx, cy) = (self.map.core.0 + 1, self.map.core.1 + 1);