mirror of
https://github.com/osmarks/ewo3.git
synced 2026-05-19 12:02:06 +00:00
'fix' plants somewhat
This commit is contained in:
Generated
+138
-48
@@ -70,6 +70,15 @@ version = "1.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
|
||||
|
||||
[[package]]
|
||||
name = "approx"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "argh"
|
||||
version = "0.1.14"
|
||||
@@ -197,6 +206,12 @@ version = "3.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
|
||||
|
||||
[[package]]
|
||||
name = "by_address"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.16.1"
|
||||
@@ -456,27 +471,6 @@ version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||
|
||||
[[package]]
|
||||
name = "enum-map"
|
||||
version = "2.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9"
|
||||
dependencies = [
|
||||
"enum-map-derive",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enum-map-derive"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
@@ -510,7 +504,6 @@ dependencies = [
|
||||
"anyhow",
|
||||
"argh",
|
||||
"bincode",
|
||||
"enum-map",
|
||||
"euclid",
|
||||
"fastrand",
|
||||
"futures-util",
|
||||
@@ -524,10 +517,11 @@ dependencies = [
|
||||
"imgui-winit-support",
|
||||
"indexmap",
|
||||
"lazy_static",
|
||||
"linearize",
|
||||
"ndarray",
|
||||
"ndarray-conv",
|
||||
"noise-functions",
|
||||
"oklab",
|
||||
"palette",
|
||||
"raw-window-handle 0.5.2",
|
||||
"rayon",
|
||||
"seahash",
|
||||
@@ -1005,6 +999,31 @@ dependencies = [
|
||||
"redox_syscall 0.7.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linearize"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6e1430c89633736996fd763822abd252e395dbccaaee33be601b4d59678a93e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"linearize-derive",
|
||||
"rand 0.8.5",
|
||||
"rand 0.9.2",
|
||||
"serde",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linearize-derive"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f657db73fbcad5341c5991ddee6c464d4bfd521575c0dc1a47913e0f434defeb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.15"
|
||||
@@ -1278,16 +1297,6 @@ version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666"
|
||||
|
||||
[[package]]
|
||||
name = "oklab"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1e35ab3c8efa6bc97d651abe7fb051aebb30c925a450ff6722cf9c797a938cc"
|
||||
dependencies = [
|
||||
"fast-srgb8",
|
||||
"rgb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
@@ -1313,6 +1322,30 @@ dependencies = [
|
||||
"ttf-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "palette"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"fast-srgb8",
|
||||
"palette_derive",
|
||||
"phf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "palette_derive"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30"
|
||||
dependencies = [
|
||||
"by_address",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.3"
|
||||
@@ -1342,6 +1375,48 @@ version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
|
||||
dependencies = [
|
||||
"phf_macros",
|
||||
"phf_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"rand 0.8.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_macros"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.14"
|
||||
@@ -1434,9 +1509,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.85"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -1473,7 +1548,16 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
|
||||
dependencies = [
|
||||
"rand_core 0.9.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1483,7 +1567,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1495,6 +1579,12 @@ dependencies = [
|
||||
"getrandom 0.2.15",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
|
||||
|
||||
[[package]]
|
||||
name = "raw-window-handle"
|
||||
version = "0.5.2"
|
||||
@@ -1569,12 +1659,6 @@ dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rgb"
|
||||
version = "0.8.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4"
|
||||
|
||||
[[package]]
|
||||
name = "rustfft"
|
||||
version = "6.4.1"
|
||||
@@ -1750,6 +1834,12 @@ version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.9"
|
||||
@@ -1928,9 +2018,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.49.0"
|
||||
version = "1.50.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86"
|
||||
checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
@@ -2035,7 +2125,7 @@ dependencies = [
|
||||
"http",
|
||||
"httparse",
|
||||
"log",
|
||||
"rand",
|
||||
"rand 0.8.5",
|
||||
"sha1",
|
||||
"thiserror 1.0.61",
|
||||
"utf-8",
|
||||
@@ -2073,9 +2163,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "virtue"
|
||||
|
||||
+2
-2
@@ -28,7 +28,6 @@ smallvec = { version = "1", features = ["serde"] }
|
||||
argh = "0.1"
|
||||
ndarray-conv = "0.6.0"
|
||||
ndarray = "0.17.2"
|
||||
enum-map = { version = "2.7.3", features = ["serde"] }
|
||||
imgui = "0.12"
|
||||
imgui-winit-support = "0.12"
|
||||
imgui-glow-renderer = "0.12"
|
||||
@@ -37,7 +36,8 @@ glutin = "0.31"
|
||||
glutin-winit = "0.4"
|
||||
raw-window-handle = "0.5"
|
||||
winit = "0.29"
|
||||
oklab = "1.1.2"
|
||||
linearize = { version = "0.1.6", features = ["derive", "serde-1"] }
|
||||
palette = "0.7.6"
|
||||
|
||||
[[bin]]
|
||||
name = "render"
|
||||
|
||||
+10
-10
@@ -5,7 +5,7 @@ use indexmap::IndexMap;
|
||||
use hecs::Entity;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use enum_map::{Enum, EnumMap};
|
||||
use linearize::{Linearize, StaticMap};
|
||||
|
||||
use crate::map::*;
|
||||
use crate::plant;
|
||||
@@ -22,7 +22,7 @@ pub enum NonFungibleItem {
|
||||
Seed(plant::Genome)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Enum, Copy)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Linearize, Copy)]
|
||||
pub enum HealthChangeType {
|
||||
BluntForce,
|
||||
Magic,
|
||||
@@ -187,8 +187,8 @@ impl HealthChangeModifier {
|
||||
pub struct Health {
|
||||
pub current: f32,
|
||||
pub max: f32,
|
||||
pub health_change_totals: EnumMap<HealthChangeType, f32>,
|
||||
pub health_change_modifiers: EnumMap<HealthChangeType, HealthChangeModifier>
|
||||
pub health_change_totals: StaticMap<HealthChangeType, f32>,
|
||||
pub health_change_modifiers: StaticMap<HealthChangeType, HealthChangeModifier>
|
||||
}
|
||||
|
||||
impl Health {
|
||||
@@ -204,8 +204,8 @@ impl Health {
|
||||
Self {
|
||||
current,
|
||||
max,
|
||||
health_change_modifiers: EnumMap::from_fn(|_| HealthChangeModifier::default()),
|
||||
health_change_totals: EnumMap::from_fn(|_| 0.0)
|
||||
health_change_modifiers: StaticMap::from_fn(|_| HealthChangeModifier::default()),
|
||||
health_change_totals: StaticMap::from_fn(|_| 0.0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,8 +221,8 @@ impl Health {
|
||||
Self {
|
||||
current: f32::MAX,
|
||||
max: f32::MAX,
|
||||
health_change_modifiers: EnumMap::from_fn(|_| HealthChangeModifier::invulnerable()),
|
||||
health_change_totals: EnumMap::from_fn(|_| 0.0)
|
||||
health_change_modifiers: StaticMap::from_fn(|_| HealthChangeModifier::invulnerable()),
|
||||
health_change_totals: StaticMap::from_fn(|_| 0.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -395,10 +395,10 @@ pub struct Plant {
|
||||
}
|
||||
|
||||
impl Plant {
|
||||
pub fn new(genome: plant::Genome) -> Self {
|
||||
pub fn new(genome: plant::Genome, size: f32) -> Self {
|
||||
Self {
|
||||
genome,
|
||||
current_size: 0.1,
|
||||
current_size: size * 0.1,
|
||||
nutrients_consumed: 0.0,
|
||||
nutrients_added: 0.0,
|
||||
water_consumed: 0.0,
|
||||
|
||||
+19
-8
@@ -302,7 +302,12 @@ async fn game_tick(state: &mut GameState) -> Result<()> {
|
||||
if state.ticks % FIELD_DECAY_DELAY == 0 {
|
||||
state.dynamic_soil_nutrients.for_each_mut(|nutrients| *nutrients *= 0.9999);
|
||||
} else if state.ticks % FIELD_DECAY_DELAY == 1 {
|
||||
state.dynamic_groundwater.for_each_mut(|water| *water *= 0.999);
|
||||
for (pos, water) in state.dynamic_groundwater.iter_mut() {
|
||||
*water *= 0.999;
|
||||
if state.map.water[pos] > 0.0 {
|
||||
*water *= 0.9; // reversion to baseline much faster in active water areas
|
||||
}
|
||||
}
|
||||
} else if state.ticks % FIELD_DECAY_DELAY == 2 {
|
||||
state.dynamic_soil_nutrients = smooth(&state.dynamic_soil_nutrients, 3);
|
||||
} else if state.ticks % FIELD_DECAY_DELAY == 3 {
|
||||
@@ -472,7 +477,7 @@ async fn game_tick(state: &mut GameState) -> Result<()> {
|
||||
}
|
||||
|
||||
if let Some(other) = maybe_other {
|
||||
// TODO: multiple seeds from one plant with different genomes\
|
||||
// TODO: multiple seeds from one plant with different hybridizations?
|
||||
let [plant, other_plant] = state.world.query_disjoint_mut::<&mut Plant, 2>([entity, other]);
|
||||
let plant = plant?;
|
||||
let other_plant = other_plant?;
|
||||
@@ -483,18 +488,23 @@ async fn game_tick(state: &mut GameState) -> Result<()> {
|
||||
if !state.map.heightmap.in_range(newpos) || state.positions.entities[newpos].is_some() || !hybrid_genome.terrain_valid(&state.map.get_terrain(newpos)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let child_size = (plant.genome.initial_size_scale() + other_plant.genome.initial_size_scale()) * 0.5;
|
||||
|
||||
buffer.cmd.spawn((
|
||||
Position::single_tile(newpos, MapLayer::Entities),
|
||||
Render('+'),
|
||||
Health::new(1.0, 1.0),
|
||||
Plant::new(hybrid_genome.clone()),
|
||||
// TODO: work out more reasonable health/size parameterization, or at least factor this out
|
||||
Health::new(1.0 + (child_size - 1.0) * 2.0, 1.0 + (child_size - 1.0) * 2.0),
|
||||
Plant::new(hybrid_genome.clone(), child_size),
|
||||
NewlyAdded
|
||||
));
|
||||
plant.children += 1;
|
||||
other_plant.children += 1;
|
||||
// TODO: can this go negative?
|
||||
plant.current_size -= PLANT_CHILD_COST;
|
||||
other_plant.current_size -= PLANT_CHILD_COST;
|
||||
// TODO: gendering?
|
||||
plant.current_size -= plant.genome.initial_size_scale() * 0.5;
|
||||
other_plant.current_size -= other_plant.genome.initial_size_scale() * 0.5;
|
||||
state.metrics.plants_reproduced += 1;
|
||||
break;
|
||||
}
|
||||
@@ -904,12 +914,13 @@ async fn main() -> Result<()> {
|
||||
let radius = state.map.radius();
|
||||
let pos = Coord::origin() + sample_range(&mut state.rng, radius);
|
||||
if genome.base_growth_rate(state.actual_soil_nutrients(pos), state.actual_groundwater(pos), state.baseline_temperature[pos], state.baseline_salt[pos], &state.map.get_terrain(pos)) > 0.2 && !used.contains(&pos) {
|
||||
let initial_size = genome.initial_size_scale();
|
||||
batch.push((
|
||||
Position::single_tile(pos, MapLayer::Entities),
|
||||
Render('+'),
|
||||
Health::new(1.0, 1.0),
|
||||
Health::new(1.0 + (initial_size - 1.0) * 2.0, 1.0 + (initial_size - 1.0) * 2.0),
|
||||
//ShrinkOnDeath,
|
||||
Plant::new(genome),
|
||||
Plant::new(genome, initial_size),
|
||||
NewlyAdded
|
||||
));
|
||||
used.insert(pos);
|
||||
|
||||
+26
-18
@@ -1,6 +1,7 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::worldgen::TerrainType;
|
||||
use crate::util::*;
|
||||
use crate::util::config::*;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum CropType {
|
||||
@@ -25,6 +26,7 @@ pub struct Genome {
|
||||
mature_size: f32,
|
||||
lifespan_multiplier: f32,
|
||||
reproduction_rate: f32,
|
||||
initial_size_scale: f32
|
||||
// TODO number of seeds produced?
|
||||
// TODO color trait
|
||||
}
|
||||
@@ -47,10 +49,10 @@ impl Genome {
|
||||
}
|
||||
let temperature_diff = (temperature - sigmoid(self.optimal_temperature)).powf(2.0);
|
||||
let base = 1.0
|
||||
- self.nutrient_addition_rate() * 0.16 // nutrient enrichment has a growth tradeoff
|
||||
- self.water_tolerance * 0.08
|
||||
- self.temperature_tolerance * 0.07
|
||||
- self.salt_tolerance.max(0.0) * 0.05;
|
||||
- self.nutrient_addition_rate() * 0.04 // nutrient enrichment has a growth tradeoff
|
||||
- self.water_tolerance * 0.11
|
||||
- self.temperature_tolerance * 0.09
|
||||
- self.salt_tolerance.max(0.0) * 0.01;
|
||||
let base = base.max(0.0);
|
||||
|
||||
let water_tolerance_coefficient = 13.0 * (1.0 + (-self.water_tolerance).exp());
|
||||
@@ -89,6 +91,10 @@ impl Genome {
|
||||
self.nutrient_addition_rate.max(0.0)
|
||||
}
|
||||
|
||||
pub fn initial_size_scale(&self) -> f32 {
|
||||
self.initial_size_scale.exp()
|
||||
}
|
||||
|
||||
pub fn reproduction_rate(&self) -> f32 {
|
||||
sigmoid(self.reproduction_rate)
|
||||
}
|
||||
@@ -106,10 +112,10 @@ impl Genome {
|
||||
// Size is something like total mass of a 1m^2 collection of this.
|
||||
// TODO pick these more precisely.
|
||||
let (nutrient_addition_rate, optimal_water_level, optimal_temperature, salt_tolerance, lifespan_multiplier, mature_size, reproduction_rate) = match crop_type {
|
||||
CropType::Grass => (-10.0,-1.0,-0.5, 0.0, 0.5, -1.0, 0.0), // TODO: tie reproduction rate to something else?
|
||||
CropType::EucalyptusTree => (-10.0, 1.0, 0.0, 0.1, 5.0, 6.0, -4.0),
|
||||
CropType::BushTomato => (-10.0, 0.0, 1.0, 0.2, 1.5, 1.0, -3.0),
|
||||
CropType::GoldenWattleTree => ( 2.0, 0.5, 0.2, 0.7, 3.0, 4.0, -4.0),
|
||||
CropType::Grass => (-10.0,-1.0,-0.5, 0.0, 0.5, 0.0, 0.0), // TODO: tie reproduction rate to something else?
|
||||
CropType::EucalyptusTree => (-10.0, 1.0, 0.0, 0.6, 5.0, 6.0, -4.0),
|
||||
CropType::BushTomato => (-10.0, 0.0, 1.0, 1.2, 1.5, 1.0, -3.0),
|
||||
CropType::GoldenWattleTree => ( 2.0, 0.5, 0.2, 4.0, 3.0, 4.0, -4.0),
|
||||
|
||||
};
|
||||
|
||||
@@ -123,7 +129,8 @@ impl Genome {
|
||||
salt_tolerance: normal(rng) + salt_tolerance,
|
||||
mature_size,
|
||||
lifespan_multiplier,
|
||||
reproduction_rate
|
||||
reproduction_rate,
|
||||
initial_size_scale: mature_size * 0.5 // TODO
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,15 +143,16 @@ impl Genome {
|
||||
if self.crop_type != other.crop_type { return None }
|
||||
Some(Genome {
|
||||
crop_type: self.crop_type,
|
||||
nutrient_addition_rate: (self.nutrient_addition_rate + other.nutrient_addition_rate) / 2.0 + normal_scaled(rng, 0.0, 0.03),
|
||||
optimal_water_level: (self.optimal_water_level + other.optimal_water_level) / 2.0 + normal_scaled(rng, 0.0, 0.03),
|
||||
optimal_temperature: (self.optimal_temperature + other.optimal_temperature) / 2.0 + normal_scaled(rng, 0.0, 0.03),
|
||||
temperature_tolerance: (self.temperature_tolerance + other.temperature_tolerance) / 2.0 + normal_scaled(rng, 0.0, 0.2),
|
||||
water_tolerance: (self.water_tolerance + other.water_tolerance) / 2.0 + normal_scaled(rng, 0.0, 0.2),
|
||||
salt_tolerance: (self.salt_tolerance + other.salt_tolerance) / 2.0 + normal_scaled(rng, 0.0, 0.2),
|
||||
mature_size: (self.mature_size + other.mature_size) / 2.0 + normal_scaled(rng, 0.0, 0.1),
|
||||
lifespan_multiplier: (self.lifespan_multiplier + other.lifespan_multiplier) / 2.0 + normal_scaled(rng, 0.0, 0.1),
|
||||
reproduction_rate: (self.reproduction_rate + other.reproduction_rate) / 2.0 + normal_scaled(rng, 0.0, 0.05),
|
||||
nutrient_addition_rate: (self.nutrient_addition_rate + other.nutrient_addition_rate) / 2.0 + EVOLUTION_RATE * normal_scaled(rng, 0.0, 0.03),
|
||||
optimal_water_level: (self.optimal_water_level + other.optimal_water_level) / 2.0 + EVOLUTION_RATE * normal_scaled(rng, 0.0, 0.03),
|
||||
optimal_temperature: (self.optimal_temperature + other.optimal_temperature) / 2.0 + EVOLUTION_RATE * normal_scaled(rng, 0.0, 0.03),
|
||||
temperature_tolerance: (self.temperature_tolerance + other.temperature_tolerance) / 2.0 + EVOLUTION_RATE * normal_scaled(rng, 0.0, 0.1),
|
||||
water_tolerance: (self.water_tolerance + other.water_tolerance) / 2.0 + EVOLUTION_RATE * normal_scaled(rng, 0.0, 0.02),
|
||||
salt_tolerance: (self.salt_tolerance + other.salt_tolerance) / 2.0 + EVOLUTION_RATE * normal_scaled(rng, 0.0, 0.02),
|
||||
mature_size: (self.mature_size + other.mature_size) / 2.0 + EVOLUTION_RATE * normal_scaled(rng, 0.0, 0.1),
|
||||
lifespan_multiplier: (self.lifespan_multiplier + other.lifespan_multiplier) / 2.0 + EVOLUTION_RATE * normal_scaled(rng, 0.0, 0.1),
|
||||
reproduction_rate: (self.reproduction_rate + other.reproduction_rate) / 2.0 + EVOLUTION_RATE * normal_scaled(rng, 0.0, 0.05),
|
||||
initial_size_scale: (self.initial_size_scale + other.initial_size_scale) / 2.0 + EVOLUTION_RATE * normal_scaled(rng, 0.0, 0.1),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+39
-20
@@ -3,12 +3,6 @@ extern crate test;
|
||||
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use argh::FromArgs;
|
||||
use ewo3::components::{Health, MapLayer, Plant, Position, PositionIndex, Render};
|
||||
use ewo3::map::*;
|
||||
use ewo3::save::SavedGame;
|
||||
use ewo3::world_serde;
|
||||
use ewo3::worldgen::*;
|
||||
use ewo3::util::config::*;
|
||||
use glow::HasContext;
|
||||
use glutin::config::ConfigTemplateBuilder;
|
||||
use glutin::context::{ContextAttributesBuilder, NotCurrentGlContext, PossiblyCurrentContext};
|
||||
@@ -21,12 +15,22 @@ use ndarray::{Array1, Array2, Axis};
|
||||
use hecs::World;
|
||||
use image::{ImageBuffer, Rgb};
|
||||
use imgui_winit_support::{HiDpiMode, WinitPlatform};
|
||||
use palette::IntoColor;
|
||||
use std::collections::HashMap;
|
||||
use std::num::NonZeroU32;
|
||||
use std::time::Instant;
|
||||
use winit::event::{Event, WindowEvent};
|
||||
use winit::event_loop::EventLoopBuilder;
|
||||
use raw_window_handle::HasRawWindowHandle;
|
||||
use linearize::{Linearize, LinearizeExt};
|
||||
|
||||
use ewo3::components::{Health, MapLayer, Plant, Position, PositionIndex, Render};
|
||||
use ewo3::map::*;
|
||||
use ewo3::plant::CropType;
|
||||
use ewo3::save::SavedGame;
|
||||
use ewo3::world_serde;
|
||||
use ewo3::worldgen::*;
|
||||
use ewo3::util::config::*;
|
||||
|
||||
#[derive(FromArgs)]
|
||||
/// Render world/debug fields from generated terrain or a saved game.
|
||||
@@ -130,19 +134,23 @@ define_fields! {
|
||||
DynamicSoil => "dynamic_soil",
|
||||
EntityHealth => "health",
|
||||
EntityHealthFraction => "health_fraction",
|
||||
PlantsType => "plant_type"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Linearize)]
|
||||
enum ColorSpace {
|
||||
Rgb,
|
||||
Oklab,
|
||||
Hsv
|
||||
}
|
||||
|
||||
// TODO: do this better
|
||||
impl ColorSpace {
|
||||
fn parse(s: &str) -> Self {
|
||||
match s {
|
||||
"oklab" => Self::Oklab,
|
||||
"hsv" => Self::Hsv,
|
||||
_ => Self::Rgb,
|
||||
}
|
||||
}
|
||||
@@ -151,6 +159,7 @@ impl ColorSpace {
|
||||
match self {
|
||||
ColorSpace::Rgb => "rgb",
|
||||
ColorSpace::Oklab => "oklab",
|
||||
ColorSpace::Hsv => "hsv",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -180,6 +189,7 @@ struct RenderData {
|
||||
dynamic_soil: Map<f32>,
|
||||
entity_health: Map<f32>,
|
||||
entity_health_fraction: Map<f32>,
|
||||
plants_type: Map<f32>,
|
||||
}
|
||||
|
||||
struct RenderedImage {
|
||||
@@ -222,6 +232,7 @@ fn sample_field(field: Field, position: Coord, data: &RenderData) -> f32 {
|
||||
Field::DynamicSoil => data.dynamic_soil[position],
|
||||
Field::EntityHealth => data.entity_health[position],
|
||||
Field::EntityHealthFraction => data.entity_health_fraction[position],
|
||||
Field::PlantsType => data.plants_type[position],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,14 +253,13 @@ fn field_range(field: Option<Field>, data: &RenderData) -> (f32, f32) {
|
||||
}
|
||||
|
||||
fn to_rgb(c1: f32, c2: f32, c3: f32, color_space: ColorSpace) -> [u8; 3] {
|
||||
let (r, g, b) = match color_space {
|
||||
ColorSpace::Rgb => (c1, c2, c3),
|
||||
ColorSpace::Oklab => {
|
||||
let rgb = oklab::oklab_to_srgb_f32(oklab::Oklab { l: c1.clamp(0.0, 1.0), a: c2 * 1.0 - 0.5, b: c3 * 1.0 - 0.5 });
|
||||
(rgb.r, rgb.g, rgb.b)
|
||||
}
|
||||
let transformed: palette::Srgb = match color_space {
|
||||
ColorSpace::Rgb => palette::Srgb::from_components((c1, c2, c3)).into_color(),
|
||||
ColorSpace::Oklab => palette::Oklab::from_components((c1.clamp(0.0, 1.0), c2 * 1.0 - 0.5, c3 * 1.0 - 0.5)).into_color(),
|
||||
ColorSpace::Hsv => palette::Hsv::from_components((c1 * 360.0, c2, c3)).into_color(),
|
||||
};
|
||||
[(r * 255.0) as u8, (g * 255.0) as u8, (b * 255.0) as u8]
|
||||
|
||||
[(transformed.red * 255.0) as u8, (transformed.green * 255.0) as u8, (transformed.blue * 255.0) as u8]
|
||||
}
|
||||
|
||||
fn build_derived_data(
|
||||
@@ -287,6 +297,7 @@ fn build_derived_data(
|
||||
let mut plants = Map::new(world.radius, 0.0f32);
|
||||
let mut plants_age = Map::new(world.radius, 0.0f32);
|
||||
let mut plants_lifespan_fraction = Map::new(world.radius, 0.0f32);
|
||||
let mut plants_type = Map::new(world.radius, 0.0f32);
|
||||
for (position, plant) in ecs_world.query::<(&Position, &Plant)>().iter() {
|
||||
let pos = position.head();
|
||||
if !plants.in_range(pos) {
|
||||
@@ -304,10 +315,17 @@ fn build_derived_data(
|
||||
}
|
||||
plants_age[pos] = plant.age as f32;
|
||||
plants_lifespan_fraction[pos] = plant.age as f32 / (plant.genome.lifespan() * PLANT_LIFESPAN_SCALE);
|
||||
match plant.genome.crop_type {
|
||||
CropType::Grass => plants_type[pos] = 1.0f32,
|
||||
CropType::BushTomato => plants_type[pos] = 2.0f32,
|
||||
CropType::GoldenWattleTree => plants_type[pos] = 3.0f32,
|
||||
CropType::EucalyptusTree => plants_type[pos] = 0.0f32,
|
||||
}
|
||||
}
|
||||
|
||||
let mut entity_health = Map::new(world.radius, 0.0f32);
|
||||
let mut entity_health_fraction = Map::new(world.radius, 0.0f32);
|
||||
|
||||
for (position, health) in ecs_world.query::<(&Position, &Health)>().iter() {
|
||||
let pos = position.head();
|
||||
if !plants.in_range(pos) {
|
||||
@@ -332,6 +350,7 @@ fn build_derived_data(
|
||||
dynamic_soil: dynamic_soil_nutrients,
|
||||
entity_health,
|
||||
entity_health_fraction,
|
||||
plants_type,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -781,10 +800,10 @@ fn run_window(data: RenderData, mut settings: RenderSettings) -> Result<()> {
|
||||
settings.normalize = normalize;
|
||||
}
|
||||
|
||||
let mut cs_idx = if settings.color_space == ColorSpace::Rgb { 0 } else { 1 };
|
||||
let cs_labels = ["rgb", "oklab"];
|
||||
if ui.combo_simple_string("Color space", &mut cs_idx, &cs_labels) {
|
||||
settings.color_space = if cs_idx == 0 { ColorSpace::Rgb } else { ColorSpace::Oklab };
|
||||
let mut cs_idx = settings.color_space.linearize();
|
||||
// TODO this should be static
|
||||
if ui.combo_simple_string("Color space", &mut cs_idx, &ColorSpace::variants().map(|x| x.name()).collect::<Vec<&'static str>>()) {
|
||||
settings.color_space = ColorSpace::from_linear(cs_idx).unwrap();
|
||||
}
|
||||
|
||||
if pca_mode {
|
||||
@@ -969,10 +988,10 @@ fn run_window(data: RenderData, mut settings: RenderSettings) -> Result<()> {
|
||||
let color = imgui::ImColor32::from_rgba_f32s(1.0, 1.0, 1.0, 1.0);
|
||||
let draw = ui.get_window_draw_list();
|
||||
draw.add_line([cx - len, cy], [cx + len, cy], color)
|
||||
.thickness(3.0)
|
||||
.thickness(2.0)
|
||||
.build();
|
||||
draw.add_line([cx, cy - len], [cx, cy + len], color)
|
||||
.thickness(3.0)
|
||||
.thickness(2.0)
|
||||
.build();
|
||||
} else {
|
||||
ui.text("hover map to zoom");
|
||||
|
||||
+5
-5
@@ -18,9 +18,9 @@ pub mod config {
|
||||
pub const PLANT_TICK_DELAY: u64 = 128;
|
||||
pub const FIELD_DECAY_DELAY: u64 = 100;
|
||||
pub const PLANT_GROWTH_SCALE: f32 = 0.01;
|
||||
pub const SOIL_NUTRIENT_CONSUMPTION_RATE: f32 = 0.5;
|
||||
pub const SOIL_NUTRIENT_FIXATION_RATE: f32 = 0.002;
|
||||
pub const WATER_CONSUMPTION_RATE: f32 = 0.1;
|
||||
pub const SOIL_NUTRIENT_CONSUMPTION_RATE: f32 = 0.8;
|
||||
pub const SOIL_NUTRIENT_FIXATION_RATE: f32 = 0.1;
|
||||
pub const WATER_CONSUMPTION_RATE: f32 = 0.05;
|
||||
pub const PLANT_IDLE_WATER_CONSUMPTION_OFFSET: f32 = 0.2;
|
||||
pub const PLANT_DIEOFF_THRESHOLD: f32 = 0.3;
|
||||
pub const PLANT_DIEOFF_RATE: f32 = 0.2;
|
||||
@@ -32,8 +32,8 @@ pub mod config {
|
||||
pub const SOIL_NUTRIENT_DECOMP_RETURN_RATE: f32 = 1.0 / SOIL_NUTRIENT_CONSUMPTION_RATE * 0.6;
|
||||
pub const PLANT_LIFESPAN_SCALE: f32 = 1.0 / PLANT_GROWTH_SCALE;
|
||||
pub const PLANT_REPRODUCTION_ATTEMPT_COST: f32 = 0.01;
|
||||
pub const PLANT_CHILD_COST: f32 = 0.05; // TODO genome parameter, tie to initial size
|
||||
pub const INITIAL_PLANTS: usize = 262144;
|
||||
pub const INITIAL_PLANTS: usize = 131072;
|
||||
pub const EVOLUTION_RATE: f32 = 0.1;
|
||||
// Runtime game logic (misc)
|
||||
pub const VIEW: i32 = 15;
|
||||
pub const RANDOM_DESPAWN_INV_RATE: u64 = 4000;
|
||||
|
||||
Reference in New Issue
Block a user