Let flyers path over water and lava everywhere
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
574660e173
commit
1ef2239fbf
7 files changed
+85
-23
No files matched your search
+47
-10
@@ -1692,7 +1692,7 @@ impl Game {
|
||||
}
|
||||
let cur = e.tile();
|
||||
let near = |i: usize| tasks.iter().copied().find(|&t| i != t && adj4(i, t) || (i == t && self.map.t[t].walkable()));
|
||||
let Some(p) = self.map.search(cur, self.map.walk_cost(), |i| near(i).is_some(), true) else { return false };
|
||||
let Some(p) = self.map.search(cur, self.map.creature_cost(flies(e.kind)), |i| near(i).is_some(), true) else { return false };
|
||||
let end = p.last().copied().unwrap_or(cur);
|
||||
let Some(t) = near(end) else { return false };
|
||||
e.path = p;
|
||||
@@ -3387,10 +3387,10 @@ impl Game {
|
||||
|
||||
// ---------------------------------------------------------------- creatures
|
||||
|
||||
fn find_room_tile(&self, cur: usize, kind: Kind, me: u32, need_food: bool) -> Option<Vec<usize>> {
|
||||
fn find_room_tile(&self, e: &Ent, kind: Kind, me: u32, need_food: bool) -> Option<Vec<usize>> {
|
||||
self.map.search(
|
||||
cur,
|
||||
self.map.walk_cost(),
|
||||
e.tile(),
|
||||
self.map.creature_cost(flies(e.kind)),
|
||||
|i| {
|
||||
let t = &self.map.t[i];
|
||||
t.kind == kind && t.owner == self.me && (t.reserved == 0 || t.reserved == me) && (!need_food || t.food >= 1.0)
|
||||
@@ -3905,7 +3905,7 @@ impl Game {
|
||||
return;
|
||||
}
|
||||
if e.hunger > 1.0 && !(self.flag.is_some() && e.hunger < 1.5) {
|
||||
if let Some(p) = self.find_room_tile(cur, Kind::Farm, me, true) {
|
||||
if let Some(p) = self.find_room_tile(e, Kind::Farm, me, true) {
|
||||
let t = p.last().copied().unwrap_or(cur);
|
||||
self.map.t[t].reserved = me;
|
||||
e.path = p;
|
||||
@@ -3939,7 +3939,7 @@ impl Game {
|
||||
if self.counts[6] > 0 {
|
||||
let r2 = self.rng.f();
|
||||
if r2 < 0.3 || (e.kind == EK::Priestess && r2 < 0.7) {
|
||||
if let Some(p) = self.find_room_tile(cur, Kind::Temple, me, false) {
|
||||
if let Some(p) = self.find_room_tile(e, Kind::Temple, me, false) {
|
||||
let t = p.last().copied().unwrap_or(cur);
|
||||
self.map.t[t].reserved = me;
|
||||
e.path = p;
|
||||
@@ -3974,7 +3974,7 @@ impl Game {
|
||||
}
|
||||
}
|
||||
if self.counts[crate::rooms::ROOM_ARENA] > 0 && e.hp > e.max_hp * 0.8 && self.rng.f() < 0.25 {
|
||||
if let Some(p) = self.find_room_tile(cur, Kind::Arena, me, false) {
|
||||
if let Some(p) = self.find_room_tile(e, Kind::Arena, me, false) {
|
||||
let t = p.last().copied().unwrap_or(cur);
|
||||
self.map.t[t].reserved = me;
|
||||
e.path = p;
|
||||
@@ -3987,7 +3987,7 @@ impl Game {
|
||||
if self.forge_orders() && self.counts[ROOM_FORGE] > 0 {
|
||||
let r = self.rng.f();
|
||||
if (e.kind == EK::Cogling && r < 0.9) || r < 0.25 {
|
||||
if let Some(p) = self.find_room_tile(cur, Kind::Forge, me, false) {
|
||||
if let Some(p) = self.find_room_tile(e, Kind::Forge, me, false) {
|
||||
let t = p.last().copied().unwrap_or(cur);
|
||||
self.map.t[t].reserved = me;
|
||||
e.path = p;
|
||||
@@ -3999,7 +3999,7 @@ impl Game {
|
||||
}
|
||||
let r = self.rng.f();
|
||||
if (e.kind == EK::Mage && r < 0.8) || r < 0.2 {
|
||||
if let Some(p) = self.find_room_tile(cur, Kind::Library, me, false) {
|
||||
if let Some(p) = self.find_room_tile(e, Kind::Library, me, false) {
|
||||
let t = p.last().copied().unwrap_or(cur);
|
||||
self.map.t[t].reserved = me;
|
||||
e.path = p;
|
||||
@@ -4009,7 +4009,7 @@ impl Game {
|
||||
}
|
||||
}
|
||||
if r < 0.8 && self.gold >= 5.0 {
|
||||
if let Some(p) = self.find_room_tile(cur, Kind::Training, me, false) {
|
||||
if let Some(p) = self.find_room_tile(e, Kind::Training, me, false) {
|
||||
let t = p.last().copied().unwrap_or(cur);
|
||||
self.map.t[t].reserved = me;
|
||||
e.path = p;
|
||||
@@ -5935,6 +5935,43 @@ mod tests {
|
||||
assert!(best <= 2.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flyers_take_every_way_across_rivers() {
|
||||
let (mut g, rx) = river_game(false);
|
||||
let (cx, cy) = g.map.core;
|
||||
// open floor on the far bank with one training tile of the player
|
||||
for y in cy - 2..=cy + 2 {
|
||||
for x in rx + 3..rx + 7 {
|
||||
let t = &mut g.map.t[idx(x, y)];
|
||||
t.kind = Kind::Floor;
|
||||
t.owner = Owner::None;
|
||||
}
|
||||
}
|
||||
let room = idx(rx + 4, cy);
|
||||
g.map.t[room].kind = Kind::Training;
|
||||
g.map.t[room].owner = g.me;
|
||||
let owl = g.spawn(EK::Owl, false, (cx + 4) as f32 + 0.5, cy as f32 + 0.5, 1);
|
||||
let kobold = g.spawn(EK::Kobold, false, (cx + 4) as f32 + 0.5, cy as f32 + 0.5, 1);
|
||||
let owl = g.ents.iter().find(|e| e.id == owl).unwrap().clone();
|
||||
let kobold = g.ents.iter().find(|e| e.id == kobold).unwrap().clone();
|
||||
// room searches: the owl flies over the river to the training room, the kobold cannot get there
|
||||
let p = g.find_room_tile(&owl, Kind::Training, owl.id + 1, false).expect("the owl finds the room across the river");
|
||||
assert_eq!(p.last().copied(), Some(room));
|
||||
assert!(g.find_room_tile(&kobold, Kind::Training, kobold.id + 1, false).map_or(true, |p| p.last() != Some(&room)));
|
||||
// flyers cut corners over water: a diagonal crossing is as short as on open ground
|
||||
let (a, b) = (idx(rx - 1, cy - 1), idx(rx + 3, cy + 1));
|
||||
let p = g.map.creature_path(true, a, b).expect("flight path");
|
||||
assert!(p.len() <= 5, "diagonal flight over the river: {} steps", p.len());
|
||||
assert!(p.iter().any(|&i| g.map.t[i].liquid()));
|
||||
// attacking flyers (the fairy spy) also fly over rivers instead of searching for a bridge
|
||||
assert!(g.map.hero_cost_as(true)(idx(rx + 1, cy)).is_some());
|
||||
assert_eq!(g.map.hero_cost()(idx(rx + 1, cy)), None);
|
||||
// a locked door stops flyers too
|
||||
g.map.t[idx(rx + 5, cy)].kind = Kind::Door;
|
||||
g.map.t[idx(rx + 5, cy)].res = 1;
|
||||
assert_eq!(g.map.fly_cost()(idx(rx + 5, cy)), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flyers_cross_rivers_flee_and_heal() {
|
||||
let (mut g, rx) = river_game(true);
|
||||
|
||||
Reference in new issue
Block a user