diff --git a/scripts/gui/microbe_hud.mjs b/scripts/gui/microbe_hud.mjs
index 4cdf037fbbb..a1924640dfa 100644
--- a/scripts/gui/microbe_hud.mjs
+++ b/scripts/gui/microbe_hud.mjs
@@ -444,7 +444,7 @@ function checkExtinction(population){
}
function checkGeneration (generation, population){
- if(generation >= 20 && population >= 500 && wonOnce == false){
+ if(generation >= 20 && population >= 400 && wonOnce == false){
document.getElementById("winTitle").style.display = "inline-block";
document.getElementById("winBody").style.display = "inline-block";
document.getElementById("winContainer").style.display = "inline-block";
diff --git a/scripts/gui/thrive_gui.html b/scripts/gui/thrive_gui.html
index 020882f8215..9bde8728e47 100644
--- a/scripts/gui/thrive_gui.html
+++ b/scripts/gui/thrive_gui.html
@@ -326,7 +326,7 @@
For this Release if your population (top tab) drops to zero you go extinct.
-But if you survive for twenty generations with 500 population, you are considered to have won, after winning you get a popup and can continue playing as you wish.
+But if you survive for twenty generations with 400 population, you are considered to have won, after winning you get a popup and can continue playing as you wish.
Be wary because your competitors are evolving alongside you. Every time you enter the editor they evolve as well.
diff --git a/scripts/microbe_stage/configs.as b/scripts/microbe_stage/configs.as
index 83e592cf76c..3930895c47a 100644
--- a/scripts/microbe_stage/configs.as
+++ b/scripts/microbe_stage/configs.as
@@ -40,9 +40,14 @@ const auto MAX_OPACITY_MUTATION = 0.01f;
// Mutation Variables
const auto MUTATION_BACTERIA_TO_EUKARYOTE = 1;
-const auto MUTATION_CREATION_RATE = 0.1f;
+const auto MUTATION_CREATION_RATE = 0.5f;
+const auto MUTATION_EXTRA_CREATION_RATE = 0.1f;
const auto MUTATION_DELETION_RATE = 0.1f;
-const auto MUTATION_REPLACEMENT_RATE = 0.1f;
+const auto MUTATION_REPLACEMENT_RATE = 0.3f;
+
+// Genus splitting and name mutation
+const auto MUTATION_CHANGE_GENUS = 33;
+const auto MUTATION_WORD_EDIT = 75;
//Removal cost
const auto ORGANELLE_REMOVE_COST = 10;
diff --git a/scripts/microbe_stage/microbe.as b/scripts/microbe_stage/microbe.as
index e51500de5b5..83c0cbf9687 100644
--- a/scripts/microbe_stage/microbe.as
+++ b/scripts/microbe_stage/microbe.as
@@ -465,11 +465,16 @@ class MicrobeSystem : ScriptSystem{
if (microbeComponent.hostileEngulfer != NULL_OBJECT){
auto predatorPosition = world.GetComponent_Position(microbeComponent.hostileEngulfer);
auto ourPosition = world.GetComponent_Position(microbeEntity);
+ auto predatorMembraneComponent = world.GetComponent_MembraneComponent(microbeComponent.hostileEngulfer);
+ auto circleRad = predatorMembraneComponent.calculateEncompassingCircleRadius();
MicrobeComponent@ hostileMicrobeComponent = cast(
world.GetScriptComponentHolder("MicrobeComponent").Find(microbeComponent.hostileEngulfer));
+ if (hostileMicrobeComponent.isBacteria){
+ circleRad = circleRad/2;
+ }
if ((hostileMicrobeComponent is null) || (!hostileMicrobeComponent.engulfMode) ||
(hostileMicrobeComponent.dead) || (ourPosition._Position - predatorPosition._Position).LengthSquared() >=
- ((hostileMicrobeComponent.totalHexCountCache+3)*HEX_SIZE)+50){
+ circleRad){
microbeComponent.hostileEngulfer = NULL_OBJECT;
microbeComponent.isBeingEngulfed = false;
}
@@ -802,7 +807,7 @@ class MicrobeSystem : ScriptSystem{
if(organellesToAdd.length() > 0){
// Redo the cell membrane.
membraneComponent.clear();
- MicrobeOperations::rebuildProcessList(world, microbeEntity);
+ MicrobeOperations::rebuildProcessList(world, microbeEntity);
}
if(reproductionStageComplete && microbeComponent.reproductionStage < 2){
diff --git a/scripts/microbe_stage/microbe_operations.as b/scripts/microbe_stage/microbe_operations.as
index e4ef6bf3abe..9b5902f25b5 100644
--- a/scripts/microbe_stage/microbe_operations.as
+++ b/scripts/microbe_stage/microbe_operations.as
@@ -906,14 +906,6 @@ ObjectID spawnMicrobe(CellStageWorld@ world, Float3 pos, const string &in specie
if(pos.Y != 0)
LOG_WARNING("spawnMicrobe: spawning at y-coordinate: " + pos.Y);
- auto processor = getProcessorComponent(world, speciesName);
-
- if(processor is null){
- LOG_ERROR("Skipping microbe spawn because species '" + speciesName +
- "' doesn't have a processor component");
-
- return NULL_OBJECT;
- }
// Create microbeEntity with correct template, physics and species name
auto microbeEntity = _createMicrobeEntity(world, aiControlled, speciesName,
@@ -958,16 +950,6 @@ ObjectID spawnBacteria(CellStageWorld@ world, Float3 pos, const string &in speci
if(pos.Y != 0)
LOG_WARNING("spawnBacteria: spawning at y-coordinate: " + pos.Y);
- auto processor = getProcessorComponent(world, speciesName);
-
- if(processor is null){
-
- LOG_ERROR("Skipping microbe spawn because species '" + speciesName +
- "' doesn't have a processor component");
-
- return NULL_OBJECT;
- }
-
// Create microbeEntity with correct template, physics and species name
auto microbeEntity = _createMicrobeEntity(world, aiControlled, speciesName,
// in_editor
@@ -1087,17 +1069,6 @@ ObjectID _createMicrobeEntity(CellStageWorld@ world, bool aiControlled,
return entity;
}
- auto processor = world.GetComponent_ProcessorComponent(speciesEntity);
-
- if(processor is null){
- LOG_ERROR("Microbe species '" + microbeComponent.speciesName +
- "' doesn't have a processor component");
- } else {
- // Each microbe now has their own processor component to allow
- // the process system to run safely while species are deleted
- Species::copyProcessesFromSpecies(world, species, entity);
- }
-
if(microbeComponent.organelles.length() > 0)
assert(false, "Freshly created microbe has organelles in it");
@@ -1108,6 +1079,7 @@ ObjectID _createMicrobeEntity(CellStageWorld@ world, bool aiControlled,
// up to date with the species so either this should apply the species processes OR
// there should be a ProcessConfiguration object that would be shared between the
// ProcessorComponent both in the species and individual cells
+ // this also sets up the processor component
Species::applyTemplate(world, entity, species, shape);
// ------------------------------------ //
@@ -1115,6 +1087,7 @@ ObjectID _createMicrobeEntity(CellStageWorld@ world, bool aiControlled,
assert(microbeComponent.organelles.length() > 0, "Microbe has no "
"organelles in initializeMicrobe");
+
auto rigidBody = world.Create_Physics(entity, position);
_applyMicrobeCollisionShape(world, rigidBody, microbeComponent, shape);
diff --git a/scripts/microbe_stage/procedural_microbes.as b/scripts/microbe_stage/procedural_microbes.as
index 48f8404bdf8..7a5e26bf76e 100644
--- a/scripts/microbe_stage/procedural_microbes.as
+++ b/scripts/microbe_stage/procedural_microbes.as
@@ -281,6 +281,7 @@ string mutateMicrobe(const string &in stringCode, bool isBacteria)
completeString = join(modifiedArray,"|");
+ // Can add up to 6 new organelles (Which should allow AI to catch up to player more
// We can insert new organelles at the end of the list
if(GetEngine().GetRandom().GetNumber(0.f, 1.f) < MUTATION_CREATION_RATE){
auto organelleList = positionOrganelles(completeString);
@@ -292,6 +293,25 @@ string mutateMicrobe(const string &in stringCode, bool isBacteria)
completeString+="|"+returnedGenome;
}
+ /*
+ Probability of mutation occuring 5 time(s) = 0.15 = 1.0E-5
+ Probability of mutation NOT occuring = (1 - 0.1)5 = 0.59049
+ Probability of mutation occuring = 1 - (1 - 0.1)5 = 0.40951
+ */
+ // We can insert new organelles at the end of the list
+ for(int n = 0; n < 5; n++ ){
+ // We can insert new organelles at the end of the list
+ if(GetEngine().GetRandom().GetNumber(0.f, 1.f) < MUTATION_EXTRA_CREATION_RATE){
+ auto organelleList = positionOrganelles(completeString);
+ const auto letter = getRandomLetter(isBacteria);
+ string name = string(organelleLetters[letter]);
+ string returnedGenome = translateOrganelleToGene(getRealisticPosition(name,organelleList));
+ //LOG_INFO("Adding");
+ //LOG_INFO("chromosomes:"+returnedGenome);
+ completeString+="|"+returnedGenome;
+ }
+ }
+
LOG_INFO("Mutated: "+completeString);
return completeString;
}
diff --git a/scripts/microbe_stage/setup.as b/scripts/microbe_stage/setup.as
index c70f8b58e89..d20c763fa06 100644
--- a/scripts/microbe_stage/setup.as
+++ b/scripts/microbe_stage/setup.as
@@ -233,11 +233,7 @@ void onReturnFromEditor(CellStageWorld@ world)
SpeciesComponent@ ourActualSpecies = MicrobeOperations::getSpeciesComponent(world, player);
auto membraneComponent = world.GetComponent_MembraneComponent(player);
- // Call this before creating the clone.
- Species::initProcessorComponent(world, player, ourActualSpecies);
// Can probabbly wrap this into the usual init to keep things clean
- // This makes sure that the player's processer are up to date with their species
- Species::copyProcessesFromSpecies(world, ourActualSpecies, player);
PlayerSpeciesSpawner factory("Default");
@@ -256,6 +252,7 @@ void onReturnFromEditor(CellStageWorld@ world)
world.GetScriptComponentHolder("MicrobeComponent").Find(player));
// Reset the player cell to be the same as the species template
+ // This also sets the processor component
Species::restoreOrganelleLayout(world, player, microbeComponent, playerSpecies);
// Reset Players reproduction
diff --git a/scripts/microbe_stage/species_system.as b/scripts/microbe_stage/species_system.as
index 05c6ae09368..78360f6556a 100644
--- a/scripts/microbe_stage/species_system.as
+++ b/scripts/microbe_stage/species_system.as
@@ -65,40 +65,60 @@ Float4 randomProkayroteColour(float opaqueness = randomOpacityBacteria())
}
string mutateWord(string name) {
+ //
const array vowels = {"a", "e", "i", "o", "u"};
+ const array pronoucablePermutation = {"th", "sh", "ch", "wh", "Th", "Sh", "Ch", "Wh"};
const array consonants = {"b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
- "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z"};
+ "n", "p", "q", "s", "t", "v", "w", "x", "y", "z"};
string newName = name;
- int changeLimit = 4;
+ int changeLimit = 1;
+ int letterChangeLimit = 2;
+ int letterChanges=0;
int changes=0;
- //Ignore the first letter and last letter
- for(uint i = 1; i < newName.length()-1; i++) {
- // Index we are adding or erasing chromosomes at
- uint index = newName.length() - i - 1;
-
- // Are we a vowel or are we a consonant?
- bool isVowel = vowels.find(newName.substr(index,1)) >= 0;
-
- //30 percent chance replace
- if(GetEngine().GetRandom().GetNumber(0,20) <= 6 && changes <= changeLimit) {
- newName.erase(index, 1);
- changes++;
-
- if (isVowel)
- newName.insert(index, randomChoice(vowels));
- else
- newName.insert(index, randomChoice(consonants));
+ // th, sh, ch, wh
+ for(uint i = 1; i < newName.length(); i++) {
+ if(changes <= changeLimit && i > 1){
+ // Index we are adding or erasing chromosomes at
+ uint index = newName.length() - i - 1;
+ // Are we a vowel or are we a consonant?
+ bool isPermute = pronoucablePermutation.find(newName.substr(index,2)) > 0;
+ string original = newName.substr(index, 2);
+ if (GetEngine().GetRandom().GetNumber(0,20) <= 10 && isPermute){
+ newName.erase(index, 2);
+ changes++;
+ newName.insert(index,randomChoice(pronoucablePermutation));
+ }
}
+ }
+
+ // 2% chance each letter
+ for(uint i = 1; i < newName.length(); i++) {
+ if(GetEngine().GetRandom().GetNumber(0,120) <= 1 && changes <= changeLimit){
+ // Index we are adding or erasing chromosomes at
+ uint index = newName.length() - i - 1;
+
+ // Are we a vowel or are we a consonant?
+ bool isVowel = vowels.find(newName.substr(index,1)) >= 0;
+
+ bool isPermute=false;
+ if (i > 1){
+ if (pronoucablePermutation.find(newName.substr(index-1,2)) > 0 ||
+ pronoucablePermutation.find(newName.substr(index-2,2)) > 0 ||
+ pronoucablePermutation.find(newName.substr(index,2)) > 0){
+ isPermute=true;
+ //LOG_INFO(i + ":"+newName.substr(index-1,2));
+ //LOG_INFO(i + ":"+newName.substr(index-2,2));
+ //LOG_INFO(i + ":"+newName.substr(index,2));
+ }
+ }
- //10 percent chance new syllable
- if(GetEngine().GetRandom().GetNumber(0,20) <= 2 && changes <= changeLimit){
string original = newName.substr(index, 1);
- newName.erase(index, 1);
- changes++;
- if (!isVowel){
+ if (!isVowel && newName.substr(index,1)!="r" && !isPermute){
+ newName.erase(index, 1);
+ changes++;
switch (GetEngine().GetRandom().GetNumber(0,5)) {
case 0:
newName.insert(index, randomChoice(vowels) + randomChoice(consonants));
@@ -120,9 +140,10 @@ string mutateWord(string name) {
break;
}
}
-
// If is vowel
- else {
+ else if (newName.substr(index,1)!="r" && !isPermute){
+ newName.erase(index, 1);
+ changes++;
if(GetEngine().GetRandom().GetNumber(0,20) <= 10)
newName.insert(index, randomChoice(consonants) + randomChoice(vowels) + original);
else
@@ -131,14 +152,63 @@ string mutateWord(string name) {
}
}
+ //Ignore the first letter and last letter
+ for(uint i = 1; i < newName.length(); i++) {
+ // Index we are adding or erasing chromosomes at
+ uint index = newName.length() - i - 1;
+
+ bool isPermute=false;
+ if (i > 1){
+ if (pronoucablePermutation.find(newName.substr(index-1,2)) > 0 ||
+ pronoucablePermutation.find(newName.substr(index-2,2)) > 0 ||
+ pronoucablePermutation.find(newName.substr(index,2)) > 0){
+ isPermute=true;
+ //LOG_INFO(i + ":"+newName.substr(index-1,2));
+ //LOG_INFO(i + ":"+newName.substr(index-2,2));
+ //LOG_INFO(i + ":"+newName.substr(index,2));
+ }
+ }
+
+ // Are we a vowel or are we a consonant?
+ bool isVowel = vowels.find(newName.substr(index,1)) >= 0;
+
+ //50 percent chance replace
+ if(GetEngine().GetRandom().GetNumber(0,20) <= 10 && changes <= changeLimit) {
+ if (!isVowel && newName.substr(index,1)!="r" && !isPermute){
+ newName.erase(index, 1);
+ letterChanges++;
+ newName.insert(index, randomChoice(consonants));
+ }
+ else if (!isPermute){
+ newName.erase(index, 1);
+ letterChanges++;
+ newName.insert(index, randomChoice(vowels));
+ }
+ }
+
+ }
+
// Our base case
- if(changes == 0) {
+ if(letterChanges < letterChangeLimit && changes==0 ) {
//We didnt change our word at all, try again recursviely until we do
return mutateWord(name);
}
+ // Convert to lower case
+ for(uint i = 1; i < newName.length()-1; i++) {
+ if(newName[i]>=65 && newName[i]<=92){
+ newName[i]=newName[i]+32;
+ }
+ }
+
+ // Convert first letter to upper case
+ if(newName[0]>=97 && newName[0]<=122){
+ newName[0]=newName[0]-32;
+ }
+
+
LOG_INFO("Mutating Name:"+name +" to new name:"+newName);
- return newName;
+ return newName;;
}
string generateNameSection()
@@ -272,7 +342,7 @@ class Species{
name = randomSpeciesName();
//Mutate the epithet
- if (GetEngine().GetRandom().GetNumber(0, 10) < 5){
+ if (GetEngine().GetRandom().GetNumber(0, 100) < MUTATION_WORD_EDIT){
epithet = mutateWord(parent.epithet);
}
else {
@@ -295,11 +365,11 @@ class Species{
LOG_INFO("X:"+parent.colour.X+" Y:"+parent.colour.Y+" Z:"+parent.colour.Z+" W:"+parent.colour.W);
LOG_INFO("X:"+colour.X+" Y:"+colour.Y+" Z:"+colour.Z+" W:"+colour.W);
// Chance of new color needs to be low
- if (GetEngine().GetRandom().GetNumber(0,100) <= 20)
+ if (GetEngine().GetRandom().GetNumber(0,100) <= MUTATION_CHANGE_GENUS)
{
LOG_INFO("New Genus");
// We can do more fun stuff here later
- if (GetEngine().GetRandom().GetNumber(0, 10) < 5){
+ if (GetEngine().GetRandom().GetNumber(0, 100) < MUTATION_WORD_EDIT){
genus = mutateWord(parent.genus);
}
else {
@@ -593,7 +663,7 @@ class Species{
genus = parent.genus;
colour=parent.colour;
//Mutate the epithet
- if (GetEngine().GetRandom().GetNumber(0, 10) < 5){
+ if (GetEngine().GetRandom().GetNumber(0, 100) < MUTATION_WORD_EDIT){
epithet = mutateWord(parent.epithet);
}
else {
@@ -616,13 +686,13 @@ class Species{
LOG_INFO("X:"+parent.colour.X+" Y:"+parent.colour.Y+" Z:"+parent.colour.Z+" W:"+parent.colour.W);
LOG_INFO("X:"+colour.X+" Y:"+colour.Y+" Z:"+colour.Z+" W:"+colour.W);
- if (GetEngine().GetRandom().GetNumber(0,100) <= 20)
+ if (GetEngine().GetRandom().GetNumber(0,100) <= MUTATION_CHANGE_GENUS)
{
LOG_INFO("New Genus of bacteria");
// We can do more fun stuff here later
//Mutate the genus
- if (GetEngine().GetRandom().GetNumber(0, 10) < 5){
+ if (GetEngine().GetRandom().GetNumber(0, 100) < MUTATION_WORD_EDIT){
genus = mutateWord(parent.genus);
}
else {
@@ -716,14 +786,14 @@ class Species{
const auto INITIAL_POPULATION = 3000;
// How much time does it take for the simulation to update.
-const auto SPECIES_SIM_INTERVAL = 5000;
+const auto SPECIES_SIM_INTERVAL = 2500;
// If a specie's population goes below this it goes extinct.
const auto MIN_POP_SIZE = 500;
// If a specie's population goes above this it gets split in half and a
// new mutated species apears. this should be randomized
-const auto MAX_POP_SIZE = 6000;
+const auto MAX_POP_SIZE = 3000;
// The amount of species at the start of the microbe stage (not counting Default/Player)
const auto INITIAL_SPECIES = 7;
@@ -1040,7 +1110,6 @@ void applyTemplate(CellStageWorld@ world, ObjectID microbe, SpeciesComponent@ sp
MicrobeComponent@ microbeComponent = cast(
world.GetScriptComponentHolder("MicrobeComponent").Find(microbe));
- // TODO: Make this also set the microbe's ProcessorComponent
microbeComponent.speciesName = species.name;
MicrobeOperations::setMembraneType(world, microbe, species.speciesMembraneType);
MicrobeOperations::setMembraneColour(world, microbe, species.colour);
@@ -1090,110 +1159,10 @@ void restoreOrganelleLayout(CellStageWorld@ world, ObjectID microbeEntity,
microbeComponent.isBacteria = species.isBacteria;
// Call this to reset processor component
- Species::initProcessorComponent(world, microbeEntity, species);
- // This makes sure that the microbes processer are up to date with their species
- Species::copyProcessesFromSpecies(world, species, microbeEntity);
-}
-
-void initProcessorComponent(CellStageWorld@ world, ObjectID entity,
- SpeciesComponent@ speciesComponent)
-{
- assert(world.GetComponent_SpeciesComponent(entity) !is speciesComponent,
- "Wrong speciesComponent passed to initProcessorComponent");
-
- initProcessorComponent(world,speciesComponent);
-}
-
-
-void initProcessorComponent(CellStageWorld@ world,
- SpeciesComponent@ speciesComponent)
-{
- assert(speciesComponent.organelles.length() > 0, "initProcessorComponent given a "
- "species that has no organelles");
- auto speciesEntity = findSpeciesEntityByName(world, speciesComponent.name);
-
- ProcessorComponent@ processorComponent = world.GetComponent_ProcessorComponent(
- speciesEntity);
-
- dictionary capacities;
- for(uint i = 0; i < speciesComponent.organelles.length(); i++){
-
- const Organelle@ organelleDefinition = cast(speciesComponent.organelles[i]).organelle;
- if(organelleDefinition is null){
-
- LOG_ERROR("Organelle table has a null organelle in it, position: " + i +
- "', that was added to a species entity");
- continue;
- }
-
- for(uint processNumber = 0;
- processNumber < organelleDefinition.processes.length(); ++processNumber)
- {
- // This name needs to match the one in bioProcessRegistry
- TweakedProcess@ process = organelleDefinition.processes[processNumber];
-
- if(!capacities.exists(process.process.internalName)){
- capacities[process.process.internalName] = double(0.0f);
- }
-
- // Here the second capacities[process.name] was initially capacities[process]
- // but the processes are just strings inside the Organelle class
- capacities[process.process.internalName] = double(capacities[
- process.process.internalName]) +
- process.capacity;
- }
- }
-
- uint64 processCount = SimulationParameters::bioProcessRegistry().getSize();
- for(BioProcessId bioProcessId = 0; bioProcessId < processCount; ++bioProcessId){
- auto processName = SimulationParameters::bioProcessRegistry().getInternalName(
- bioProcessId);
-
- if(capacities.exists(processName)){
- double capacity;
- if(!capacities.get(processName, capacity)){
- LOG_ERROR("capacities has invalid value");
- continue;
- }
-
- // LOG_INFO("Process: " + processName + " Capacity: " + capacity);
- processorComponent.setCapacity(bioProcessId, capacity);
- } else {
- // If it doesnt exist:
- capacities.set(processName, 0.0f);
-
- // This is related to https://github.com/Revolutionary-Games/Thrive/issues/599
- processorComponent.setCapacity(bioProcessId, 0.0f);
- }
- }
+ MicrobeOperations::rebuildProcessList(world,microbeEntity);
}
-//! This function copies process data from a species to an entity with a ProcessorComponent
-void copyProcessesFromSpecies(CellStageWorld@ world,
- SpeciesComponent@ speciesComponent, ObjectID entity)
-{
- ProcessorComponent@ cellProcessorComponent = world.GetComponent_ProcessorComponent(
- entity);
- if(cellProcessorComponent is null)
- {
- LOG_ERROR("Entity doesn't have a ProcessorComponent for process copy target");
- return;
- }
-
- auto speciesEntity = findSpeciesEntityByName(world, speciesComponent.name);
-
- ProcessorComponent@ speciesProcessor = world.GetComponent_ProcessorComponent(
- speciesEntity);
-
- if(speciesProcessor is null){
- LOG_ERROR("Species lacks processor component for copying processes from");
- return;
- }
-
- // Use assignment operator to copy all data
- cellProcessorComponent = speciesProcessor;
-}
//! Creates a species from the initial template. This doesn't register with SpeciesSystem
//! because this is (currently) only used for the player's species which isn't managed by it
@@ -1261,9 +1230,6 @@ ObjectID createSpecies(CellStageWorld@ world, const string &in name, const strin
}
}
- ProcessorComponent@ processorComponent = world.Create_ProcessorComponent(
- speciesEntity);
-
speciesComponent.colour = colour;
speciesComponent.speciesMembraneType = speciesMembraneType;
@@ -1296,8 +1262,7 @@ ObjectID createSpecies(CellStageWorld@ world, const string &in name, const strin
speciesComponent.avgCompoundAmounts[formatUInt(compound.id)] = compoundAmount;
}
- // Call init instead of going through the same code here again.
- initProcessorComponent(world,speciesComponent);
+
return speciesEntity;
}