diff --git a/src/game.rs b/src/game.rs index f391f22..322d87c 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1541,6 +1541,19 @@ impl Game { } } } + // at least 10% of the imps (at least one) claim floor while there is floor to claim + let imps = 1 + self.ents.iter().filter(|o| o.alive && !o.hero && o.kind == EK::Worker).count(); + let claiming = self.ents.iter().filter(|o| o.alive && !o.hero && o.kind == EK::Worker && matches!(o.job, Job::Claim(_))).count(); + let quota = ((imps as f32 * 0.1).ceil() as usize).max(1); + if claiming < quota { + if let Some(p) = self.map.search(cur, self.map.walk_cost(), |i| self.claimable(i, me), true) { + let end = p.last().copied().unwrap_or(cur); + self.map.t[end].reserved = me; + e.path = p; + e.job = Job::Claim(end); + return; + } + } if let Some(p) = self.map.search(cur, self.map.walk_cost(), |i| self.dig_neighbor(i, me).is_some(), true) { let end = p.last().copied().unwrap_or(cur); if let Some(t) = self.dig_neighbor(end, me) { @@ -3101,6 +3114,39 @@ mod tests { } } + #[test] + fn some_imps_always_claim() { + // lots of digging work: still at least 10% (min. one) of the imps claim the dug-out floor + let mut g = Game::new(11, 64, 64); + let (cx, cy) = g.map.core; + for _ in 0..8 { + let (x, y) = (g.ents[0].x, g.ents[0].y); + g.spawn(EK::Worker, false, x, y, 1); + } + g.mark_rect(cx - 12, cy - 12, cx + 12, cy + 12, true); + let (mut samples, mut ok) = (0, 0); + for step in 0..(150 * 20) { + g.update(0.05); + if step % 20 != 0 || step < 200 { + continue; + } + let digging = g.map.t.iter().any(|t| t.marked); + let claimable = (0..g.map.t.len()).any(|i| g.claimable(i, u32::MAX)); + if digging && claimable { + let imps = g.worker_count(); + let quota = ((imps as f32 * 0.1).ceil() as usize).max(1); + let claiming = g.ents.iter().filter(|e| e.alive && e.kind == EK::Worker && matches!(e.job, Job::Claim(_))).count(); + samples += 1; + if claiming >= quota { + ok += 1; + } + } + } + println!("claim quota met in {}/{} samples", ok, samples); + assert!(samples > 10); + assert!(ok * 10 >= samples * 8); + } + #[test] fn imps_reinforce_walls() { let mut g = Game::new(3, 64, 64);