diff --git a/src/game.rs b/src/game.rs index 9fe035b..3fea8fa 100644 --- a/src/game.rs +++ b/src/game.rs @@ -2130,7 +2130,7 @@ impl Game { if e.timer <= 0.0 { let cur = e.tile(); let bed_kind = if flies(e.kind) { Kind::Aerie } else { Kind::Lair }; - let free = |i: usize| self.map.t[i].kind == bed_kind && self.map.t[i].bed == 0; + let free = |i: usize| self.map.t[i].kind == bed_kind && self.map.t[i].bed == 0 && self.map.t[i].owner == self.me; let found = if flies(e.kind) { self.map.search(cur, self.map.fly_cost(), free, true) } else { self.map.search(cur, self.map.walk_cost(), free, true) }; match found { Some(p) => { @@ -3405,7 +3405,7 @@ impl Game { let me = self.me; let target = e .bed - .filter(|&b| self.map.t[b].kind == bed_kind) + .filter(|&b| self.map.t[b].kind == bed_kind && self.map.t[b].owner == me) .or_else(|| self.map.search(cur, self.map.creature_cost(fly), |i| self.map.t[i].kind == bed_kind && self.map.t[i].owner == me, true).map(|p| p.last().copied().unwrap_or(cur))) .or_else(|| self.map.search(cur, self.map.creature_cost(fly), |i| self.map.adj_core_of(i, me), true).map(|p| p.last().copied().unwrap_or(cur))); let Some(b) = target else { return false }; @@ -3824,7 +3824,7 @@ impl Game { let beds = if flies(e.kind) { self.counts[7] } else { self.counts[1] }; if e.bed.is_none() && beds > 0 && !matches!(e.job, Job::Attack(_) | Job::Leave | Job::Rally | Job::March(_)) && self.rng.f() < 0.15 { let cur = e.tile(); - let free = |i: usize| self.map.t[i].kind == bed_kind && self.map.t[i].bed == 0; + let free = |i: usize| self.map.t[i].kind == bed_kind && self.map.t[i].bed == 0 && self.map.t[i].owner == self.me; let found = if flies(e.kind) { self.map.search(cur, self.map.fly_cost(), free, true) } else { self.map.search(cur, self.map.walk_cost(), free, true) }; if let Some(p) = found { let b = p.last().copied().unwrap_or(cur); @@ -4272,14 +4272,18 @@ impl Game { let bed_kind = if flies(e.kind) { Kind::Aerie } else { Kind::Lair }; if let Some(b) = e.bed { let t = &self.map.t[b]; - if t.kind != bed_kind || t.bed != me { + // a bed in somebody else's lair (an ally's, or ground that changed hands) is given up + if t.kind != bed_kind || t.bed != me || t.owner != self.me { + if t.bed == me { + self.map.t[b].bed = 0; + } e.bed = None; } } if e.bed.is_none() { let free = |i: usize| { let t = &self.map.t[i]; - t.kind == bed_kind && t.bed == 0 + t.kind == bed_kind && t.bed == 0 && t.owner == self.me }; let found = if flies(e.kind) { self.map.search(cur, self.map.fly_cost(), free, true) } else { self.map.search(cur, self.map.walk_cost(), free, true) }; if let Some(p) = found { @@ -6857,6 +6861,33 @@ mod tests { assert!(g.ents.iter().filter(|e| e.kind == EK::Chainbreaker).count() <= 1); } + #[test] + fn creatures_never_make_their_bed_in_an_allys_lair() { + let mut g = Game::new(11, 96, 128); + g.coop = true; + assert!(g.start_masters(&[0, 2], 0)); + let (cx, cy) = g.map.core; + for y in cy + 4..cy + 7 { + for x in cx - 1..cx + 4 { + let t = &mut g.map.t[idx(x, y)]; + t.kind = Kind::Lair; + t.owner = Owner::Player; + } + } + g.recount(); + let id = g.spawn(EK::Kobold, false, cx as f32 + 1.5, cy as f32 + 5.5, 1); + if let Some(e) = g.ents.iter_mut().find(|e| e.id == id) { + e.side = 2; + e.energy = 0.1; + } + for _ in 0..(40 * 20) { + g.update(0.05); + } + let e = g.ents.iter().find(|e| e.id == id).expect("still there"); + assert!(e.bed.map_or(true, |b| g.map.t[b].owner != Owner::Player), "no bed in the ally's lair"); + assert!(!g.map.t.iter().any(|t| t.kind == Kind::Lair && t.bed == id + 1)); + } + #[test] fn every_master_of_a_coop_mission_has_an_own_portal() { let m = crate::campaign::coop_mission_indexes()[2];