Skip to content

Commit f7808e5

Browse files
committed
health, food consumption and pop growth linked, 1st draft
1 parent e1381c5 commit f7808e5

File tree

6 files changed

+368
-237
lines changed

6 files changed

+368
-237
lines changed

.idea/workspace.xml

Lines changed: 129 additions & 206 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"cells": [],
3+
"metadata": {},
4+
"nbformat": 4,
5+
"nbformat_minor": 2
6+
}

notebooks/health.ipynb

Lines changed: 185 additions & 0 deletions
Large diffs are not rendered by default.

src/agriculture/systems.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ pub fn base_yield(seed_ratio: u8, area: f32, fertility: f32) -> f32 {
5555
bpkm * area * FALLOW_MULT
5656
}
5757

58-
// Normal grain consumption for cohort
58+
/// Normal yearly grain consumption for cohort
5959
pub fn grain_for_cohort(c: &Cohort) -> f32 {
6060
let &Cohort { pop, mean_age, male, .. } = c;
6161
let bm = if mean_age < 14. {
@@ -73,6 +73,7 @@ pub fn grain_for_cohort(c: &Cohort) -> f32 {
7373
(bm * pop as f64 * male + bf as f64 * pop as f64 * (1. - male)) as f32
7474
}
7575

76+
/// normal yearly grain cosump for pop
7677
pub fn grain_for_pop(p: &RegionPop) -> f32 {
7778
p.cohorts.iter().fold(0., |grain, c| grain_for_cohort(c) + grain)
7879
}

src/pop/components.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ pub struct FoodConsumption {
4040
#[derive(Component, Clone, Debug, Serialize, Deserialize, PartialOrd, PartialEq, TypescriptDefinition)]
4141
pub struct PopEst(pub usize);
4242

43-
const NUM_COHORTS: usize = 17;
43+
pub const NUM_COHORTS: usize = 17;
4444

4545
impl RegionPop {
46-
pub fn new(dist: &[f32; NUM_COHORTS], pop: usize) -> RegionPop {
46+
pub fn new(dist: &[f32], pop: usize) -> RegionPop {
4747
let cohorts = (0..NUM_COHORTS).map(|i| {
4848
Cohort::new(i * 5, dist[i as usize], pop)
4949
}).collect();
@@ -53,7 +53,7 @@ impl RegionPop {
5353
}
5454
}
5555

56-
pub fn update(&mut self, brs: &[f32; NUM_COHORTS], drs: &[f32; NUM_COHORTS], dt: u16) {
56+
pub fn update(&mut self, brs: &[f32], drs: &[f32], dt: u16) {
5757
let mut newborns = 0;
5858
for c in &mut self.cohorts {
5959
let br = lerp_pop_arr(c.mean_age, brs);
@@ -141,7 +141,7 @@ impl Cohort {
141141
}
142142
}
143143

144-
pub fn lerp_pop_arr(x: f64, arr: &[f32; NUM_COHORTS]) -> f64 {
144+
pub fn lerp_pop_arr(x: f64, arr: &[f32]) -> f64 {
145145
let l_i = (x / 5.).floor() as usize;
146146
let h_i = (x / 5.).ceil() as usize;
147147
let l: f64 = (arr[l_i].clone()).into();

src/pop/systems.rs

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,15 @@ use specs_derive;
44
use crate::misc::time::Date;
55
use chrono::Datelike;
66
use crate::prelude::*;
7+
use crate::pop::NUM_COHORTS;
78

9+
const DEATH_RATES: [f32; 17] = [
10+
0.2, 0.045, 0.035, 0.02, 0.007, 0.005, 0.005, 0.005,
11+
0.01, 0.015, 0.02, 0.03, 0.04, 0.06, 0.1, 0.3, 0.8
12+
];
13+
const BIRTH_RATES: [f32; 17] = [0., 0., 0., 0.01, 0.02, 0.55, 0.45, 0.25, 0.1, 0., 0., 0., 0., 0., 0., 0., 0.];
14+
const HARVEST_MONTH: u32 = 9;
15+
const HEALTH_CHANGE_RATE: f32 = 0.10;
816

917
pub struct PopUpdate {
1018
pub old_date: Date,
@@ -13,14 +21,8 @@ pub struct PopUpdate {
1321
// Changes Cohort health in response to food scarcity, disease, sanitation etc.
1422
pub struct HealthUpdate;
1523

16-
// The
17-
pub struct FoodConsumptionUpdate;
18-
19-
const DEATH_RATES: [f32; 17] = [
20-
0.2, 0.045, 0.035, 0.02, 0.007, 0.005, 0.005, 0.005,
21-
0.01, 0.015, 0.02, 0.03, 0.04, 0.06, 0.1, 0.3, 0.8
22-
];
23-
const BIRTH_RATES: [f32; 17] = [0., 0., 0., 0.01, 0.02, 0.55, 0.45, 0.25, 0.1, 0., 0., 0., 0., 0., 0., 0., 0.];
24+
// Recalculate Monthly Food Consumption
25+
pub struct FoodConsumptionSystem;
2426

2527
impl<'a> System<'a> for PopUpdate {
2628
type SystemData = (ReadStorage<'a, Health>,
@@ -34,61 +36,75 @@ impl<'a> System<'a> for PopUpdate {
3436
let dt = (*date - self.old_date).num_days();
3537
self.old_date = date.clone();
3638

37-
// if dt < 30 { return; }
38-
3939

40-
let mut b = true;
4140
for (p, h) in (&mut pop, &health).join() {
42-
p.update(&BIRTH_RATES, &DEATH_RATES, dt as u16);
43-
44-
if b {
45-
//dbg!(&p);
46-
b = false
47-
}
41+
let brs: ArrayVec<[f32; NUM_COHORTS]> = BIRTH_RATES.iter().map(|&br| br * h.health).collect();
42+
let drs: ArrayVec<[f32; NUM_COHORTS]> = DEATH_RATES.iter().map(|&dr| dr * h.health).collect();
43+
p.update(brs.as_slice(), &drs, dt as u16);
4844
}
4945
}
5046
}
5147
}
5248

49+
50+
51+
5352
impl<'a> System<'a> for HealthUpdate {
5453
type SystemData = (WriteStorage<'a, Health>,
55-
WriteStorage<'a, FoodConsumption>,
54+
ReadStorage<'a, FoodConsumption>,
5655
ReadStorage<'a, FoodStock>);
5756

58-
fn run(&mut self, (health, consump, food): Self::SystemData) {}
57+
fn run(&mut self, (mut health, consump, food): Self::SystemData) {
58+
for (health, consump, food) in (&mut health, &consump, &food).join() {
59+
let r = consump.ratio_of_norm;
60+
61+
// later add more interesting interactions with other systems
62+
let target_health = r;
63+
64+
65+
// half-life for health change is .7/rate, so .10 rate
66+
// ==> will get to half the difference in 7 months (periods)
67+
health.health += HEALTH_CHANGE_RATE * (target_health - health.health);
68+
}
69+
}
5970
}
6071

61-
impl<'a> System<'a> for FoodConsumptionUpdate {
72+
impl<'a> System<'a> for FoodConsumptionSystem {
6273
type SystemData = (WriteStorage<'a, FoodStock>,
6374
WriteStorage<'a, FoodConsumption>,
6475
ReadStorage<'a, RegionPop>,
65-
ReadStorage<'a, Health>,
6676
ReadExpect<'a, Date>);
6777

68-
fn run(&mut self, (mut stock, mut consump, pop, health, date): Self::SystemData) {
78+
fn run(&mut self, (mut stock, mut consump, pop, date): Self::SystemData) {
6979
if date.day() != 3 {
7080
return;
7181
}
7282

73-
let months_2_harvest = ((9 - date.month()) % 12) as f32;
83+
let months_2_harvest = ((HARVEST_MONTH - date.month()) % 12) as f32;
7484

75-
for (stock, mut consump, pop, health) in (&mut stock, &mut consump, &pop, &health).join() {
85+
for (mut stock, mut consump, pop) in (&mut stock, &mut consump, &pop).join() {
7686
let base_grain = grain_for_pop(pop);
7787
let abundance = stock.bushels / (base_grain * months_2_harvest / 12.);
78-
let r = if abundance > 1.3 {
88+
let r = if abundance > 1.4 {
7989
1.2
8090
} else if abundance > 0.8 {
8191
abundance.sqrt()
8292
} else if abundance > 0.6 {
8393
abundance
8494
} else {
85-
0.65
95+
0.6
8696
};
8797

8898
consump.consump = base_grain * r / 12.;
8999
consump.ratio_of_norm = r;
100+
101+
stock.bushels = (stock.bushels - consump.consump).max(0.);
90102
}
91103
}
92104
}
93105

106+
pub fn logistic(r: f32, x: f32, k: f32) -> f32 {
107+
r * x * (k - x) / k
108+
}
109+
94110

0 commit comments

Comments
 (0)