Skip to content

Commit

Permalink
started properly on getting ai to actually use the opportunisticness …
Browse files Browse the repository at this point in the history
…behavior.

Ai now use sits opportrunism behavipr value to determine when to eat chunks and they eat chunks quite effectively.

AI is now more heavily weighted towards the scavenging state

slight tweak

ai now sets boredom to 0 when they switch to scavenging so they stay in the  scavenging state for longer
  • Loading branch information
Untrustedlife authored and hhyyrylainen committed Mar 15, 2019
1 parent e128f3c commit 3ca27fa
Show file tree
Hide file tree
Showing 2 changed files with 162 additions and 5 deletions.
1 change: 1 addition & 0 deletions scripts/microbe_stage/configs.as
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ const bool SMALL_IRON_DISSOLVES = true;
//Auto Evo Values
const int CREATURE_DEATH_POPULATION_LOSS = -60;
const int CREATURE_KILL_POPULATION_GAIN = 50;
const int CREATURE_SCAVENGE_POPULATION_GAIN = 10;
const int CREATURE_REPRODUCE_POPULATION_GAIN = 50;
const int CREATURE_ESCAPE_POPULATION_GAIN = 50;

Expand Down
166 changes: 161 additions & 5 deletions scripts/microbe_stage/microbe_ai.as
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ const int GLUCOSE_SEARCH_THRESHHOLD = 5;
GATHERING_STATE,
FLEEING_STATE,
PREDATING_STATE,
PLANTLIKE_STATE
PLANTLIKE_STATE,
SCAVENGING_STATE
}

class MicrobeAIControllerComponent : ScriptComponent{
Expand Down Expand Up @@ -48,11 +49,12 @@ class MicrobeAIControllerComponent : ScriptComponent{
float previousAngle = 0.0f;
float compoundDifference=0;
ObjectID prey = NULL_OBJECT;
ObjectID targetChunk = NULL_OBJECT;
bool preyPegged=false;
// Prey and predator lists
array<ObjectID> predatoryMicrobes;
array<ObjectID> preyMicrobes;

array<ObjectID> chunkList;

LIFESTATE lifeState = NEUTRAL_STATE;

Expand Down Expand Up @@ -103,7 +105,7 @@ class MicrobeAISystem : ScriptSystem{
// This list is quite expensive to build each frame but
// there's currently no good way to cache this
array<ObjectID>@ allMicrobes = world.GetScriptComponentHolder("MicrobeComponent").GetIndex();
//array<ObjectID>@ allChunks = world.GetScriptComponentHolder("EngulfableComponent").GetIndex();
array<ObjectID>@ allChunks = world.GetComponentIndex_EngulfableComponent();

for(uint i = 0; i < CachedComponents.length(); ++i){

Expand Down Expand Up @@ -148,6 +150,7 @@ class MicrobeAISystem : ScriptSystem{
// Clear the lists
aiComponent.predatoryMicrobes.removeRange(0,aiComponent.predatoryMicrobes.length());
aiComponent.preyMicrobes.removeRange(0,aiComponent.preyMicrobes.length());
aiComponent.chunkList.removeRange(0,aiComponent.chunkList.length());
ObjectID prey = NULL_OBJECT;
// Peg your prey
if (!aiComponent.preyPegged){
Expand All @@ -158,8 +161,12 @@ class MicrobeAISystem : ScriptSystem{
aiComponent.preyPegged=true;
}
}
ObjectID predator = getNearestPredatorItem(components,allMicrobes);


aiComponent.targetChunk=NULL_OBJECT;
aiComponent.targetChunk = getNearestChunkItem(components,allChunks);

ObjectID predator = getNearestPredatorItem(components,allMicrobes);
//30 seconds about
if (aiComponent.boredom == GetEngine().GetRandom().GetNumber(aiComponent.speciesFocus*2,1000.0f+aiComponent.speciesFocus*2)){
// Occassionally you need to reevaluate things
Expand Down Expand Up @@ -195,7 +202,13 @@ class MicrobeAISystem : ScriptSystem{
case GATHERING_STATE:
{
//In this state you gather compounds
if (rollCheck(aiComponent.speciesOpportunism,400.0f)){
aiComponent.lifeState= SCAVENGING_STATE;
aiComponent.boredom = 0;
}
else {
doRunAndTumble(components);
}
break;
}
case FLEEING_STATE:
Expand Down Expand Up @@ -234,6 +247,23 @@ class MicrobeAISystem : ScriptSystem{
}
break;
}
case SCAVENGING_STATE:
{
if (aiComponent.targetChunk != NULL_OBJECT){
dealWithChunks(components, aiComponent.targetChunk, allChunks);
}
else{
if (!rollCheck(aiComponent.speciesOpportunism, 400)){
//LOG_INFO("gather only");
aiComponent.lifeState = NEUTRAL_STATE;
aiComponent.boredom=0;
}
else{
aiComponent.lifeState = NEUTRAL_STATE;
}
}
break;
}
}

/* Check if we are willing to run, and there is a predator nearby, if so, flee for your life
Expand Down Expand Up @@ -263,6 +293,53 @@ class MicrobeAISystem : ScriptSystem{
aiComponent.previousStoredCompounds = microbeComponent.stored;
}
}
// deal with chunks
ObjectID getNearestChunkItem(MicrobeAISystemCached@ components, array<ObjectID>@ allChunks){
ObjectID microbeEntity = components.entity;
MicrobeAIControllerComponent@ aiComponent = components.first;
MicrobeComponent@ microbeComponent = components.second;
Position@ position = components.third;
ObjectID chosenChunk = NULL_OBJECT;


// Retrieve nearest potential chunk
for (uint i = 0; i < allChunks.length(); i++){
// Get the microbe component
auto compoundBag = world.GetComponent_CompoundBagComponent(allChunks[i]);
// Get the microbe component
auto engulfableComponent = world.GetComponent_EngulfableComponent(allChunks[i]);

if ((aiComponent.speciesOpportunism==MAX_SPECIES_OPPORTUNISM) or
((((microbeComponent.totalHexCountCache)*1.0f)*(aiComponent.speciesOpportunism/OPPORTUNISM_DIVISOR)) >
(engulfableComponent.getSize()*1.0f))){
//You are non-threatening to me
aiComponent.chunkList.insertLast(allChunks[i]);
}
}
// Get the nearest one if it exists
if (aiComponent.chunkList.length() > 0 )
{
//LOG_INFO(""+aiComponent.chunkList.length());
if (world.GetComponent_Position(aiComponent.chunkList[0]) !is null)
{
Float3 testPosition = world.GetComponent_Position(aiComponent.chunkList[0])._Position;
chosenChunk = aiComponent.chunkList[0];
for (uint c = 0; c < aiComponent.chunkList.length(); c++){
// Get position
Position@ thisPosition = world.GetComponent_Position(aiComponent.chunkList[c]);
if (thisPosition !is null){
if ((testPosition - position._Position).LengthSquared() > (thisPosition._Position - position._Position).LengthSquared()){
testPosition = thisPosition._Position;
chosenChunk = aiComponent.chunkList[c];
}
}
}
}

}

return chosenChunk;
}

// Building the prey list and returning the best option
ObjectID getNearestPreyItem(MicrobeAISystemCached@ components, array<ObjectID>@ allMicrobes){
Expand Down Expand Up @@ -431,6 +508,11 @@ class MicrobeAISystem : ScriptSystem{
if (!microbeComponent.isPlayerMicrobe && microbeComponent.speciesName != playerSpecies.name){
MicrobeOperations::alterSpeciesPopulation(world,microbeEntity,CREATURE_KILL_POPULATION_GAIN);
}

if (rollCheck(aiComponent.speciesOpportunism,400.0f)){
aiComponent.lifeState= SCAVENGING_STATE;
}

}
else
{
Expand Down Expand Up @@ -467,6 +549,71 @@ class MicrobeAISystem : ScriptSystem{
}
}

// For chasing down and eating chunka in various ways
void dealWithChunks(MicrobeAISystemCached@ components, ObjectID chunk, array<ObjectID>@ allChunks )
{
//LOG_INFO("chasing"+prey);
// Set Components
ObjectID microbeEntity = components.entity;
MicrobeAIControllerComponent@ aiComponent = components.first;
MicrobeComponent@ microbeComponent = components.second;
Position@ position = components.third;
// Tick the engulf tick
aiComponent.ticksSinceLastToggle+=1;
// Required For AI
CompoundId ironId = SimulationParameters::compoundRegistry().getTypeId("iron");
CompoundId atpID = SimulationParameters::compoundRegistry().getTypeId("atp");
//LOG_INFO("predating");
auto compoundBag = world.GetComponent_CompoundBagComponent(chunk);
// Get the engulfablecomponent
auto engulfableComponent = world.GetComponent_EngulfableComponent(chunk);
if (engulfableComponent is null){
aiComponent.targetChunk = NULL_OBJECT;
//(maybe immediately target a new one)
return;
}

aiComponent.targetPosition = world.GetComponent_Position(chunk)._Position;
auto vec = (aiComponent.targetPosition - position._Position);
aiComponent.direction = vec.Normalize();
microbeComponent.facingTargetPoint = aiComponent.targetPosition;
aiComponent.hasTargetPosition = true;

//Always set target Position, for use later in AI
microbeComponent.movementDirection = Float3(0, 0, -AI_BASE_MOVEMENT);

// Turn off engulf if chunk is gone
if (engulfableComponent is null){
aiComponent.hasTargetPosition = false;
aiComponent.targetChunk=getNearestChunkItem(components,allChunks);
if (microbeComponent.engulfMode){
MicrobeOperations::toggleEngulfMode(world, microbeEntity);
}
// You got a consumption, good job
auto playerSpecies = MicrobeOperations::getSpeciesComponent(world, "Default");
if (!microbeComponent.isPlayerMicrobe && microbeComponent.speciesName != playerSpecies.name){
MicrobeOperations::alterSpeciesPopulation(world,microbeEntity,CREATURE_SCAVENGE_POPULATION_GAIN);
}
}
else
{
// Turn on engulfmode if close
if (((position._Position - aiComponent.targetPosition).LengthSquared() <= 300+(microbeComponent.totalHexCountCache*3.0f))
&& (MicrobeOperations::getCompoundAmount(world,microbeEntity,atpID) >= 1.0f)
&& !microbeComponent.engulfMode &&
(float(microbeComponent.totalHexCountCache) > (
ENGULF_HP_RATIO_REQ*engulfableComponent.getSize()))){
MicrobeOperations::toggleEngulfMode(world, microbeEntity);
aiComponent.ticksSinceLastToggle=0;
}
else if (((position._Position - aiComponent.targetPosition).LengthSquared() >= 500+(microbeComponent.totalHexCountCache*3.0f))
&& (microbeComponent.engulfMode && aiComponent.ticksSinceLastToggle >= AI_ENGULF_INTERVAL)){
MicrobeOperations::toggleEngulfMode(world, microbeEntity);
aiComponent.ticksSinceLastToggle=0;
}
}
}

// For self defense (not necessarily fleeing)
void dealWithPredators(MicrobeAISystemCached@ components, ObjectID predator)
{
Expand Down Expand Up @@ -534,7 +681,12 @@ class MicrobeAISystem : ScriptSystem{
//LOG_INFO("evaluating");
MicrobeAIControllerComponent@ aiComponent = components.first;
Position@ position = components.third;
if (rollCheck(aiComponent.speciesActivity,500.0f))
if (rollCheck(aiComponent.speciesOpportunism,500.0f))
{
aiComponent.lifeState = SCAVENGING_STATE;
aiComponent.boredom = 0;
}
else if (rollCheck(aiComponent.speciesActivity,500.0f))
{
aiComponent.lifeState = PLANTLIKE_STATE;
aiComponent.boredom = 0;
Expand Down Expand Up @@ -575,6 +727,10 @@ class MicrobeAISystem : ScriptSystem{
aiComponent.lifeState = GATHERING_STATE;
}
}
else if (aiComponent.targetChunk != NULL_OBJECT){
//LOG_INFO("prey only");
aiComponent.lifeState = SCAVENGING_STATE;
}
// Every 2 intervals or so
else if (GetEngine().GetRandom().GetNumber(0,10) < 8){
//LOG_INFO("gather only");
Expand Down

0 comments on commit 3ca27fa

Please sign in to comment.