1use std::collections::BTreeMap;
19
20use banished_formats::game::{
21 AnimalDescription, CharacterDescription, HerdDescription, PopulationDescription,
22};
23use banished_formats::types::AnimationGroup;
24
25use crate::behaviour::animation::AnimationStack;
26use crate::behaviour::character::{Action, Character, MoveTo};
27use crate::nature::seeding::{Cells, Placed, Template};
28use crate::random::Random;
29use crate::scheduler::{seconds, ticks, EntityScheduler};
30use crate::terrain::{CellType, HeightGrid};
31
32pub const HUNTED: u32 = 0x100000;
37pub const WILD: u32 = 0x400000;
42pub const BIRTH: u32 = 0x200000;
47pub const BREEDER: u32 = 0x800000;
52const ANIMAL_WALK: u32 = 0xf9f;
54const PERIOD: f32 = 300.0;
56
57#[derive(Debug, Clone)]
60pub struct PopulationKind {
61 pub desc: PopulationDescription,
63 pub herd: Option<usize>,
65}
66
67#[derive(Debug, Clone)]
69pub struct HerdKind {
70 pub desc: HerdDescription,
72 pub animal: usize,
74}
75
76#[derive(Debug, Clone)]
78pub struct AnimalKind {
79 pub desc: AnimalDescription,
81 pub materials: Vec<usize>,
83 pub character: CharacterDescription,
85}
86
87#[derive(Debug, Clone, Default, PartialEq)]
90pub struct LivestockKind {
91 pub product: Option<usize>,
93 pub interval: f32,
95 pub group: i32,
97}
98
99#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
102pub struct Livestock {
103 pub pasture: Option<usize>,
105 pub timer: i64,
107}
108
109#[derive(Debug, Clone, Default, PartialEq)]
114pub struct Pasture {
115 pub kind: Option<usize>,
117 pub livestock: Vec<usize>,
119 pub limit: i32,
121 pub produced: i32,
123 pub area: [i16; 4],
125}
126
127#[derive(Debug, Clone, PartialEq)]
129pub struct Population {
130 pub entity: usize,
132 pub template: usize,
134 pub width: i32,
137 pub cells: Vec<[i32; 3]>,
140 pub herd_width: i32,
143 pub clock: i64,
146 pub cursor: i32,
149}
150
151#[derive(Debug, Clone, PartialEq)]
153pub struct Herd {
154 pub entity: usize,
156 pub template: usize,
158 pub population: usize,
161 pub index: i32,
163 pub animals: Vec<usize>,
166 pub moving: bool,
169 pub target: i32,
172 pub rest: i64,
175 pub regrow: i64,
177}
178
179pub struct Animal {
181 pub template: usize,
183 pub character: Character,
185 pub herd: Option<usize>,
188 pub flags: u32,
191 pub home: i32,
194 pub timer: i64,
197 pub area: [i16; 4],
200 pub male: bool,
203 pub age: f32,
206 pub life: f32,
208 pub breed: i64,
211 pub livestock: Option<Livestock>,
213 pub variant: usize,
215 pub mesh: usize,
217 pub scale: f32,
221 pub dying: bool,
225}
226
227#[derive(Debug, Clone, Copy, PartialEq, Eq)]
229enum Kind {
230 Population(usize),
231 Herd(usize),
232 Animal,
233}
234
235#[derive(Default)]
237pub struct Wildlife {
238 pub tree: crate::behaviour::character_tree::CharacterTree,
241 pub populations: Vec<Population>,
243 pub herds: Vec<Herd>,
245 pub animals: BTreeMap<usize, Animal>,
247 pub population_kinds: BTreeMap<usize, PopulationKind>,
249 pub herd_kinds: BTreeMap<usize, HerdKind>,
251 pub animal_kinds: BTreeMap<usize, AnimalKind>,
253 pub groups: BTreeMap<(usize, usize), std::sync::Arc<AnimationGroup>>,
255 pub dying: Vec<usize>,
257 kinds: BTreeMap<usize, Kind>,
258 pub livestock_kinds: BTreeMap<usize, LivestockKind>,
260 pub unassigned: Vec<usize>,
263 pub pastures: BTreeMap<usize, Pasture>,
266 pub pasture_list: Vec<usize>,
268 pub nomads: BTreeMap<usize, crate::people::immigration::Nomad>,
270 pub nomad_kinds: BTreeMap<usize, crate::people::immigration::NomadKind>,
272 pub boats: BTreeMap<usize, crate::commerce::boat::Boat>,
274 pub boat_kinds: BTreeMap<usize, crate::commerce::boat::BoatKind>,
276}
277
278pub struct Wild<'a, 't> {
280 pub wildlife: &'a mut Wildlife,
282 pub placed: &'a mut Vec<Placed>,
284 pub templates: &'a [Template],
286 pub cells: &'a Cells,
288 pub terrain: &'a HeightGrid<'t>,
290 pub rng: &'a mut Random,
292 pub scheduler: &'a mut EntityScheduler<usize>,
294}
295
296impl Population {
297 fn capacity(&self, d: &PopulationDescription, cells: &Cells, i: i32) -> i32 {
300 let n = cells.size as i32;
301 let cs = d.cell;
302 let (y0, x0) = ((i / self.width) * cs, (i % self.width) * cs);
303 let (mut habitat, mut forbid) = (0, 0u32);
304 for y in y0..y0 + cs {
305 for x in x0..x0 + cs {
306 let c = (n * y + x) as usize;
307 let bit = 1u32 << (cells.types[c].0 & 0x1f);
308 if bit & d.habitat != 0 {
309 habitat += 1;
310 }
311 forbid |= d.forbidden & bit;
312 if d.no_occupants && cells.occupants[c].is_some() {
313 forbid |= 1;
314 }
315 }
316 }
317 if forbid == 0 && habitat > 0 {
318 d.capacity
319 } else {
320 0
321 }
322 }
323
324 fn block(&self) -> i32 {
326 self.width / self.herd_width.max(1)
327 }
328
329 fn habitable_share(&self, index: i32) -> f32 {
331 let bs = self.block();
332 let (row0, col0) = (
333 (index / self.herd_width) * bs,
334 (index % self.herd_width) * bs,
335 );
336 let mut n = 0;
337 for r in 0..bs {
338 for c in 0..bs {
339 if self.cells[(self.width * (row0 + r) + col0 + c) as usize][0] > 0 {
340 n += 1;
341 }
342 }
343 }
344 n as f32 / (bs * bs) as f32
345 }
346
347 fn pick(&self, d: &PopulationDescription, index: i32, n: i32, rng: &mut Random) -> i32 {
350 let bs = self.block();
351 let (row0, col0) = (
352 (index / self.herd_width) * bs,
353 (index % self.herd_width) * bs,
354 );
355 let mut found = Vec::new();
356 for r in 0..bs {
357 for c in 0..bs {
358 let i = self.width * (row0 + r) + col0 + c;
359 if self.cells[i as usize][0] > 0 {
360 found.push(i);
361 }
362 }
363 }
364 if found.is_empty() {
365 return -1;
366 }
367 let i = found[rng.rand_below(found.len() as u32) as usize];
368 let cs = d.cell;
369 n * (cs * (i / self.width) + (cs >> 1)) + cs * (i % self.width) + (cs >> 1)
370 }
371
372 fn capacity_at(&self, d: &PopulationDescription, n: i32, cell: i32) -> i32 {
374 if cell < 0 {
375 return 0;
376 }
377 let (y, x) = (cell / n / d.cell, cell % n / d.cell);
378 self.cells
379 .get((y * self.width + x) as usize)
380 .map_or(0, |c| c[0])
381 }
382
383 fn regrow(&mut self, d: &PopulationDescription) {
386 for c in &mut self.cells {
387 c[1] += d.regrowth;
388 if c[0] < c[1] {
389 c[1] = c[0];
390 }
391 }
392 let w = self.width;
393 let mut mean = vec![0; self.cells.len()];
394 for gy in 0..w {
395 for gx in 0..w {
396 let (mut sum, mut weights) = (0, 0);
397 for dy in -2..3 {
398 for dx in -2..3 {
399 let (x, y) = (gx + dx, gy + dy);
400 if x < 0 || y < 0 || x >= w || y >= w {
401 continue;
402 }
403 let c = self.cells[(w * y + x) as usize];
404 if c[0] == 0 {
405 continue;
406 }
407 let k = 16 - dx * dx - dy * dy;
408 if k >= 0 {
409 sum += c[1] * k;
410 weights += k;
411 }
412 }
413 }
414 mean[(w * gy + gx) as usize] = if weights == 0 { 0 } else { sum / weights };
415 }
416 }
417 for (c, m) in self.cells.iter_mut().zip(mean) {
418 c[1] = m;
419 c[2] = m;
420 }
421 }
422}
423
424impl Wildlife {
425 pub fn restore_population(&mut self, p: Population) -> usize {
429 let index = self.populations.len();
430 self.kinds.insert(p.entity, Kind::Population(index));
431 self.populations.push(p);
432 index
433 }
434
435 pub fn restore_herd(&mut self, h: Herd) -> usize {
439 let index = self.herds.len();
440 self.kinds.insert(h.entity, Kind::Herd(index));
441 self.herds.push(h);
442 index
443 }
444
445 pub fn restore_animal(&mut self, entity: usize, a: Animal) {
450 self.kinds.insert(entity, Kind::Animal);
451 self.animals.insert(entity, a);
452 }
453
454 pub fn kill(&mut self, a: usize) {
459 let Some(animal) = self.animals.get_mut(&a) else {
460 return;
461 };
462 if animal.dying {
463 return;
464 }
465 animal.dying = true;
466 if let Some(h) = animal.herd.take() {
467 self.herds[h].animals.retain(|&x| x != a);
468 }
469 if let Some(l) = animal.livestock {
471 match l.pasture {
472 None => self.unassigned.retain(|&x| x != a),
473 Some(p) => {
474 if let Some(p) = self.pastures.get_mut(&p) {
475 p.livestock.retain(|&x| x != a);
476 }
477 }
478 }
479 }
480 self.dying.push(a);
481 }
482
483 pub fn capacity(&self, p: usize) -> i32 {
488 let Some(pasture) = self.pastures.get(&p) else {
489 return 0;
490 };
491 let Some(kind) = pasture.kind else { return 0 };
492 let space = self.animal_kinds.get(&kind).map_or(0, |k| k.desc.space);
493 let area = pasture.area[2] as i32 * pasture.area[3] as i32;
494 if space == 0 {
496 return 0;
497 }
498 area / space
499 }
500
501 pub fn group(&self, a: &Animal) -> Option<&AnimationGroup> {
503 self.groups.get(&(a.template, a.variant)).map(|g| &**g)
504 }
505}
506
507impl Wild<'_, '_> {
508 fn n(&self) -> i32 {
509 self.cells.size as i32
510 }
511
512 fn cell_of(&self, p: [f32; 3]) -> i32 {
513 let n = self.n();
514 let half = (n >> 1) as f32;
515 let x = ((p[0] + half) as i32).clamp(0, n - 1);
516 let y = ((p[1] + half) as i32).clamp(0, n - 1);
517 n * y + x
518 }
519
520 fn ground(&self, cell: i32) -> [f32; 3] {
521 crate::town::floor_ground(&self.cells.floors, self.cells.size, self.terrain, cell)
522 }
523
524 fn create(&mut self, template: usize, position: [f32; 3]) -> usize {
527 let id = self.place(template, position);
528 let handle = self.scheduler.register(id, self.templates[template].bucket);
529 debug_assert_eq!(handle, id);
530 id
531 }
532
533 fn place(&mut self, template: usize, position: [f32; 3]) -> usize {
535 let id = self.placed.len();
536 let cell = self.cell_of(position);
537 let n = self.n();
538 self.placed.push(Placed {
539 template,
540 bucket: self.templates[template].bucket,
541 cell: (cell % n, cell / n),
542 footprint: (1, 1),
543 position,
544 yaw: 0.0,
545 variant: 0,
546 mesh: usize::MAX,
547 growth: 0.0,
548 growth_state: None,
549 spawn_state: None,
550 alive: true,
551 removal_requested: false,
552 animation: None,
553 scale: [1.0; 4],
554 });
555 id
556 }
557
558 pub fn start_population(&mut self, template: usize) {
562 let Some(kind) = self.wildlife.population_kinds.get(&template).cloned() else {
563 return;
564 };
565 let d = &kind.desc;
566 let entity = self.create(template, [0.0; 3]);
567 let n = self.n();
568 let width = n / d.cell.max(1);
569 let mut p = Population {
570 entity,
571 template,
572 width,
573 cells: vec![[0; 3]; (width * width) as usize],
574 herd_width: n / d.herd_block.max(1),
575 clock: 0,
576 cursor: 0,
577 };
578 for i in 0..width * width {
579 let c = p.capacity(d, self.cells, i);
580 p.cells[i as usize] = [c, c, c];
581 }
582 let index = self.wildlife.populations.len();
583 let herds = p.herd_width * p.herd_width;
584 self.wildlife.populations.push(p);
585 self.wildlife.kinds.insert(entity, Kind::Population(index));
586 let Some(herd_t) = kind.herd else { return };
587 let Some(hk) = self.wildlife.herd_kinds.get(&herd_t).cloned() else {
588 return;
589 };
590 for i in 0..herds {
591 let h = self.wildlife.herds.len();
592 self.wildlife.herds.push(Herd {
593 entity: usize::MAX,
594 template: herd_t,
595 population: index,
596 index: i,
597 animals: Vec::new(),
598 moving: false,
599 target: -1,
600 rest: 0,
601 regrow: 0,
602 });
603 let count =
604 self.rng.rand_below((hk.desc.max - hk.desc.min) as u32) as i32 + hk.desc.min;
605 self.spawn_herd(h, count);
606 let e = self.create(herd_t, [0.0; 3]);
608 self.wildlife.herds[h].entity = e;
609 self.wildlife.kinds.insert(e, Kind::Herd(h));
610 }
611 }
612
613 fn herd_area(&self, h: usize) -> [i16; 4] {
617 let herd = &self.wildlife.herds[h];
618 let size = self.wildlife.herd_kinds[&herd.template].desc.area;
619 let n = self.n();
620 let x0 = (herd.target % n - (size >> 1)).max(1);
621 let y0 = (herd.target / n - (size >> 1)).max(1);
622 let mut w = size;
623 if n - 1 <= x0 + size {
624 w = n - x0 - 2;
625 }
626 let mut h = size;
627 if n - 1 <= y0 + w {
628 h = n - y0 - 2;
629 }
630 [x0 as i16, y0 as i16, w as i16, h as i16]
631 }
632
633 pub fn retarget(&mut self, h: usize) {
638 let (p, index, template) = {
639 let herd = &self.wildlife.herds[h];
640 (herd.population, herd.index, herd.template)
641 };
642 let _ = template;
643 let pt = self.wildlife.populations[p].template;
644 let d = self.wildlife.population_kinds[&pt].desc.clone();
645 let n = self.n();
646 let target = self.wildlife.populations[p].pick(&d, index, n, self.rng);
647 self.wildlife.herds[h].target = target;
648 if target < 0 {
649 for a in std::mem::take(&mut self.wildlife.herds[h].animals) {
650 self.kill(a);
651 }
652 return;
653 }
654 let area = self.herd_area(h);
655 for a in self.wildlife.herds[h].animals.clone() {
656 if let Some(animal) = self.wildlife.animals.get_mut(&a) {
657 animal.area = area;
658 }
659 }
660 }
661
662 fn kill(&mut self, a: usize) {
663 self.wildlife.kill(a);
664 }
665
666 fn spawn_herd(&mut self, h: usize, count: i32) {
668 self.retarget(h);
669 let template = self.wildlife.herds[h].template;
670 let hk = self.wildlife.herd_kinds[&template].clone();
671 let area = self.herd_area(h);
672 let (x0, y0, w, hh) = (
673 area[0] as i32,
674 area[1] as i32,
675 area[2] as i32,
676 area[3] as i32,
677 );
678 let male = self.rng.rand_below(2) == 0;
679 let n = self.n();
680 for _ in 0..count {
681 let x = x0 + self.rng.rand_below(w.max(0) as u32) as i32;
682 let y = y0 + self.rng.rand_below(hh.max(0) as u32) as i32;
683 let base = self.ground(n * y + x);
684 let dy = self.rng.rand_float_tol();
685 let dx = self.rng.rand_float_tol();
686 let position = [base[0] + dx * 0.4, base[1] + dy * 0.4, base[2]];
687 let yaw = self.rng.rand_float_tol() * 180.0;
688 let Some(a) = self.new_animal(hk.animal, position, yaw, male) else {
689 return;
690 };
691 let life = self.wildlife.animal_kinds[&hk.animal].desc.life;
692 let age = self.rng.rand_float() * life;
693 if let Some(animal) = self.wildlife.animals.get_mut(&a) {
694 animal.age = age;
695 }
696 self.rescale(a);
697 self.join(a, h);
698 self.register_animal(a);
699 }
700 let rest = self.rng.rand_float() * (hk.desc.rest_range + hk.desc.rest) * PERIOD;
701 let herd = &mut self.wildlife.herds[h];
702 herd.rest = ticks(rest);
703 herd.moving = false;
704 }
705
706 fn regrow_herd(&mut self, h: usize, target: i32) {
708 let template = self.wildlife.herds[h].template;
709 let hk = self.wildlife.herd_kinds[&template].clone();
710 let male = self.rng.rand_below(2) == 0;
711 while (self.wildlife.herds[h].animals.len() as i32) < target {
712 let area = hk.desc.area as f32;
713 let base = self.ground(self.wildlife.herds[h].target);
714 let dy = self.rng.rand_float_tol();
715 let dx = self.rng.rand_float_tol();
716 let position = [base[0] + dx * area, base[1] + dy * area, base[2]];
717 let yaw = self.rng.rand_float_tol() * 180.0;
718 let Some(a) = self.new_animal(hk.animal, position, yaw, male) else {
719 return;
720 };
721 self.join(a, h);
722 self.register_animal(a);
723 }
724 }
725
726 fn new_animal(
729 &mut self,
730 template: usize,
731 position: [f32; 3],
732 yaw: f32,
733 male: bool,
734 ) -> Option<usize> {
735 let variant = self.pick_variant(template)?;
736 self.insert_animal(template, variant, position, yaw, male)
737 }
738
739 fn pick_variant(&mut self, template: usize) -> Option<(usize, usize)> {
742 self.wildlife.animal_kinds.get(&template)?;
743 let t = &self.templates[template];
744 let (mut variant, mut mesh) = (0usize, 0usize);
745 if let Some(m) = &t.model {
746 variant = m.variant.max(0) as usize;
747 if m.random_variant {
748 variant = self.rng.rand_below(m.variants.len() as u32) as usize;
749 }
750 mesh = m.mesh.max(0) as usize;
751 }
752 Some((variant, mesh))
753 }
754
755 fn insert_animal(
758 &mut self,
759 template: usize,
760 (variant, mut mesh): (usize, usize),
761 position: [f32; 3],
762 yaw: f32,
763 male: bool,
764 ) -> Option<usize> {
765 let kind = self.wildlife.animal_kinds.get(&template)?.clone();
766 if let Some(m) = &self.templates[template].model {
767 if male && m.variants.get(variant).is_some_and(|v| v.meshes.len() > 1) {
768 mesh = 1;
769 }
770 }
771 let id = self.placed.len();
772 let mut character = Character::new(kind.character, position, 1.0);
773 character.yaw = yaw;
774 self.wildlife.animals.insert(
775 id,
776 Animal {
777 template,
778 character,
779 herd: None,
780 flags: WILD,
781 home: -1,
782 timer: 0,
783 area: [0; 4],
784 male,
785 age: 0.0,
786 life: 0.0,
787 breed: 0,
788 livestock: self
789 .wildlife
790 .livestock_kinds
791 .contains_key(&template)
792 .then(Livestock::default),
793 variant,
794 mesh,
795 scale: 1.0,
796 dying: false,
797 },
798 );
799 self.rescale(id);
800 Some(id)
801 }
802
803 fn join(&mut self, a: usize, h: usize) {
805 let area = self.herd_area(h);
806 self.wildlife.herds[h].animals.push(a);
807 if let Some(animal) = self.wildlife.animals.get_mut(&a) {
808 animal.herd = Some(h);
809 animal.area = area;
810 }
811 }
812
813 fn register_animal(&mut self, a: usize) {
817 self.register_animal_in(a, true);
818 }
819
820 fn register_animal_in(&mut self, a: usize, buckets: bool) {
822 let template = self.wildlife.animals[&a].template;
823 let position = self.wildlife.animals[&a].character.position;
824 let e = if buckets {
825 self.create(template, position)
826 } else {
827 self.place(template, position)
828 };
829 debug_assert_eq!(e, a);
830 self.wildlife.kinds.insert(a, Kind::Animal);
831 let ch = &self.wildlife.animals[&a].character;
833 let slot = self.wildlife.tree.insert(
834 crate::behaviour::character_tree::Who::Animal(a),
835 ch.position,
836 ch.desc.radius,
837 );
838 self.wildlife
839 .animals
840 .get_mut(&a)
841 .unwrap()
842 .character
843 .tree_slot = slot;
844 let d = self.wildlife.animal_kinds[&template].desc.clone();
845 let life = self.rng.rand_float_tol() * d.life_range + d.life;
846 let n = self.n();
847 let cell = self.cell_of(position);
848 let animal = self.wildlife.animals.get_mut(&a).unwrap();
849 animal.life = life;
850 if animal.flags & WILD != 0 {
851 animal.home = cell;
852 animal.area = area_around(n, cell, d.area);
853 self.update_animal(a, 0);
854 }
855 let animal = &self.wildlife.animals[&a];
858 if animal.livestock.is_some_and(|l| l.pasture.is_none()) {
859 self.wildlife.unassigned.push(a);
860 }
861 }
862
863 fn rescale(&mut self, a: usize) {
865 let Some(animal) = self.wildlife.animals.get_mut(&a) else {
866 return;
867 };
868 let d = &self.wildlife.animal_kinds[&animal.template].desc;
869 let s = (animal.age / d.adult * 0.67 + 0.33).min(1.0);
870 animal.scale = s;
871 animal.character.scale = s;
872 }
873
874 pub fn scheduled(&mut self, e: usize, elapsed: i64) {
876 match self.wildlife.kinds.get(&e).copied() {
877 Some(Kind::Population(p)) => self.update_population(p, elapsed),
878 Some(Kind::Herd(h)) => self.update_herd(h, elapsed),
879 Some(Kind::Animal) => {
880 if let Some(animal) = self.wildlife.animals.get_mut(&e) {
883 let following = self.wildlife.tree.follows(animal.character.tree_slot);
884 animal.character.stack.notify_moves(following);
885 }
886 self.update_animal(e, elapsed);
887 self.update_livestock(e, elapsed);
888 }
889 None => {}
890 }
891 }
892
893 fn update_population(&mut self, p: usize, dt: i64) {
895 let template = self.wildlife.populations[p].template;
896 let d = self.wildlife.population_kinds[&template].desc.clone();
897 let period = ticks(PERIOD);
898 let pop = &mut self.wildlife.populations[p];
899 pop.clock += dt;
900 while period < pop.clock {
901 pop.regrow(&d);
902 pop.clock -= period;
903 }
904 if !d.refresh {
905 return;
906 }
907 let total = pop.width * pop.width;
908 for _ in 0..total / 16 {
909 let i = pop.cursor;
910 let cap = pop.capacity(&d, self.cells, i);
911 let c = &mut pop.cells[i as usize];
912 c[0] = cap;
913 if cap < c[1] {
914 c[1] = cap;
915 }
916 if cap < c[2] {
917 c[2] = cap;
918 }
919 pop.cursor = if i + 1 == total { 0 } else { i + 1 };
920 }
921 }
922
923 fn update_herd(&mut self, h: usize, dt: i64) {
925 let template = self.wildlife.herds[h].template;
926 let hd = self.wildlife.herd_kinds[&template].desc.clone();
927 let p = self.wildlife.herds[h].population;
928 let pt = self.wildlife.populations[p].template;
929 let pd = self.wildlife.population_kinds[&pt].desc.clone();
930 let n = self.n();
931 let herd = &mut self.wildlife.herds[h];
932 herd.regrow += dt;
933 let period = ticks(hd.regrowth * PERIOD);
934 if period < herd.regrow {
935 herd.regrow -= period;
936 let share = self.wildlife.populations[p].habitable_share(herd.index);
937 let f = if share < 0.5 { share * 2.0 } else { 1.0 };
938 let count = self.wildlife.herds[h].animals.len() as i32;
939 let mut target = if count * 2 == 0 { 2 } else { count * 2 };
940 let by_share = (hd.max as f32 * f + 0.5) as i32;
941 if by_share < target {
942 target = by_share;
943 }
944 self.regrow_herd(h, target);
945 }
946 let herd = &self.wildlife.herds[h];
947 let habitable = self.wildlife.populations[p].capacity_at(&pd, n, herd.target) != 0;
948 if !herd.moving {
949 let rest = herd.rest - dt;
950 self.wildlife.herds[h].rest = rest;
951 if 0 < rest && habitable {
952 return;
953 }
954 self.retarget(h);
955 let herd = &mut self.wildlife.herds[h];
956 herd.rest = 0;
957 herd.moving = true;
958 } else {
959 if self.all_home(h) {
960 let rest = (self.rng.rand_float() * hd.rest_range + hd.rest) * PERIOD;
961 let herd = &mut self.wildlife.herds[h];
962 herd.moving = false;
963 herd.rest = ticks(rest);
964 return;
965 }
966 if !habitable {
967 self.retarget(h);
968 }
969 }
970 }
971
972 fn all_home(&self, h: usize) -> bool {
974 self.wildlife.herds[h].animals.iter().all(|a| {
975 self.wildlife.animals.get(a).is_some_and(|animal| {
976 inside(
977 &animal.area,
978 self.cell_of(animal.character.position),
979 self.n(),
980 )
981 })
982 })
983 }
984
985 pub fn update_animal(&mut self, a: usize, dt: i64) {
989 let Some(animal) = self.wildlife.animals.get_mut(&a) else {
990 return;
991 };
992 if animal.dying {
993 return;
994 }
995 let d = self.wildlife.animal_kinds[&animal.template].desc.clone();
996 animal.age += seconds(dt) * (1.0 / 3600.0);
997 if animal.life < animal.age {
998 self.kill(a);
999 return;
1000 }
1001 let animal = self.wildlife.animals.get_mut(&a).unwrap();
1003 if animal.male && animal.flags & BIRTH == 0 && animal.flags & BREEDER != 0 {
1004 if animal.breed != 0 || animal.age <= d.adult {
1005 if 0 < animal.breed {
1006 animal.breed -= dt;
1007 if animal.breed <= 0 {
1008 animal.flags |= BIRTH;
1010 animal.breed = 0;
1011 }
1012 }
1013 } else {
1014 let years = self.rng.rand_float() * d.breed + d.breed;
1015 self.wildlife.animals.get_mut(&a).unwrap().breed = ticks(years * 3600.0);
1016 }
1017 }
1018 self.rescale(a);
1019 let n = self.n();
1020 let animal = self.wildlife.animals.get_mut(&a).unwrap();
1021 if animal.character.stack.is_active() {
1022 return;
1023 }
1024 animal.timer -= dt;
1025 if 0 < animal.timer {
1026 return;
1027 }
1028 let mut anim = 1;
1029 if animal.flags & HUNTED == 0 {
1030 if animal.flags & WILD != 0 {
1031 let home = animal.home;
1032 let taken = home >= 0
1035 && self.cells.occupants[home as usize]
1036 .is_some_and(|o| !self.templates[self.placed[o].template].trading_post);
1037 if home < 0 || self.cells.types[home as usize] != CellType(2) || taken {
1038 self.rehome(a, &d);
1039 }
1040 }
1041 let animal = &self.wildlife.animals[&a];
1042 let here = self.cell_of(animal.character.position);
1043 let area = animal.area;
1044 let mut wander = !inside(&area, here, n);
1045 if !wander {
1046 anim = self.rng.rand_below(4) as usize;
1047 wander = anim == 0;
1048 }
1049 if wander {
1050 let mut in_area = 0;
1051 let mut total = 0;
1052 let mut dest;
1053 loop {
1054 let area = self.wildlife.animals[&a].area;
1055 let ry = self.rng.rand_below(area[3] as u32) as i32;
1056 let rx = self.rng.rand_below(area[2] as u32) as i32;
1057 let cell = rx + area[0] as i32 + (ry + area[1] as i32) * n;
1058 let base = self.ground(cell);
1059 let first = self.rng.rand_float_tol();
1060 let second = self.rng.rand_float_tol();
1061 dest = [base[0] + second * 0.4, base[1] + first * 0.4, base[2]];
1062 if 10 < in_area {
1063 self.rehome(a, &d);
1064 in_area = 0;
1065 }
1066 in_area += 1;
1067 total += 1;
1068 let at = self.cell_of(dest);
1069 if self.cells.types[at as usize] == CellType(2) || 100 <= total {
1070 break;
1071 }
1072 }
1073 if self.cells.types[self.cell_of(dest) as usize] == CellType(2) {
1074 let walk = MoveTo::new(dest, 0, 1, ANIMAL_WALK, 1, -1.0, self.rng);
1075 self.restack(a, Some(Action::move_to(walk)));
1076 self.wildlife.animals.get_mut(&a).unwrap().timer = 0;
1077 return;
1078 }
1079 anim = self.rng.rand_below(3) as usize + 1;
1080 }
1081 }
1082 let idle = self.rng.rand_float() * d.idle + d.idle;
1083 self.idle(a, anim, idle, d.turn);
1084 }
1085
1086 fn restack(&mut self, a: usize, action: Option<Action>) {
1088 let Some(animal) = self.wildlife.animals.get(&a) else {
1089 return;
1090 };
1091 let Some(group) = self
1092 .wildlife
1093 .groups
1094 .get(&(animal.template, animal.variant))
1095 .cloned()
1096 else {
1097 return;
1098 };
1099 let ch = &mut self.wildlife.animals.get_mut(&a).unwrap().character;
1100 let mut stack = std::mem::take(&mut ch.stack);
1101 stack.clear(ch, &group, &mut []);
1102 if let Some(action) = action {
1103 stack.push(ch, &group, action);
1104 }
1105 ch.stack = stack;
1106 }
1107
1108 pub fn hunted(&mut self, a: usize) {
1112 let Some(animal) = self.wildlife.animals.get_mut(&a) else {
1113 return;
1114 };
1115 animal.flags |= HUNTED;
1116 if animal.character.stack.is_active() {
1117 self.restack(a, None);
1118 self.update_animal(a, 0);
1119 }
1120 }
1121
1122 fn idle(&mut self, a: usize, anim: usize, secs: f32, turn: bool) {
1124 let group = {
1125 let animal = &self.wildlife.animals[&a];
1126 self.wildlife
1127 .groups
1128 .get(&(animal.template, animal.variant))
1129 .cloned()
1130 };
1131 let animal = self.wildlife.animals.get_mut(&a).unwrap();
1132 match &group {
1133 Some(g) => animal.character.animation.play(g, anim, 0),
1134 None => animal.character.animation = AnimationStack::new(anim, 0),
1135 }
1136 animal.timer = ticks(secs);
1137 if turn {
1138 let y = self.rng.rand_float_tol();
1141 let x = self.rng.rand_float_tol();
1142 let v = crate::math::normalize3([x, y, 0.0]);
1143 let ch = &mut self.wildlife.animals.get_mut(&a).unwrap().character;
1144 ch.flag_28 = false;
1145 ch.direction = crate::math::normalize3(v);
1146 ch.target_heading = crate::math::heading(v[0], v[1]);
1147 }
1148 }
1149
1150 fn rehome(&mut self, a: usize, d: &AnimalDescription) {
1153 let n = self.n();
1154 let home = self.wildlife.animals[&a].home.max(0);
1155 let new = nearest_ground(self.cells, n, home);
1156 let animal = self.wildlife.animals.get_mut(&a).unwrap();
1157 animal.home = new;
1158 animal.area = area_around(n, new, d.area);
1159 }
1160
1161 fn update_livestock(&mut self, a: usize, dt: i64) {
1164 let Some(animal) = self.wildlife.animals.get(&a) else {
1165 return;
1166 };
1167 let Some(Livestock {
1168 pasture: Some(p),
1169 timer,
1170 }) = animal.livestock
1171 else {
1172 return;
1173 };
1174 let Some(kind) = self.wildlife.livestock_kinds.get(&animal.template) else {
1175 return;
1176 };
1177 if kind.product.is_none() {
1178 return;
1179 }
1180 let period = ticks(kind.interval * PERIOD);
1181 let mut timer = timer + dt;
1182 let mut products = 0;
1183 while 0 < period && period < timer {
1185 products += 1;
1186 timer -= period;
1187 }
1188 if let Some(l) = self
1189 .wildlife
1190 .animals
1191 .get_mut(&a)
1192 .unwrap()
1193 .livestock
1194 .as_mut()
1195 {
1196 l.timer = timer;
1197 }
1198 if let Some(pasture) = self.wildlife.pastures.get_mut(&p) {
1199 pasture.produced += products;
1200 }
1201 }
1202
1203 pub fn assign(&mut self, a: usize, to: Option<usize>) {
1208 let Some(l) = self.wildlife.animals.get(&a).and_then(|x| x.livestock) else {
1209 return;
1210 };
1211 if l.pasture == to {
1212 return;
1213 }
1214 match l.pasture {
1215 None => self.wildlife.unassigned.retain(|&x| x != a),
1216 Some(p) => {
1217 if let Some(p) = self.wildlife.pastures.get_mut(&p) {
1218 p.livestock.retain(|&x| x != a);
1219 }
1220 self.turn_wild(a);
1221 }
1222 }
1223 if let Some(l) = self
1224 .wildlife
1225 .animals
1226 .get_mut(&a)
1227 .and_then(|x| x.livestock.as_mut())
1228 {
1229 l.pasture = to;
1230 }
1231 match to {
1232 Some(p) => {
1233 if let Some(pasture) = self.wildlife.pastures.get_mut(&p) {
1234 pasture.livestock.push(a);
1235 }
1236 self.pen(a);
1237 }
1238 None => self.wildlife.unassigned.push(a),
1239 }
1240 }
1241
1242 fn turn_wild(&mut self, a: usize) {
1245 let n = self.n();
1246 let Some(animal) = self.wildlife.animals.get(&a) else {
1247 return;
1248 };
1249 let cell = self.cell_of(animal.character.position);
1250 let size = self.wildlife.animal_kinds[&animal.template].desc.area;
1251 let animal = self.wildlife.animals.get_mut(&a).unwrap();
1252 animal.flags |= WILD;
1253 animal.home = cell;
1254 animal.area = area_around(n, cell, size);
1255 self.update_animal(a, 0);
1256 }
1257
1258 fn pen(&mut self, a: usize) {
1260 let Some(p) = self
1261 .wildlife
1262 .animals
1263 .get(&a)
1264 .and_then(|x| x.livestock)
1265 .and_then(|l| l.pasture)
1266 else {
1267 return;
1268 };
1269 let Some(area) = self.wildlife.pastures.get(&p).map(|x| x.area) else {
1270 return;
1271 };
1272 let animal = self.wildlife.animals.get_mut(&a).unwrap();
1273 animal.flags &= !WILD;
1274 animal.area = area;
1275 }
1276
1277 pub fn fill(&mut self, p: usize) {
1282 if self.wildlife.unassigned.is_empty() {
1283 return;
1284 }
1285 let cap = self.wildlife.capacity(p);
1286 let Some(pasture) = self.wildlife.pastures.get(&p) else {
1287 return;
1288 };
1289 if cap <= pasture.livestock.len() as i32 {
1290 return;
1291 }
1292 let kind = pasture.kind;
1293 let waiting: Vec<usize> = self
1294 .wildlife
1295 .unassigned
1296 .iter()
1297 .copied()
1298 .filter(|a| Some(self.wildlife.animals[a].template) == kind)
1299 .collect();
1300 for a in waiting {
1301 self.assign(a, Some(p));
1302 if cap <= self.wildlife.pastures[&p].livestock.len() as i32 {
1303 break;
1304 }
1305 }
1306 }
1307
1308 pub fn births(&mut self, p: usize) -> Vec<usize> {
1314 let cap = self.wildlife.capacity(p);
1315 let mut born = Vec::new();
1316 let mut i = 0;
1317 while i < self
1318 .wildlife
1319 .pastures
1320 .get(&p)
1321 .map_or(0, |x| x.livestock.len())
1322 {
1323 let a = self.wildlife.pastures[&p].livestock[i];
1324 let animal = self.wildlife.animals.get_mut(&a).unwrap();
1325 if animal.flags & BIRTH != 0 {
1326 animal.flags &= !BIRTH;
1327 if (self.wildlife.pastures[&p].livestock.len() as i32) < cap + 3 {
1328 born.extend(self.give_birth(p, Some(a), false));
1329 }
1330 }
1331 i += 1;
1332 }
1333 born
1334 }
1335
1336 pub fn give_birth(&mut self, p: usize, parent: Option<usize>, buckets: bool) -> Option<usize> {
1342 let pasture = self.wildlife.pastures.get(&p)?;
1343 let kind = pasture.kind?;
1344 let area = pasture.area;
1345 let variant = self.pick_variant(kind)?;
1346 let position = match parent.and_then(|a| self.wildlife.animals.get(&a)) {
1347 Some(parent) => {
1348 let q = parent.character.position;
1349 let dy = self.rng.rand_float_tol();
1350 let dx = self.rng.rand_float_tol();
1351 [q[0] + dx, q[1] + dy, q[2]]
1352 }
1353 None => {
1354 let n = self.n();
1355 let rx = self.rng.rand_below(area[2] as u32) as i32;
1356 let ry = self.rng.rand_below(area[3] as u32) as i32;
1357 let dy = self.rng.rand_float_tol();
1358 let dx = self.rng.rand_float_tol();
1359 let cell = n * (area[1] as i32 + ry) + area[0] as i32 + rx;
1360 let g = self.ground(cell);
1361 [g[0] + dx, g[1] + dy, g[2]]
1362 }
1363 };
1364 let herd = &self.wildlife.pastures[&p].livestock;
1365 let females = herd
1366 .iter()
1367 .filter(|a| self.wildlife.animals.get(a).is_some_and(|x| !x.male))
1368 .count();
1369 let male = if herd.is_empty() {
1370 true
1371 } else {
1372 let share = females as f32 / herd.len() as f32;
1373 share > self.rng.rand_float()
1374 };
1375 let yaw = self.rng.rand_float_tol() * 180.0;
1376 let a = self.insert_animal(kind, variant, position, yaw, male)?;
1377 self.assign(a, Some(p));
1378 let age = if parent.is_none() {
1379 self.rng.rand_float()
1380 } else {
1381 0.0
1382 };
1383 self.wildlife.animals.get_mut(&a).unwrap().age = age;
1384 self.rescale(a);
1385 self.register_animal_in(a, buckets);
1386 Some(a)
1387 }
1388
1389 pub fn start_livestock(&mut self, template: usize, count: i32, at: [f32; 3], spread: f32) {
1395 let mut male = self.rng.rand_below(2) == 0;
1396 for _ in 0..count {
1397 let Some(variant) = self.pick_variant(template) else {
1398 return;
1399 };
1400 let dy = self.rng.rand_float_tol();
1401 let dx = self.rng.rand_float_tol();
1402 let (x, y) = (at[0] + dx * spread, at[1] + dy * spread);
1403 let position = [x, y, at[2]];
1406 let yaw = self.rng.rand_float_tol() * 180.0;
1407 let Some(a) = self.insert_animal(template, variant, position, yaw, male) else {
1408 return;
1409 };
1410 male = !male;
1411 self.wildlife.animals.get_mut(&a).unwrap().age = self.rng.rand_float();
1412 self.rescale(a);
1413 self.register_animal(a);
1414 }
1415 }
1416
1417 pub fn trade_livestock(
1426 &mut self,
1427 template: usize,
1428 count: i32,
1429 a: [f32; 3],
1430 b: [f32; 3],
1431 area: [i16; 4],
1432 ) {
1433 let mut male = self.rng.rand_below(2) == 0;
1434 for _ in 0..count {
1435 let Some(variant) = self.pick_variant(template) else {
1436 return;
1437 };
1438 let fy = self.rng.rand_float();
1439 let fx = self.rng.rand_float();
1440 let (x, y) = (a[0] + (b[0] - a[0]) * fx, a[1] + (b[1] - a[1]) * fy);
1441 let position = [x, y, a[2]];
1444 let yaw = self.rng.rand_float_tol() * crate::nature::seeding::YAW_RANGE;
1445 let Some(id) = self.insert_animal(template, variant, position, yaw, male) else {
1446 return;
1447 };
1448 male = !male;
1449 let animal = self.wildlife.animals.get_mut(&id).unwrap();
1450 animal.flags &= !WILD;
1451 animal.area = area;
1452 let life = animal.life;
1453 let f = self.rng.rand_float();
1454 self.wildlife.animals.get_mut(&id).unwrap().age = f * life * 0.5;
1455 self.rescale(id);
1456 self.register_animal_in(id, false);
1457 }
1458 }
1459
1460 pub fn mark_breeder(&mut self, p: usize) {
1464 let Some(herd) = self.wildlife.pastures.get(&p).map(|x| x.livestock.clone()) else {
1465 return;
1466 };
1467 if herd.is_empty() {
1468 return;
1469 }
1470 let r = self.rng.rand_below(herd.len() as u32) as usize;
1471 if let Some(animal) = self.wildlife.animals.get_mut(&herd[r]) {
1472 animal.flags |= BREEDER;
1473 }
1474 }
1475
1476 pub fn release(&mut self, p: usize) {
1481 while let Some(a) = self
1482 .wildlife
1483 .pastures
1484 .get(&p)
1485 .and_then(|x| x.livestock.last().copied())
1486 {
1487 self.assign(a, None);
1488 }
1489 self.wildlife.pasture_list.retain(|&x| x != p);
1490 }
1491
1492 pub fn bury(&mut self) -> bool {
1494 let dying = std::mem::take(&mut self.wildlife.dying);
1495 let changed = !dying.is_empty();
1496 for a in dying {
1497 if let Some(animal) = self.wildlife.animals.remove(&a) {
1498 self.wildlife.tree.remove(animal.character.tree_slot);
1500 if let Some(h) = animal.herd {
1501 self.wildlife.herds[h].animals.retain(|&x| x != a);
1502 }
1503 }
1504 self.wildlife.kinds.remove(&a);
1505 if let Some(p) = self.placed.get_mut(a) {
1506 p.alive = false;
1507 }
1508 self.scheduler.remove(a);
1509 }
1510 changed
1511 }
1512}
1513
1514fn inside(area: &[i16; 4], cell: i32, n: i32) -> bool {
1516 let (x, y) = (cell % n, cell / n);
1517 let (ax, ay, aw, ah) = (
1518 area[0] as i32,
1519 area[1] as i32,
1520 area[2] as i32,
1521 area[3] as i32,
1522 );
1523 !(x < ax || y < ay || ax + aw <= x || ay + ah <= y)
1524}
1525
1526fn area_around(n: i32, cell: i32, size: i32) -> [i16; 4] {
1528 let half = size / 2;
1529 let x = (cell % n - half).max(0);
1530 let y = (cell / n - half).max(0);
1531 let mut w = size;
1532 let mut h = size;
1533 if n <= w + x {
1534 w = n - x - 1;
1535 }
1536 if n <= h + y {
1537 h = n - y - 1;
1538 }
1539 [x as i16, y as i16, w as i16, h as i16]
1540}
1541
1542fn nearest_ground(cells: &Cells, n: i32, home: i32) -> i32 {
1546 let free = |c: i32| {
1547 c >= 0
1548 && (c as usize) < cells.types.len()
1549 && cells.types[c as usize] == CellType(2)
1550 && cells.occupants[c as usize].is_none()
1551 };
1552 let mut s = 3;
1553 loop {
1554 s += 2;
1555 let half = s / 2;
1556 let x0 = (home % n - half).max(0);
1557 let y0 = (home / n - half).max(0);
1558 let mut w = s;
1559 if n <= s + x0 {
1560 w = n - x0 - 1;
1561 }
1562 let mut h = s;
1563 if n <= s + y0 {
1564 h = n - y0 - 1;
1565 }
1566 let bottom = y0 - 1 + h;
1567 let right = w - 1 + x0;
1568 for x in x0..=right {
1569 if free(y0 * n + x) {
1570 return y0 * n + x;
1571 }
1572 if free(n * bottom + x) {
1573 return n * bottom + x;
1574 }
1575 }
1576 let mut y = y0;
1577 loop {
1578 y += 1;
1579 if y > bottom - 1 {
1580 break;
1581 }
1582 if free(n * y + x0) {
1583 return x0 + n * y;
1584 }
1585 if free(n * y + right) {
1586 return y * n + right;
1587 }
1588 }
1589 if 30 < s {
1590 return home;
1591 }
1592 }
1593}