Skip to main content

banished_game/nature/
wildlife.rs

1//! Wild animals: PopulationComponent, HerdComponent, AnimalComponent and WildAnimalComponent. See
2//! docs/WILDLIFE-POPULATION.md.
3//!
4//! A population divides the map into cells of `cell` map cells. Each cell holds a capacity, set by
5//! its habitat, and a count that regrows and spreads every 300 s. The map is also divided into herd
6//! blocks. Each block starts one herd of `min..max` animals on a random habitable cell of the
7//! block. A herd rests for a while, then moves to another habitable cell of its block, and regrows
8//! from time to time. Its animals wander within an area around their home, idle, grow up and die of
9//! old age.
10//!
11//! Livestock (LivestockComponent) are animals too. Until a pasture of their kind takes them they
12//! roam like wild ones and wait in the town's list; in a pasture they keep to its area, a breeding
13//! male has young, and products gather. See docs/FARMING.md "Pastures".
14//!
15//! Original: `0x140169ab0`, `0x140168530`, `0x14016af20`.
16// vtable 0x1401604b0; vtable 0x140169fb0; +0x80
17
18use 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
32// +0x20
33/// AnimalComponent flag: a hunter has it.
34///
35/// Original: `FUN_14010c730`.
36pub const HUNTED: u32 = 0x100000;
37// +0x20
38/// AnimalComponent flag: wild.
39///
40/// Original: `FUN_14010c8d0`.
41pub const WILD: u32 = 0x400000;
42// +0x20
43/// AnimalComponent flag: young are due; the pasture's update has them born.
44///
45/// Original: `FUN_14010b8f0`, `FUN_14012c840`.
46pub const BIRTH: u32 = 0x200000;
47// +0x20
48/// AnimalComponent flag: may breed (a rancher's visit marks a random animal of the pasture).
49///
50/// Original: `FUN_14012cbf0`.
51pub const BREEDER: u32 = 0x800000;
52/// The animal walk mask (`3999`).
53const ANIMAL_WALK: u32 = 0xf9f;
54/// `DAT_140178934`.
55const PERIOD: f32 = 300.0;
56
57/// A population template's description and herd template (index into the placed-object
58/// templates).
59#[derive(Debug, Clone)]
60pub struct PopulationKind {
61    /// The population description.
62    pub desc: PopulationDescription,
63    /// The herd template it spawns, if any.
64    pub herd: Option<usize>,
65}
66
67/// The settings of a kind of herd.
68#[derive(Debug, Clone)]
69pub struct HerdKind {
70    /// The herd description.
71    pub desc: HerdDescription,
72    /// The animal template.
73    pub animal: usize,
74}
75
76/// The settings of a kind of animal.
77#[derive(Debug, Clone)]
78pub struct AnimalKind {
79    /// The animal description.
80    pub desc: AnimalDescription,
81    /// The raw-material (pile) templates a hunted animal leaves.
82    pub materials: Vec<usize>,
83    /// The character description: speeds and turning.
84    pub character: CharacterDescription,
85}
86
87/// A livestock template's LivestockDescription, resolved: the product's pile template, every
88/// `interval` × 300 s, and the stock slot.
89#[derive(Debug, Clone, Default, PartialEq)]
90pub struct LivestockKind {
91    /// The raw-material template it produces, if any.
92    pub product: Option<usize>,
93    /// The time between products, in seconds.
94    pub interval: f32,
95    /// The stock slot its product counts towards.
96    pub group: i32,
97}
98
99// +0x28; +0x30
100/// LivestockComponent: the pasture (entity), towards the next product.
101#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
102pub struct Livestock {
103    /// The pasture, if any.
104    pub pasture: Option<usize>,
105    /// The time towards the next product.
106    pub timer: i64,
107}
108
109// +0x28; +0x30; +0x40; +0x44
110/// PastureComponent's livestock side: the kind (animal template), its animals in joining order, the
111/// most it keeps (the window's slider), products gathered; with the MapComponent's area (x, y,
112/// width, height).
113#[derive(Debug, Clone, Default, PartialEq)]
114pub struct Pasture {
115    /// The animal template it keeps, if any.
116    pub kind: Option<usize>,
117    /// Its animals.
118    pub livestock: Vec<usize>,
119    /// The most animals it keeps.
120    pub limit: i32,
121    /// The amount produced that is not yet in piles.
122    pub produced: i32,
123    /// The area (x, y, width, height).
124    pub area: [i16; 4],
125}
126
127/// PopulationComponent.
128#[derive(Debug, Clone, PartialEq)]
129pub struct Population {
130    /// The entity.
131    pub entity: usize,
132    /// The template.
133    pub template: usize,
134    // +0x30
135    /// Cells per row.
136    pub width: i32,
137    // +0x38
138    /// Capacity, count and next count per cell.
139    pub cells: Vec<[i32; 3]>,
140    // +0x48
141    /// Herd blocks per row.
142    pub herd_width: i32,
143    // +0x60
144    /// Towards the next 300 s step.
145    pub clock: i64,
146    // +0x68
147    /// The next cell to recount.
148    pub cursor: i32,
149}
150
151/// HerdComponent.
152#[derive(Debug, Clone, PartialEq)]
153pub struct Herd {
154    /// The entity.
155    pub entity: usize,
156    /// The template.
157    pub template: usize,
158    // +0x28, +0x30
159    /// The population.
160    pub population: usize,
161    /// The herd's block in the population.
162    pub index: i32,
163    // +0x38
164    /// The animals (entities), in joining order.
165    pub animals: Vec<usize>,
166    // +0x48
167    /// Moving to the target (else resting).
168    pub moving: bool,
169    // +0x4c
170    /// The target map cell (−1 none).
171    pub target: i32,
172    // +0x50; +0x58
173    /// The rest time left.
174    pub rest: i64,
175    /// The time towards the next regrowth.
176    pub regrow: i64,
177}
178
179/// AnimalComponent and WildAnimalComponent, with the animal's CharacterComponent.
180pub struct Animal {
181    /// The template.
182    pub template: usize,
183    /// The character: position and movement.
184    pub character: Character,
185    // +0x28
186    /// WildAnimalComponent: the herd (index into [`Wildlife::herds`]).
187    pub herd: Option<usize>,
188    // +0x20
189    /// Component flags ([`HUNTED`], [`WILD`]).
190    pub flags: u32,
191    // +0x28
192    /// The home cell.
193    pub home: i32,
194    // +0x30
195    /// Until the next decision.
196    pub timer: i64,
197    // +0x38..+0x3e
198    /// The area it keeps to (x, y, width, height).
199    pub area: [i16; 4],
200    // +0x40
201    /// Male (the second mesh, antlers).
202    pub male: bool,
203    // +0x44, +0x48
204    /// The age in years.
205    pub age: f32,
206    /// The lifespan in years.
207    pub life: f32,
208    // +0x50
209    /// Until a breeding male's young (livestock only).
210    pub breed: i64,
211    /// LivestockComponent.
212    pub livestock: Option<Livestock>,
213    /// The model variant.
214    pub variant: usize,
215    /// The mesh.
216    pub mesh: usize,
217    /// Model scale.
218    ///
219    /// Original: `FUN_14010c7f0`.
220    pub scale: f32,
221    /// Queued for removal (entity flag `0x400`).
222    ///
223    /// Original: `FUN_1400c8370`.
224    pub dying: bool,
225}
226
227/// What a scheduled entity is.
228#[derive(Debug, Clone, Copy, PartialEq, Eq)]
229enum Kind {
230    Population(usize),
231    Herd(usize),
232    Animal,
233}
234
235/// The wildlife of a town.
236#[derive(Default)]
237pub struct Wildlife {
238    // Game +0x88
239    /// The characters' spatial tree (`Game`): citizens, animals, boats and nomads.
240    pub tree: crate::behaviour::character_tree::CharacterTree,
241    /// The animal populations.
242    pub populations: Vec<Population>,
243    /// The herds.
244    pub herds: Vec<Herd>,
245    /// Animals by entity.
246    pub animals: BTreeMap<usize, Animal>,
247    /// Templates by placed-object template index.
248    pub population_kinds: BTreeMap<usize, PopulationKind>,
249    /// The herd templates, by placed-object template index.
250    pub herd_kinds: BTreeMap<usize, HerdKind>,
251    /// The animal templates, by placed-object template index.
252    pub animal_kinds: BTreeMap<usize, AnimalKind>,
253    /// Animation groups by animal template and model variant.
254    pub groups: BTreeMap<(usize, usize), std::sync::Arc<AnimationGroup>>,
255    /// Entities queued for removal, in order.
256    pub dying: Vec<usize>,
257    kinds: BTreeMap<usize, Kind>,
258    /// LivestockDescriptions by animal template.
259    pub livestock_kinds: BTreeMap<usize, LivestockKind>,
260    // +0x80
261    /// The town's livestock without a pasture, in order.
262    pub unassigned: Vec<usize>,
263    // +0x90
264    /// The pastures, by entity.
265    pub pastures: BTreeMap<usize, Pasture>,
266    /// The town's list of pastures.
267    pub pasture_list: Vec<usize>,
268    /// The nomads, by entity.
269    pub nomads: BTreeMap<usize, crate::people::immigration::Nomad>,
270    /// The nomad templates, by template.
271    pub nomad_kinds: BTreeMap<usize, crate::people::immigration::NomadKind>,
272    /// The trader boats, by entity.
273    pub boats: BTreeMap<usize, crate::commerce::boat::Boat>,
274    /// The boat templates, by template.
275    pub boat_kinds: BTreeMap<usize, crate::commerce::boat::BoatKind>,
276}
277
278/// The town state wildlife reads and writes.
279pub struct Wild<'a, 't> {
280    /// The animals.
281    pub wildlife: &'a mut Wildlife,
282    /// The placed objects.
283    pub placed: &'a mut Vec<Placed>,
284    /// The object templates.
285    pub templates: &'a [Template],
286    /// The gameplay map.
287    pub cells: &'a Cells,
288    /// The ground's heights.
289    pub terrain: &'a HeightGrid<'t>,
290    /// The game's random numbers.
291    pub rng: &'a mut Random,
292    /// The entity scheduler.
293    pub scheduler: &'a mut EntityScheduler<usize>,
294}
295
296impl Population {
297    /// `FUN_1400544b0`: a cell's capacity: the description's when its block has habitat and
298    /// nothing forbidden (cell types, or an occupant with `no_occupants`).
299    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    /// The side of a herd block in population cells.
325    fn block(&self) -> i32 {
326        self.width / self.herd_width.max(1)
327    }
328
329    /// `FUN_140054880`: the share of a herd block's cells that are habitable.
330    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    /// `FUN_140054600`: the map cell at the centre of a random habitable population cell of
348    /// a herd block (`Rand(count)`), or −1 without one (no draw).
349    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    /// The capacity of the population cell holding map cell `cell`.
373    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    /// `FUN_140054220`: every cell regrows up to its capacity, then each count becomes the
384    /// weighted mean of the habitable cells within two (weight `16 − dx² − dy²`).
385    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    /// A saved PopulationComponent; returns its index.
426    ///
427    /// Original: `FUN_140054e00`.
428    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    /// A saved HerdComponent; returns its index.
436    ///
437    /// Original: `FUN_140127460`.
438    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    /// Restore an animal from a save: its animal component, its wild animal component, its
446    /// character and its livestock component.
447    ///
448    /// Original: `FUN_14010c310` (the animal component).
449    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    /// An animal dies (killed by a hunter, of old age, or in a herd without a habitat): it is
455    /// queued for removal and leaves its herd.
456    ///
457    /// Original: `FUN_1400c8370` on the animal.
458    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        // LivestockComponent's removal slot (`FUN_1401290d0`).
470        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    /// The animals a pasture has room for, its area over the kind's space per animal (none without
484    /// a kind).
485    ///
486    /// Original: `FUN_14012da40`.
487    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        // Deviation: a zero space would divide by zero in the original.
495        if space == 0 {
496            return 0;
497        }
498        area / space
499    }
500
501    /// The animation group of an animal.
502    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    /// `FUN_1400c8bf0` + `FUN_1400c9d70` for an entity without a map footprint: a placed
525    /// entry registered in its template's bucket.
526    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    /// The placed entry of [`Wild::create`] alone (its owner registers it in the buckets).
534    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    /// Start one population of a new town: its entity, then its herds.
559    ///
560    /// Original: `FUN_140054b80`, called by `FUN_1400a5eb0`.
561    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            // Registered after its animals (`FUN_1400c9d70` follows `FUN_140126420`).
607            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    /// The herd's area around its target (`FUN_140126fa0` / `FUN_140127810`): `area` wide,
614    /// kept a cell off the map's edge (the height test adds the possibly shortened width, as
615    /// the original does).
616    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    /// A new target in the herd's block; every animal keeps to the area around it. Without habitat
634    /// the herd's animals are removed.
635    ///
636    /// Original: `FUN_140127810`.
637    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    /// `FUN_140126420`: a new target, then `count` animals at random cells of its area.
667    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    /// `FUN_140126920`: animals join at the target until the herd has `target`.
707    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    /// `FUN_1400c8bf0` of an animal template and `FUN_14010c8d0`: placed with its model and
727    /// character, wild; a male takes the variant's second mesh.
728    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    /// `FUN_1400c8bf0`'s ModelComponent: the variant (random when the model says so) and its
740    /// mesh.
741    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    /// The animal of [`Wild::new_animal`] with its variant chosen (`FUN_14010c8d0`: placed,
756    /// turned, wild; a male takes the variant's second mesh).
757    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    /// `FUN_1401339e0`: the animal joins the herd and keeps to its area.
804    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    /// `FUN_1400c9d70` for an animal: its entity, the setup (`FUN_14010c220`, the lifespan),
814    /// the activation (`FUN_14010c0f0`: home where it stands, its area around it, then the
815    /// scheduled update with no time).
816    fn register_animal(&mut self, a: usize) {
817        self.register_animal_in(a, true);
818    }
819
820    /// [`Wild::register_animal`]; without `buckets` the owner registers the entity.
821    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        // CharacterComponent's start (`FUN_14010ee90`): into the tree.
832        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        // LivestockComponent's activation (`FUN_140129140`): without a pasture it waits in the
856        // town's list.
857        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    /// `FUN_14010c7f0`: the model grows from a third to full size by the adult age.
864    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    /// A scheduled visit of entity `e` with `elapsed` ticks.
875    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                // CharacterComponent's scheduled notify (`FUN_14010e950`): MoveTo's follow
881                // check (`FUN_1400cde40`).
882                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    /// `FUN_1400549d0`.
894    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    /// `FUN_1401270c0`.
924    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    /// `FUN_140126e50`: every animal stands in its area (`FUN_14010bfe0`).
973    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    /// AnimalComponent's scheduled update.
986    ///
987    /// Original: `FUN_14010b8f0`.
988    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        // A breeding male: once grown, young every `breed` years and up to as much again.
1002        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                        // `FUN_14011de20(.., 0x200000, 0)`.
1009                        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                // A home under an occupant other than a trading post (`+0x00`, its
1033                // TradeComponent) or no longer ground: a new home and area.
1034                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    /// `FUN_1400ca8d0` on the animal's stack, then (with `action`) `FUN_1400ca9b0`.
1087    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    /// A hunter has the animal: it stops what it does and stands.
1109    ///
1110    /// Original: `FUN_14010c730`.
1111    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    /// `FUN_14010b720`: play clip `anim` for `seconds`; with `turn`, face a random way.
1123    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            // FUN_14010b720: (second draw, first draw, 0) normalized; the direction that
1139            // normalized again, the heading of the first (`Vector3::Heading`).
1140            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    /// `FUN_14010b4f0` then `FUN_14010b2f0`: the nearest free ground in growing squares around
1151    /// the home becomes the home, and the area follows.
1152    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    /// LivestockComponent's scheduled update (`FUN_140129020`): in a pasture, an animal with a
1162    /// product adds one to the pasture's count every `interval` × 300 s.
1163    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        // Deviation: a zero interval would never leave the loop in the original.
1184        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    /// The animal joins pasture `to` (or the town's list) and leaves its old one; leaving a pasture
1204    /// it turns wild, joining one it keeps to its area.
1205    ///
1206    /// Original: `FUN_140129190`.
1207    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    /// `FUN_14010b3a0`: wild again, at home where it stands with an area around it, then the
1243    /// scheduled update with no time.
1244    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    /// `FUN_140129570`: no longer wild, the animal keeps to its pasture's area.
1259    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    /// A pasture with room takes the waiting livestock of its kind, in the town list's order, until
1278    /// full.
1279    ///
1280    /// Original: `FUN_14012c610`.
1281    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    /// Each animal with young due has them, while the pasture holds fewer than three over its room
1309    /// (the animals born join the end of the list and are seen too). Born animals are registered by
1310    /// the caller.
1311    ///
1312    /// Original: `FUN_14012c840`.
1313    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    /// A young animal of the pasture's kind next to its parent (or anywhere in the pasture, any age
1337    /// under a year, without one); male more likely the more females there are. With `buckets` it
1338    /// joins the entity manager's buckets here, else the caller's.
1339    ///
1340    /// Original: `FUN_14012db40`.
1341    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    /// The starting livestock of a kind, `count` animals around `at` (`spread` either way), males
1390    /// and females in turn from a random first; any age under a year. They wait, wild, for a
1391    /// pasture.
1392    ///
1393    /// Original: `FUN_1400a5fe0`.
1394    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            // `at`'s height, as the original passes it: the CharacterComponent's first update
1404            // stands it on the ground.
1405            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    // +0x48
1418    /// Livestock bought at a trading post, `count` animals at random between its first two create
1419    /// points (`a`, `b`), males and females in turn from a random first, turned at random; not
1420    /// wild, they keep to the cells between the points (`area`) until a pasture takes them. Each is
1421    /// `RandFloat` × half its lifespan old, which is still unset here (before the setup), so none.
1422    /// The owner registers the entities.
1423    ///
1424    /// Original: `FUN_14005b640`.
1425    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            // `a`'s height, as the original passes it: the CharacterComponent's first update
1442            // stands it on the ground.
1443            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    /// The pasture's message 0 (a rancher's visit): a random animal of it may breed.
1461    ///
1462    /// Original: `FUN_14012cbf0`.
1463    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    /// A pasture is removed: every animal goes back to the town's list, last first, and the
1477    /// pasture leaves the town's list.
1478    ///
1479    /// Original: `FUN_14012c310` (state 3) and `FUN_14012ccb0` (removal).
1480    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    /// The entity manager's removal of the queued animals (their components' removal slots).
1493    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                // CharacterComponent's end (`FUN_14010ee50`): out of the tree.
1499                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
1514/// `FUN_14010bfe0`: `cell` within `area`.
1515fn 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
1526/// `FUN_14010b2f0`: a `size` square around `cell`, clamped to the map.
1527fn 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
1542/// `FUN_14010b4f0`: the first ground cell without an occupant on the border of squares of
1543/// side 5, 7, … 31 around `home` (top and bottom rows by column, then the sides by row), else
1544/// `home`.
1545fn 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}