From 3ca27facd10ece5d2c3c5817eeaf718677e17eff Mon Sep 17 00:00:00 2001 From: Untrustedlife Date: Sun, 3 Mar 2019 17:25:41 -0600 Subject: [PATCH] started properly on getting ai to actually use the opportunisticness 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 --- scripts/microbe_stage/configs.as | 1 + scripts/microbe_stage/microbe_ai.as | 166 +++++++++++++++++++++++++++- 2 files changed, 162 insertions(+), 5 deletions(-) diff --git a/scripts/microbe_stage/configs.as b/scripts/microbe_stage/configs.as index fc6718a4ff5..bcfef8206ce 100644 --- a/scripts/microbe_stage/configs.as +++ b/scripts/microbe_stage/configs.as @@ -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; diff --git a/scripts/microbe_stage/microbe_ai.as b/scripts/microbe_stage/microbe_ai.as index edfae9d79aa..4f40b33825c 100644 --- a/scripts/microbe_stage/microbe_ai.as +++ b/scripts/microbe_stage/microbe_ai.as @@ -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{ @@ -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 predatoryMicrobes; array preyMicrobes; - + array chunkList; LIFESTATE lifeState = NEUTRAL_STATE; @@ -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@ allMicrobes = world.GetScriptComponentHolder("MicrobeComponent").GetIndex(); - //array@ allChunks = world.GetScriptComponentHolder("EngulfableComponent").GetIndex(); + array@ allChunks = world.GetComponentIndex_EngulfableComponent(); for(uint i = 0; i < CachedComponents.length(); ++i){ @@ -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){ @@ -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 @@ -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: @@ -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 @@ -263,6 +293,53 @@ class MicrobeAISystem : ScriptSystem{ aiComponent.previousStoredCompounds = microbeComponent.stored; } } + // deal with chunks + ObjectID getNearestChunkItem(MicrobeAISystemCached@ components, array@ 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@ allMicrobes){ @@ -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 { @@ -467,6 +549,71 @@ class MicrobeAISystem : ScriptSystem{ } } + // For chasing down and eating chunka in various ways + void dealWithChunks(MicrobeAISystemCached@ components, ObjectID chunk, array@ 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) { @@ -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; @@ -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");