banished_game/nature/
spawn.rs1use crate::scheduler::ticks;
5
6#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct Spawn {
10 pub timers: Vec<i64>,
13}
14
15impl Spawn {
16 pub fn new(count: usize) -> Self {
20 Self {
21 timers: vec![0; count],
22 }
23 }
24
25 pub fn update(
32 &mut self,
33 growth: f32,
34 delta: i64,
35 entries: &[(f32, f32, f32)],
36 ) -> Vec<(usize, usize)> {
37 assert_eq!(self.timers.len(), entries.len());
38 let mut attempts = Vec::new();
39 for (index, (&(lo, hi, duration), timer)) in
40 entries.iter().zip(&mut self.timers).enumerate()
41 {
42 if !(lo <= growth && growth <= hi) {
43 continue;
44 }
45 *timer += delta;
46 let interval = ticks(duration * 300.0); if interval <= 0 {
49 continue;
50 }
51 let mut count = 0;
52 while interval <= *timer {
53 *timer -= interval;
54 count += 1;
55 }
56 if count != 0 {
57 attempts.push((index, count));
58 }
59 }
60 attempts
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn clocks_freeze_outside_band_and_fire_at_exact_interval() {
70 let entries = [(0.1, 1.1, 1.0), (1.1, 3.0, 0.5)];
71 let mut spawn = Spawn::new(2);
72 assert!(spawn.update(0.5, 200_000_000, &entries).is_empty());
73 assert_eq!(spawn.timers, [200_000_000, 0]);
74 assert!(spawn.update(4.0, 999_999_999, &entries).is_empty());
75 assert_eq!(spawn.timers, [200_000_000, 0]);
76 assert_eq!(spawn.update(1.1, 100_000_000, &entries), [(0, 1)]);
77 assert_eq!(spawn.timers, [0, 100_000_000]);
78 assert_eq!(spawn.update(1.1, 650_000_000, &entries), [(0, 2), (1, 5)]);
79 assert_eq!(spawn.timers, [50_000_000, 0]);
80 }
81}