Creatures arrive faster with more free lair room, slower as the lairs fill up

- Portal interval scaled by free beds (1 free: ~3x slower, 6: normal, 14: 2x faster, up to ~3x)
- Lair info shows the free beds and the arrival speed
- Test

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-03 11:29:18 +01:00
1 parent bd8f53e8a1
commit 6c85a62f1b
4 files changed
+34 -2

No files matched your search

+27 -1
View File
@@ -834,7 +834,7 @@ impl Game {
if owned > 0 {
self.portal_timer -= dt;
if self.portal_timer <= 0.0 {
self.portal_timer = (20.0 + self.rng.f() * 14.0) / (owned as f32).sqrt();
self.portal_timer = (20.0 + self.rng.f() * 14.0) / (owned as f32).sqrt() * self.lair_factor();
self.try_portal();
}
}
@@ -938,6 +938,15 @@ impl Game {
}
}
// free beds in the lairs: much room lets creatures arrive faster, little room slower
pub fn free_beds(&self) -> usize {
self.counts[1].min(30).saturating_sub(self.creature_count())
}
pub fn lair_factor(&self) -> f32 {
(8.0 / (self.free_beds() as f32 + 2.0)).clamp(0.35, 3.0)
}
fn try_portal(&mut self) {
let creatures = self.creature_count();
let lair = self.counts[1];
@@ -4052,6 +4061,23 @@ mod tests {
assert!(g.gate_hp < GATE_HP, "the gate is shot at");
}
#[test]
fn more_lair_room_brings_creatures_faster() {
let mut g = Game::new(3, 64, 64);
g.counts[1] = 4;
let tight = g.lair_factor();
g.counts[1] = 12;
let normal = g.lair_factor();
g.counts[1] = 30;
let roomy = g.lair_factor();
assert!(tight > normal && normal > roomy, "{} {} {}", tight, normal, roomy);
// creatures fill the lair: arrivals slow down again
for _ in 0..20 {
g.spawn(EK::Kobold, false, 10.0, 10.0, 1);
}
assert!(g.lair_factor() > roomy);
}
#[test]
fn vaults_are_claimed_and_looted() {
let (mut g, _) = fort_game(|x, y| crate::fortress::FortSpec { vaults: 2, vault_value: 1800, ..spec(x, y) });
+5 -1
View File
@@ -1119,7 +1119,11 @@ pub fn hover_info(g: &Game, ent: Option<usize>, tile: Option<(i32, i32)>) -> Vec
let what = ["res.gold", "res.silver", "res.ruby", "res.diamond"][(t.res & 3) as usize];
out.push((trf("treasury.content", &[t.gold.to_string(), tr(what)]), GOLD));
}
Kind::Lair => out.push((tr(if t.bed != 0 { "lair.taken" } else { "lair.free" }), DIM)),
Kind::Lair => {
out.push((tr(if t.bed != 0 { "lair.taken" } else { "lair.free" }), DIM));
let speed = (100.0 / g.lair_factor()).round() as i32;
out.push((trf("lair.arrivals", &[g.free_beds().to_string(), speed.to_string()]), if speed >= 100 { GREEN } else { GOLD }));
}
Kind::Torture => {
let used = g.ents.iter().filter(|e| e.alive && e.hero && e.captive != 0).count();
out.push((trf("info.prison", &[used.to_string(), (g.counts[5] / 2).to_string()]), DIM));