From 0c14c42619816e5e97fdef16658fc9bc869a0574 Mon Sep 17 00:00:00 2001 From: Patryk26g Date: Fri, 31 Jan 2025 23:27:46 +0100 Subject: [PATCH 1/6] Add radioactive chunk miche --- src/auto-evo/AutoEvoGlobalCache.cs | 8 ++++++++ src/auto-evo/steps/GenerateMiche.cs | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/auto-evo/AutoEvoGlobalCache.cs b/src/auto-evo/AutoEvoGlobalCache.cs index 363486151d7..f6b26c1259a 100644 --- a/src/auto-evo/AutoEvoGlobalCache.cs +++ b/src/auto-evo/AutoEvoGlobalCache.cs @@ -29,6 +29,9 @@ public class AutoEvoGlobalCache public readonly CompoundConversionEfficiencyPressure TemperatureConversionEfficiencyPressure; public readonly EnvironmentalCompoundPressure TemperatureCompoundPressure; + public readonly CompoundConversionEfficiencyPressure RadiationConversionEfficiencyPressure; + public readonly ChunkCompoundPressure RadioactiveChunkPressure; + public readonly PredatorRoot PredatorRoot; public readonly bool HasTemperature; @@ -65,6 +68,11 @@ public AutoEvoGlobalCache(WorldGenerationSettings worldSettings) new CompoundConversionEfficiencyPressure(Compound.Sunlight, Compound.Glucose, 1.0f); SunlightCompoundPressure = new EnvironmentalCompoundPressure(Compound.Sunlight, Compound.Glucose, 20000, 1.0f); + RadiationConversionEfficiencyPressure = + new CompoundConversionEfficiencyPressure(Compound.Radiation, Compound.ATP, 1.0f); + RadioactiveChunkPressure = new ChunkCompoundPressure("radioactiveChunk", + new LocalizedString("RADIOACTIVE_CHUNK"), Compound.Radiation, Compound.ATP, 1.0f); + TemperatureConversionEfficiencyPressure = new CompoundConversionEfficiencyPressure(Compound.Temperature, Compound.ATP, 1.0f); TemperatureCompoundPressure = new EnvironmentalCompoundPressure(Compound.Temperature, Compound.ATP, 100, 1.0f); diff --git a/src/auto-evo/steps/GenerateMiche.cs b/src/auto-evo/steps/GenerateMiche.cs index 8ca85772e99..3524cc5c072 100644 --- a/src/auto-evo/steps/GenerateMiche.cs +++ b/src/auto-evo/steps/GenerateMiche.cs @@ -99,6 +99,19 @@ public Miche GenerateMicheTree(AutoEvoGlobalCache globalCache) generatedMiche.AddChild(hydrogenSulfideMiche); } + var hasRadioactiveChunk = + patch.Biome.Chunks.TryGetValue("radioactiveChunk", out var radioactiveChunk) && + radioactiveChunk.Density > 0; + + // Radioactive Chunk + if (hasRadioactiveChunk) + { + var radiationMiche = new Miche(globalCache.RadiationConversionEfficiencyPressure); + radiationMiche.AddChild(new Miche(globalCache.RadioactiveChunkPressure)); + + generatedMiche.AddChild(radiationMiche); + } + // Sunlight // TODO: should there be a dynamic energy level requirement rather than an absolute value? if (patch.Biome.TryGetCompound(Compound.Sunlight, CompoundAmountType.Biome, out var sunlightAmount) && From 2961f7cbae1ca6c28fc9fa4f3d18fd6e7ab78502 Mon Sep 17 00:00:00 2001 From: Patryk26g Date: Sat, 1 Feb 2025 12:55:01 +0100 Subject: [PATCH 2/6] Make AI omit radioactive chunks --- src/microbe_stage/systems/MicrobeAISystem.cs | 113 +++++++++++++++---- 1 file changed, 90 insertions(+), 23 deletions(-) diff --git a/src/microbe_stage/systems/MicrobeAISystem.cs b/src/microbe_stage/systems/MicrobeAISystem.cs index 5c7f6a6d9c7..e3ca970133d 100644 --- a/src/microbe_stage/systems/MicrobeAISystem.cs +++ b/src/microbe_stage/systems/MicrobeAISystem.cs @@ -62,6 +62,7 @@ public sealed class MicrobeAISystem : AEntitySetSystem, ISpeciesMemberLoc // New access to the world stuff for AI to see private readonly EntitySet microbesSet; private readonly EntitySet chunksSet; + private readonly EntitySet terrainChunksSet; private readonly List speciesCachesToDrop = new(); @@ -71,6 +72,9 @@ public sealed class MicrobeAISystem : AEntitySetSystem, ISpeciesMemberLoc private readonly List<(Entity Entity, Vector3 Position, float EngulfSize, CompoundBag Compounds)> chunkDataCache = new(); + private readonly List<(Entity Entity, Vector3 Position, CompoundBag Compounds)> + terrainChunkDataCache = new(); + private readonly Dictionary speciesUsingVaryingCompounds = new(); private readonly HashSet varyingCompoundsTemporary = new(); @@ -103,9 +107,8 @@ public MicrobeAISystem(IReadonlyCompoundClouds cloudSystem, IDaylightInfo lightI microbesSet = world.GetEntities().With().With() .With().With().With().Without().AsSet(); - // Engulfables, which are basically all chunks when they aren't cells, and aren't attached so that they - // also aren't eaten already - chunksSet = world.GetEntities().With().With().With() + // Chunks that aren't cells or attached so that they also aren't eaten already + chunksSet = world.GetEntities().With().With() .Without().Without().AsSet(); } @@ -330,6 +333,17 @@ private void ChooseActions(in Entity entity, ref MicrobeAI ai, ref CompoundAbsor control.SetMucocystState(ref organelles, ref compoundStorage, entity, false); } + var radiationAmount = compounds.GetCompoundAmount(Compound.Radiation); + var radiationFraction = radiationAmount / compounds.GetCapacityForCompound(Compound.Radiation); + + if (radiationFraction > Constants.RADIATION_DAMAGE_THRESHOLD) + { + if (RunFromNearestRadioactiveChunk(ref position, ref ai, ref control)) + { + return; + } + } + // If this microbe is out of ATP, pick an amount of time to rest if (compounds.GetCompoundAmount(Compound.ATP) < 1.0f) { @@ -510,6 +524,48 @@ private void ChooseActions(in Entity entity, ref MicrobeAI ai, ref CompoundAbsor } } + private bool RunFromNearestRadioactiveChunk(ref WorldPosition position, ref MicrobeAI ai, + ref MicrobeControl control) + { + (Entity Entity, Vector3 Position, CompoundBag Compounds)? chosenChunk = null; + float bestFoundChunkDistance = float.MaxValue; + + BuildChunksCache(); + + foreach (var chunk in terrainChunkDataCache) + { + if (!chunk.Compounds.Compounds.Keys.Contains(Compound.Radiation)) + { + continue; + } + + var distance = (chunk.Position - position.Position).LengthSquared(); + + if (distance > bestFoundChunkDistance) + continue; + + if (distance > 3000.0f) + continue; + + chosenChunk = chunk; + } + + if (chosenChunk == null) + { + return false; + } + + var oppositedirection = 2 * position.Position - chosenChunk.Value.Position; + + ai.TargetPosition = chosenChunk.Value.Position * -1; + control.LookAtPoint = oppositedirection; + + control.SetMoveSpeedTowardsPoint(ref position, oppositedirection, Constants.AI_BASE_MOVEMENT); + control.Sprinting = true; + + return true; + } + private (Entity Entity, Vector3 Position, float EngulfSize, CompoundBag Compounds)? GetNearestChunkItem( in Entity entity, ref Engulfer engulfer, ref MicrobeControl control, ref WorldPosition position, CompoundBag ourCompounds, float speciesFocus, float speciesOpportunism, Random random, bool ironEater, @@ -1320,34 +1376,45 @@ private void BuildChunksCache() // To allow multithreaded AI access safely lock (chunkDataCache) { - if (chunkCacheBuilt) - return; - - foreach (ref readonly var chunk in chunksSet.GetEntities()) + lock (terrainChunkDataCache) { - if (chunk.Has()) + if (chunkCacheBuilt) + return; + + foreach (ref readonly var chunk in chunksSet.GetEntities()) { - // Ignore already despawning chunks - ref var timed = ref chunk.Get(); + if (chunk.Has()) + { + // Ignore already despawning chunks + ref var timed = ref chunk.Get(); - if (timed.TimeToLiveRemaining <= 0) - continue; - } + if (timed.TimeToLiveRemaining <= 0) + continue; + } - // Ignore chunks that wouldn't yield any useful compounds when absorbing - ref var compounds = ref chunk.Get(); + // Ignore chunks that wouldn't yield any useful compounds when absorbing + ref var compounds = ref chunk.Get(); - if (!compounds.Compounds.HasAnyCompounds()) - continue; + if (!compounds.Compounds.HasAnyCompounds()) + continue; - // TODO: determine if it is a good idea to resolve this data here immediately - ref var position = ref chunk.Get(); - ref var engulfable = ref chunk.Get(); + // TODO: determine if it is a good idea to resolve this data here immediately + ref var position = ref chunk.Get(); - chunkDataCache.Add((chunk, position.Position, engulfable.AdjustedEngulfSize, compounds.Compounds)); - } + if (chunk.Has()) + { + ref var engulfable = ref chunk.Get(); + chunkDataCache.Add((chunk, position.Position, engulfable.AdjustedEngulfSize, + compounds.Compounds)); + } + else + { + terrainChunkDataCache.Add((chunk, position.Position, compounds.Compounds)); + } + } - chunkCacheBuilt = true; + chunkCacheBuilt = true; + } } } From 4de9fd320acead32e9124e11500407bc8f6c2d93 Mon Sep 17 00:00:00 2001 From: Patryk26g Date: Sat, 1 Feb 2025 13:00:53 +0100 Subject: [PATCH 3/6] Fix --- src/microbe_stage/systems/MicrobeAISystem.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/microbe_stage/systems/MicrobeAISystem.cs b/src/microbe_stage/systems/MicrobeAISystem.cs index e3ca970133d..e473828d26b 100644 --- a/src/microbe_stage/systems/MicrobeAISystem.cs +++ b/src/microbe_stage/systems/MicrobeAISystem.cs @@ -62,7 +62,6 @@ public sealed class MicrobeAISystem : AEntitySetSystem, ISpeciesMemberLoc // New access to the world stuff for AI to see private readonly EntitySet microbesSet; private readonly EntitySet chunksSet; - private readonly EntitySet terrainChunksSet; private readonly List speciesCachesToDrop = new(); From 5e57a73c61a75047ddb3c89823091704efb045f4 Mon Sep 17 00:00:00 2001 From: Patryk26g Date: Sat, 1 Feb 2025 13:25:14 +0100 Subject: [PATCH 4/6] Balancing --- src/microbe_stage/systems/MicrobeAISystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/microbe_stage/systems/MicrobeAISystem.cs b/src/microbe_stage/systems/MicrobeAISystem.cs index e473828d26b..1ac776a2d10 100644 --- a/src/microbe_stage/systems/MicrobeAISystem.cs +++ b/src/microbe_stage/systems/MicrobeAISystem.cs @@ -335,7 +335,7 @@ private void ChooseActions(in Entity entity, ref MicrobeAI ai, ref CompoundAbsor var radiationAmount = compounds.GetCompoundAmount(Compound.Radiation); var radiationFraction = radiationAmount / compounds.GetCapacityForCompound(Compound.Radiation); - if (radiationFraction > Constants.RADIATION_DAMAGE_THRESHOLD) + if (radiationFraction > Constants.RADIATION_DAMAGE_THRESHOLD * 0.7f) { if (RunFromNearestRadioactiveChunk(ref position, ref ai, ref control)) { From f9b708bba7fb21edeb595b7a1df06c88f0d6b9d7 Mon Sep 17 00:00:00 2001 From: Patryk26g Date: Sat, 1 Feb 2025 20:37:40 +0100 Subject: [PATCH 5/6] Teach AI to use melanosomes --- src/microbe_stage/systems/MicrobeAISystem.cs | 57 +++++++++++++++++--- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/src/microbe_stage/systems/MicrobeAISystem.cs b/src/microbe_stage/systems/MicrobeAISystem.cs index 1ac776a2d10..b8168cdcb62 100644 --- a/src/microbe_stage/systems/MicrobeAISystem.cs +++ b/src/microbe_stage/systems/MicrobeAISystem.cs @@ -510,6 +510,16 @@ private void ChooseActions(in Entity entity, ref MicrobeAI ai, ref CompoundAbsor // There is no reason to be engulfing at this stage control.SetStateColonyAware(entity, MicrobeState.Normal); + // If the microbe has radiation protection it means it has melanosomes and can stay near tha radioactive chunks + // to produce ATP + if (organelles.RadiationProtection > 0) + { + if (GoNearRadioactiveChunk(ref position, ref ai, ref control, speciesFocus)) + { + return; + } + } + // Otherwise just wander around and look for compounds if (!isSessile) { @@ -523,8 +533,7 @@ private void ChooseActions(in Entity entity, ref MicrobeAI ai, ref CompoundAbsor } } - private bool RunFromNearestRadioactiveChunk(ref WorldPosition position, ref MicrobeAI ai, - ref MicrobeControl control) + private (Entity Entity, Vector3 Position, CompoundBag Compounds)? GetNearestRadioactiveChunk(ref WorldPosition position, float maxDistance) { (Entity Entity, Vector3 Position, CompoundBag Compounds)? chosenChunk = null; float bestFoundChunkDistance = float.MaxValue; @@ -543,28 +552,62 @@ private bool RunFromNearestRadioactiveChunk(ref WorldPosition position, ref Micr if (distance > bestFoundChunkDistance) continue; - if (distance > 3000.0f) + if (distance > maxDistance) continue; chosenChunk = chunk; } + return chosenChunk; + } + + private bool RunFromNearestRadioactiveChunk(ref WorldPosition position, ref MicrobeAI ai, + ref MicrobeControl control) + { + var chosenChunk = GetNearestRadioactiveChunk(ref position, 500.0f); + if (chosenChunk == null) { return false; } - var oppositedirection = 2 * position.Position - chosenChunk.Value.Position; + var oppositeDirection = position.Position + (position.Position - chosenChunk.Value.Position); - ai.TargetPosition = chosenChunk.Value.Position * -1; - control.LookAtPoint = oppositedirection; + ai.TargetPosition = oppositeDirection; + control.LookAtPoint = ai.TargetPosition; - control.SetMoveSpeedTowardsPoint(ref position, oppositedirection, Constants.AI_BASE_MOVEMENT); + control.SetMoveSpeedTowardsPoint(ref position, ai.TargetPosition, Constants.AI_BASE_MOVEMENT); control.Sprinting = true; return true; } + private bool GoNearRadioactiveChunk(ref WorldPosition position, ref MicrobeAI ai, + ref MicrobeControl control, float speciesFocus) + { + var maxDistance = 30000.0f * speciesFocus / Constants.MAX_SPECIES_FOCUS + 3000.0f; + var chosenChunk = GetNearestRadioactiveChunk(ref position, maxDistance); + + if (chosenChunk == null) + { + return false; + } + + // If the microbe is close to the chunk it doesn't need to go any closer + if (position.Position.DistanceSquaredTo(chosenChunk.Value.Position) < 700.0f) + { + control.SetMoveSpeed(0.0f); + return true; + } + + ai.TargetPosition = chosenChunk.Value.Position; + control.LookAtPoint = ai.TargetPosition; + + control.SetMoveSpeedTowardsPoint(ref position, ai.TargetPosition, Constants.AI_BASE_MOVEMENT); + + return true; + } + private (Entity Entity, Vector3 Position, float EngulfSize, CompoundBag Compounds)? GetNearestChunkItem( in Entity entity, ref Engulfer engulfer, ref MicrobeControl control, ref WorldPosition position, CompoundBag ourCompounds, float speciesFocus, float speciesOpportunism, Random random, bool ironEater, From a7d27720ed1e1e69c41ad74c350e462106bbb803 Mon Sep 17 00:00:00 2001 From: Patryk26g Date: Sat, 1 Feb 2025 20:37:59 +0100 Subject: [PATCH 6/6] Fix --- src/microbe_stage/systems/MicrobeAISystem.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/microbe_stage/systems/MicrobeAISystem.cs b/src/microbe_stage/systems/MicrobeAISystem.cs index b8168cdcb62..34e499700dd 100644 --- a/src/microbe_stage/systems/MicrobeAISystem.cs +++ b/src/microbe_stage/systems/MicrobeAISystem.cs @@ -533,7 +533,8 @@ private void ChooseActions(in Entity entity, ref MicrobeAI ai, ref CompoundAbsor } } - private (Entity Entity, Vector3 Position, CompoundBag Compounds)? GetNearestRadioactiveChunk(ref WorldPosition position, float maxDistance) + private (Entity Entity, Vector3 Position, CompoundBag Compounds)? GetNearestRadioactiveChunk( + ref WorldPosition position, float maxDistance) { (Entity Entity, Vector3 Position, CompoundBag Compounds)? chosenChunk = null; float bestFoundChunkDistance = float.MaxValue;