Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Let AI engulf even if running out of atp #5729

Merged
95 changes: 71 additions & 24 deletions src/microbe_stage/systems/MicrobeAISystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -330,17 +330,27 @@ private void ChooseActions(in Entity entity, ref MicrobeAI ai, ref CompoundAbsor
control.SetMucocystState(ref organelles, ref compoundStorage, entity, false);
}

float atpLevel = compounds.GetCompoundAmount(Compound.ATP);

// If this microbe is out of ATP, pick an amount of time to rest
if (compounds.GetCompoundAmount(Compound.ATP) < 1.0f)
if (atpLevel < 1.0f)
{
// Keep the maximum at 95% full, as there is flickering when near full
ai.ATPThreshold = 0.95f * speciesFocus / Constants.MAX_SPECIES_FOCUS;
}

// Even if we are out of ATP and there is microbe nearby, engulf them.
// make sure engulfing doesn't kill the cell. The cell won't engulf if it would kill it
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this comment line is pretty unclear and either should be removed or reworded.

if (CheckForHuntingConditions(ref ai, ref position, ref organelles, ref ourSpecies, ref engulfer,
ref cellProperties, ref control, ref health, ref compoundStorage, entity, speciesFocus,
speciesAggression, speciesActivity, speciesOpportunism, strain, random, true))
{
return;
Patryk26g marked this conversation as resolved.
Show resolved Hide resolved
}

if (ai.ATPThreshold > MathUtils.EPSILON)
{
if (compounds.GetCompoundAmount(Compound.ATP) <
compounds.GetCapacityForCompound(Compound.ATP) * ai.ATPThreshold)
if (atpLevel < compounds.GetCapacityForCompound(Compound.ATP) * ai.ATPThreshold)
{
bool outOfSomething = false;
foreach (var compound in compounds.Compounds)
Expand Down Expand Up @@ -467,6 +477,39 @@ private void ChooseActions(in Entity entity, ref MicrobeAI ai, ref CompoundAbsor
}
}

// Check if species can hunt any prey and if so - engage in chase
if (CheckForHuntingConditions(ref ai, ref position, ref organelles, ref ourSpecies, ref engulfer,
ref cellProperties, ref control, ref health, ref compoundStorage, entity, speciesFocus,
speciesAggression,
speciesActivity, speciesOpportunism, strain, random, false))
{
return;
}

// There is no reason to be engulfing at this stage
control.SetStateColonyAware(entity, MicrobeState.Normal);

// Otherwise just wander around and look for compounds
if (!isSessile)
{
SeekCompounds(in entity, ref ai, ref position, ref control, ref organelles, ref absorber, compounds,
speciesActivity, speciesFocus, random);
}
else
{
// This organism is sessile, and will not act until the environment changes
control.SetMoveSpeed(0.0f);
}
}

private bool CheckForHuntingConditions(ref MicrobeAI ai, ref WorldPosition position,
ref OrganelleContainer organelles, ref SpeciesMember ourSpecies,
ref Engulfer engulfer, ref CellProperties cellProperties, ref MicrobeControl control, ref Health health,
ref CompoundStorage compoundStorage, in Entity entity, float speciesFocus, float speciesAggression,
float speciesActivity, float speciesOpportunism, float strain, Random random, bool outOfAtp)
{
var compounds = compoundStorage.Compounds;

// If there are no chunks, look for living prey to hunt
var possiblePrey = GetNearestPreyItem(ref ai, ref position, ref organelles, ref ourSpecies, ref engulfer,
compounds, speciesFocus, speciesAggression, speciesOpportunism, random);
Expand All @@ -482,32 +525,25 @@ private void ChooseActions(in Entity entity, ref MicrobeAI ai, ref CompoundAbsor
{
GD.PrintErr("Microbe AI tried to engage prey with no position: " + e);
ai.FocusedPrey = default;
return;
return false;
}

bool engulfPrey = cellProperties.CanEngulfObject(ref ourSpecies, ref engulfer, possiblePrey) ==
EngulfCheckResult.Ok && position.Position.DistanceSquaredTo(prey) <
10.0f * engulfer.EngulfingSize;

EngagePrey(ref ai, ref control, ref organelles, ref position, compounds, entity, prey, engulfPrey,
speciesAggression, speciesFocus, speciesActivity, strain, random);
return;
}

// There is no reason to be engulfing at this stage
control.SetStateColonyAware(entity, MicrobeState.Normal);
// If out of ATP and the prey is out of reach to engulf, do nothing
if (outOfAtp && !engulfPrey)
{
return false;
}

// Otherwise just wander around and look for compounds
if (!isSessile)
{
SeekCompounds(in entity, ref ai, ref position, ref control, ref organelles, ref absorber, compounds,
speciesActivity, speciesFocus, random);
}
else
{
// This organism is sessile, and will not act until the environment changes
control.SetMoveSpeed(0.0f);
EngagePrey(ref ai, ref control, ref organelles, ref position, ref compoundStorage, ref health, entity,
prey, engulfPrey, speciesAggression, speciesFocus, speciesActivity, strain, random);
return true;
}

return false;
}

private (Entity Entity, Vector3 Position, float EngulfSize, CompoundBag Compounds)? GetNearestChunkItem(
Expand Down Expand Up @@ -858,10 +894,21 @@ private void FleeFromPredators(ref WorldPosition position, ref MicrobeAI ai, ref
}

private void EngagePrey(ref MicrobeAI ai, ref MicrobeControl control, ref OrganelleContainer organelles,
ref WorldPosition position, CompoundBag ourCompounds, in Entity entity, Vector3 target, bool engulf,
float speciesAggression, float speciesFocus, float speciesActivity, float strain, Random random)
ref WorldPosition position, ref CompoundStorage compoundStorage, ref Health health, in Entity entity,
Vector3 target, bool engulf, float speciesAggression, float speciesFocus, float speciesActivity,
float strain, Random random)
{
control.SetStateColonyAware(entity, engulf ? MicrobeState.Engulf : MicrobeState.Normal);
var ourCompounds = compoundStorage.Compounds;

if (engulf)
{
control.EnterEngulfModeForcedState(ref health, ref compoundStorage, entity, Compound.ATP);
hhyyrylainen marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
control.SetStateColonyAware(entity, MicrobeState.Normal);
}

ai.TargetPosition = target;
control.LookAtPoint = ai.TargetPosition;
if (CanShootToxin(ourCompounds, speciesFocus))
Expand Down