From c0a2c442971ae1bb527a190445db880a162c9fac Mon Sep 17 00:00:00 2001 From: Untrustedlife Date: Fri, 26 Apr 2019 13:45:03 -0500 Subject: [PATCH 1/8] started working on my issues game currently cannot run got rid of proc gen species completely species can now mutate new membranes added population to c++ side species, fixed epithet game now runs again, it crashes when you ente rthe editor though because your species lacks a stringcode --- .../MicrobeStage/Species.json | 5 +- scripts/microbe_stage/configs.as | 12 +- .../microbe_editor/microbe_editor.as | 4 + scripts/microbe_stage/microbe_operations.as | 24 - scripts/microbe_stage/setup.as | 1 - scripts/microbe_stage/species_system.as | 416 ++++-------------- src/microbe_stage/species.cpp | 3 + src/microbe_stage/species.h | 1 + src/microbe_stage/species_component.h | 6 + src/scripting/script_initializer.cpp | 6 +- 10 files changed, 109 insertions(+), 369 deletions(-) diff --git a/scripts/SimulationParameters/MicrobeStage/Species.json b/scripts/SimulationParameters/MicrobeStage/Species.json index 25d347cd855..03b182f889c 100644 --- a/scripts/SimulationParameters/MicrobeStage/Species.json +++ b/scripts/SimulationParameters/MicrobeStage/Species.json @@ -15,6 +15,9 @@ "organelles": { }, "membranetype": 0, - "isBacteria": false + "isBacteria": false, + "genus": "Primum", + "epithet":"Thrivium", + "population": 30 } } diff --git a/scripts/microbe_stage/configs.as b/scripts/microbe_stage/configs.as index 22f36a593e7..cdd1761bafe 100644 --- a/scripts/microbe_stage/configs.as +++ b/scripts/microbe_stage/configs.as @@ -312,7 +312,9 @@ class MicrobeTemplate{ array organelles, Float4 colour, bool isBacteria, - MEMBRANE_TYPE speciesMembraneType + MEMBRANE_TYPE speciesMembraneType, + string genus, + string epithet ) { this.spawnDensity = spawnDensity; this.compounds = compounds; @@ -320,8 +322,12 @@ class MicrobeTemplate{ this.colour = colour; this.isBacteria = isBacteria; this.speciesMembraneType = speciesMembraneType; + this.genus = genus; + this.epithet = epithet; } + string genus; + string epithet; float spawnDensity; dictionary compounds; array organelles; @@ -368,7 +374,9 @@ const dictionary STARTER_MICROBES = { Float4(1, 1, 1, 1), // Player starts as bacteria true, - MEMBRANE_TYPE::WALL) + MEMBRANE_TYPE::WALL, + "Primum", + "Thrivium") } }; diff --git a/scripts/microbe_stage/microbe_editor/microbe_editor.as b/scripts/microbe_stage/microbe_editor/microbe_editor.as index 66c727a155d..c77f922fa56 100644 --- a/scripts/microbe_stage/microbe_editor/microbe_editor.as +++ b/scripts/microbe_stage/microbe_editor/microbe_editor.as @@ -134,6 +134,10 @@ class MicrobeEditor{ // Update GUI buttons now that we have correct organelles updateGuiButtonStatus(checkIsNucleusPresent()); + + //force add your species + cast(GetThriveGame().getCellStage().GetScriptSystem("SpeciesSystem")).splitSpecies(playerSpecies); + //force an auto-evo step cast(GetThriveGame().getCellStage().GetScriptSystem("SpeciesSystem")).doAutoEvoStep(); // Reset to cytoplasm if nothing is selected diff --git a/scripts/microbe_stage/microbe_operations.as b/scripts/microbe_stage/microbe_operations.as index 7697ce305ac..c3eb65a422a 100644 --- a/scripts/microbe_stage/microbe_operations.as +++ b/scripts/microbe_stage/microbe_operations.as @@ -1047,30 +1047,6 @@ ObjectID _createMicrobeEntity(CellStageWorld@ world, bool aiControlled, ObjectID entity = world.CreateEntity(); // TODO: movement sound for microbes - // auto soundComponent = SoundSourceComponent(); - // auto s1 = null; - // soundComponent.addSound("microbe-release-toxin", - // "soundeffects/microbe-release-toxin.ogg"); - // soundComponent.addSound("microbe-toxin-damage", - // "soundeffects/microbe-toxin-damage.ogg"); - // soundComponent.addSound("microbe-death", "soundeffects/microbe-death.ogg"); - // soundComponent.addSound("microbe-pickup-organelle", - // "soundeffects/microbe-pickup-organelle.ogg"); - // soundComponent.addSound("microbe-engulfment", "soundeffects/engulfment.ogg"); - // soundComponent.addSound("microbe-reproduction", "soundeffects/reproduction.ogg"); - - // s1 = soundComponent.addSound("microbe-movement-1", - // "soundeffects/microbe-movement-1.ogg"); - // s1.properties.volume = 0.4; - // s1.properties.touch(); - // s1 = soundComponent.addSound("microbe-movement-turn", - // "soundeffects/microbe-movement-2.ogg"); - // s1.properties.volume = 0.1; - // s1.properties.touch(); - // s1 = soundComponent.addSound("microbe-movement-2", - // "soundeffects/microbe-movement-3.ogg"); - // s1.properties.volume = 0.4; - // s1.properties.touch(); auto position = world.Create_Position(entity, Float3(0, 0, 0), Float4::IdentityQuaternion); diff --git a/scripts/microbe_stage/setup.as b/scripts/microbe_stage/setup.as index 137d94c36d8..233a8b95617 100644 --- a/scripts/microbe_stage/setup.as +++ b/scripts/microbe_stage/setup.as @@ -663,7 +663,6 @@ void resetWorld(CellStageWorld@ world) // but eh. We can call it all in this method. cast(world.GetScriptSystem("SpeciesSystem")).resetAutoEvo(); - cast(world.GetScriptSystem("SpeciesSystem")).createNewEcoSystem(); } //! AI species are spawned by Species in species_system diff --git a/scripts/microbe_stage/species_system.as b/scripts/microbe_stage/species_system.as index 05e7b0695b7..ce4cd544d04 100644 --- a/scripts/microbe_stage/species_system.as +++ b/scripts/microbe_stage/species_system.as @@ -253,172 +253,6 @@ string randomBacteriaName() class Species{ - //! Constructor for automatically creating a random species - Species(CellStageWorld@ world, bool isBacteria) - { - this.isBacteria = isBacteria; - - if (!isBacteria) - { - name = randomSpeciesName(); - genus = generateNameSection(); - epithet = generateNameSection(); - - initializeBehavior(); - - auto stringSize = GetEngine().GetRandom().GetNumber(MIN_INITIAL_LENGTH, - MAX_INITIAL_LENGTH); - if (GetEngine().GetRandom().GetNumber(0, 100) <= 10){ - // Generate an extremely large cell, players never really had enough challenge - LOG_INFO("Generating EPIC cell"); - stringSize = GetEngine().GetRandom().GetNumber(MIN_INITIAL_EPIC_LENGTH, - MAX_INITIAL_EPIC_LENGTH); - } - - const auto cytoplasmGene = getOrganelleDefinition("cytoplasm").gene; - string energyGene = cytoplasmGene; - const auto bonusPadding = GetEngine().GetRandom().GetNumber(1, 10); - - // it should always have a nucleus and a cytoplasm. - stringCode = getOrganelleDefinition("nucleus").gene + - cytoplasmGene; - - // generated cells need to be viable for now. so heres all possible survival strategies i can think of - switch (GetEngine().GetRandom().GetNumber(0, 15)) - { - case 0: - energyGene = getOrganelleDefinition("cytoplasm").gene; - //if cytoplasm you need a few more of them - for(int i = 0; i < bonusPadding; i++){ - this.stringCode.insert(GetEngine().GetRandom().GetNumber(2, - stringCode.length()), energyGene); - } - break; - case 1: - energyGene = getOrganelleDefinition("metabolosome").gene; - break; - case 2: - energyGene = getOrganelleDefinition("rusticyanin").gene; - energyGene += getOrganelleDefinition("cytoplasm").gene; - break; - case 3: - energyGene = getOrganelleDefinition("cytoplasm").gene; - //if cytoplasm you need a few more of them - for(int i = 0; i < bonusPadding; i++){ - this.stringCode.insert(GetEngine().GetRandom().GetNumber(2, - stringCode.length()), energyGene); - } - energyGene += getOrganelleDefinition("chemoSynthisizingProteins").gene; - break; - case 4: - energyGene = getOrganelleDefinition("mitochondrion").gene; - break; - case 5: - energyGene = getOrganelleDefinition("chemoSynthisizingProteins").gene; - energyGene += getOrganelleDefinition("mitochondrion").gene; - break; - case 6: - energyGene = getOrganelleDefinition("chloroplast").gene; - energyGene += getOrganelleDefinition("mitochondrion").gene; - break; - case 7: - energyGene = getOrganelleDefinition("metabolosome").gene; - energyGene += getOrganelleDefinition("chemoSynthisizingProteins").gene; - break; - case 8: - energyGene = getOrganelleDefinition("metabolosome").gene; - energyGene += getOrganelleDefinition("chromatophors").gene; - break; - case 9: - energyGene = getOrganelleDefinition("chromatophors").gene; - energyGene += getOrganelleDefinition("mitochondrion").gene; - break; - case 10: - energyGene = getOrganelleDefinition("chemoplast").gene; - energyGene += getOrganelleDefinition("mitochondrion").gene; - break; - case 11: - energyGene = getOrganelleDefinition("chemoplast").gene; - energyGene += getOrganelleDefinition("metabolosome").gene; - break; - case 12: - energyGene = getOrganelleDefinition("chromatophors").gene; - energyGene += getOrganelleDefinition("cytoplasm").gene; - break; - case 13: - energyGene = getOrganelleDefinition("chloroplast").gene; - energyGene += getOrganelleDefinition("cytoplasm").gene; - break; - case 14: - - energyGene = getOrganelleDefinition("cytoplasm").gene; - //if cytoplasm you need a few more of them - for(int i = 0; i < bonusPadding; i++){ - this.stringCode.insert(GetEngine().GetRandom().GetNumber(2, - stringCode.length()), energyGene); - } - energyGene += getOrganelleDefinition("chemoplast").gene; - break; - case 15: - energyGene = getOrganelleDefinition("chloroplast").gene; - energyGene += getOrganelleDefinition("metabolosome").gene; - break; - } - - const auto energyPadding = GetEngine().GetRandom().GetNumber(1, 5); - for(int i = 0; i < energyPadding; i++){ - this.stringCode.insert(GetEngine().GetRandom().GetNumber(2, - stringCode.length()), energyGene); - } - - for(int i = 0; i < stringSize; i++){ - this.stringCode += getRandomLetter(false); - } - - // And then random cytoplasm padding - const auto cytoplasmPadding = GetEngine().GetRandom().GetNumber(0, 20); - if (GetEngine().GetRandom().GetNumber(0, 100) <= 25) - { - for(int i = 0; i < cytoplasmPadding; i++){ - if (GetEngine().GetRandom().GetNumber(0, 20)<= 10) - { - this.stringCode.insert(GetEngine().GetRandom().GetNumber(2, - stringCode.length()), energyGene); - } - else { - this.stringCode.insert(GetEngine().GetRandom().GetNumber(2, - stringCode.length()), cytoplasmGene); - } - } - } - - this.colour = getRightColourForSpecies(); - - if (GetEngine().GetRandom().GetNumber(0,100) < 50){ - this.speciesMembraneType = MEMBRANE_TYPE::MEMBRANE; - } - else if (GetEngine().GetRandom().GetNumber(0,100) < 50) { - this.speciesMembraneType = MEMBRANE_TYPE::DOUBLEMEMBRANE; - this.colour.W = randomOpacityChitin();; - } - else if (GetEngine().GetRandom().GetNumber(0,100) < 50) { - this.speciesMembraneType = MEMBRANE_TYPE::WALL; - } - else { - this.speciesMembraneType = MEMBRANE_TYPE::CHITIN; - this.colour.W = randomOpacityChitin(); - } - - commonConstructor(world); - this.setupSpawn(world); - - } - else{ - // We are creating a bacteria right now - generateBacteria(world); - } - } - ~Species() { if(templateEntity != NULL_OBJECT){ @@ -428,8 +262,8 @@ class Species{ } } - // Creates a mutated version of the species and reduces the species population by half - Species(Species@ parent, CellStageWorld@ world, bool isBacteria) + // Creates a mutated version of the species + Species(SpeciesComponent@ parent, CellStageWorld@ world, bool isBacteria) { this.isBacteria = parent.isBacteria; @@ -450,6 +284,7 @@ class Species{ // Make sure not over or under our scales cleanPersonality(); + // Subtly mutate color if (GetEngine().GetRandom().GetNumber(0,5) == 0) { @@ -477,11 +312,29 @@ class Species{ parent.colour.W + randomMutationColourChannel()); } - this.population = int(floor(parent.population / 2.f)); - parent.population = int(ceil(parent.population / 2.f)); this.stringCode = Species::mutate(parent.stringCode); - this.speciesMembraneType = parent.speciesMembraneType; + + if (GetEngine().GetRandom().GetNumber(0,100)<=20){ + if (GetEngine().GetRandom().GetNumber(0,100) < 50){ + this.speciesMembraneType = MEMBRANE_TYPE::MEMBRANE; + } + else if (GetEngine().GetRandom().GetNumber(0,100) < 50) { + this.speciesMembraneType = MEMBRANE_TYPE::DOUBLEMEMBRANE; + this.colour.W = randomOpacityChitin();; + } + else if (GetEngine().GetRandom().GetNumber(0,100) < 50) { + this.speciesMembraneType = MEMBRANE_TYPE::WALL; + } + else { + this.speciesMembraneType = MEMBRANE_TYPE::CHITIN; + this.colour.W = randomOpacityChitin(); + } + } + else { + this.speciesMembraneType = parent.speciesMembraneType; + } + commonConstructor(world); @@ -502,21 +355,7 @@ class Species{ this.opportunism = clamp(this.opportunism, 0.0f, MAX_SPECIES_OPPORTUNISM); } - private void initializeBehavior(){ - // Variables used in AI to determine general behavior - this.aggression = GetEngine().GetRandom().GetFloat(0.0f, - MAX_SPECIES_AGRESSION); - this.fear = GetEngine().GetRandom().GetFloat(0.0f, - MAX_SPECIES_FEAR); - this.activity = GetEngine().GetRandom().GetFloat(0.0f, - MAX_SPECIES_ACTIVITY); - this.focus = GetEngine().GetRandom().GetFloat(0.0f, - MAX_SPECIES_FOCUS); - this.opportunism = GetEngine().GetRandom().GetFloat(0.0f, - MAX_SPECIES_OPPORTUNISM); - } - - private void mutateBehavior(Species@ parent){ + private void mutateBehavior(SpeciesComponent@ parent){ // Variables used in AI to determine general behavior mutate these this.aggression = parent.aggression+GetEngine().GetRandom().GetFloat( MIN_SPECIES_PERSONALITY_MUTATION, MAX_SPECIES_PERSONALITY_MUTATION); @@ -742,92 +581,7 @@ class Species{ BACTERIA_SPAWN_RADIUS); } - void generateBacteria(CellStageWorld@ world) - { - // Chance they spawn with flagella - int bacterialFlagellumChance = 10; - - name = randomBacteriaName(); - genus = generateNameSection(); - epithet = generateNameSection(); - - initializeBehavior(); - - // Bacteria are tiny, start off with a max of 3 hexes (maybe - // we should start them all off with just one? ) - auto stringSize = GetEngine().GetRandom().GetNumber(0, 2); - if (GetEngine().GetRandom().GetNumber(0, 100) <= 10){ - // Generate an extremely large cell, players never really had enough challenge - LOG_INFO("Generating EPIC bacterium"); - stringSize = GetEngine().GetRandom().GetNumber(MIN_INITIAL_EPIC_BACTERIA_LENGTH, - MAX_INITIAL_EPIC_BACTERIA_LENGTH); - } - - // Bacteria - // will randomly have 1 of 3 organelles right now, photosynthesizing proteins, - // respiratory Proteins, or Oxy Toxy Producing Proteins, also pure cytoplasm - // aswell for variety. - //TODO when chemosynthesis is added add a protein for that aswell - switch(GetEngine().GetRandom().GetNumber(1,8)) - { - case 1: - stringCode = getOrganelleDefinition("protoplasm").gene; - break; - case 2: - stringCode = getOrganelleDefinition("metabolosome").gene; - break; - case 3: - stringCode = getOrganelleDefinition("chromatophors").gene; - break; - case 4: - stringCode = getOrganelleDefinition("oxytoxyProteins").gene; - break; - case 5: - stringCode = getOrganelleDefinition("chemoSynthisizingProteins").gene; - break; - case 6: - stringCode = getOrganelleDefinition("nitrogenase").gene; - break; - case 7: - stringCode = getOrganelleDefinition("rusticyanin").gene; - stringCode += getOrganelleDefinition("protoplasm").gene; - break; - default: - stringCode = getOrganelleDefinition("protoplasm").gene; - break; - } - - string chosenType= stringCode; - for(int i = 0; i < stringSize; i++){ - this.stringCode += chosenType; - } - - // Allow bacteria to sometimes start with a flagella instead of having to evolve it - this.colour = getRightColourForSpecies(); - if (GetEngine().GetRandom().GetNumber(1,100) <= bacterialFlagellumChance) - { - this.stringCode+=getOrganelleDefinition("flagellum").gene; - } - if (GetEngine().GetRandom().GetNumber(0,100) < 50) { - this.speciesMembraneType = MEMBRANE_TYPE::WALL; - - } else if (GetEngine().GetRandom().GetNumber(0,100) < 50) { - this.speciesMembraneType = MEMBRANE_TYPE::CHITIN; - this.colour.W = randomOpacityChitin(); - - } else if (GetEngine().GetRandom().GetNumber(0,100) < 50) { - this.speciesMembraneType = MEMBRANE_TYPE::MEMBRANE; - - } else { - this.speciesMembraneType = MEMBRANE_TYPE::DOUBLEMEMBRANE; - this.colour.W = randomOpacityChitin(); - } - - commonConstructor(world); - this.setupSpawn(world); - } - - void mutateBacteria(Species@ parent, CellStageWorld@ world) + void mutateBacteria(SpeciesComponent@ parent, CellStageWorld@ world) { name = randomBacteriaName(); genus = parent.genus; @@ -874,11 +628,27 @@ class Species{ parent.colour.W + randomMutationColourChannel()); } - this.population = int(floor(parent.population / 2.f)); - parent.population = int(ceil(parent.population / 2.f)); - this.stringCode = Species::mutateProkaryote(parent.stringCode); - this.speciesMembraneType = parent.speciesMembraneType; + + if (GetEngine().GetRandom().GetNumber(0,100)<=20){ + if (GetEngine().GetRandom().GetNumber(0,100) < 50){ + this.speciesMembraneType = MEMBRANE_TYPE::MEMBRANE; + } + else if (GetEngine().GetRandom().GetNumber(0,100) < 50) { + this.speciesMembraneType = MEMBRANE_TYPE::DOUBLEMEMBRANE; + this.colour.W = randomOpacityChitin();; + } + else if (GetEngine().GetRandom().GetNumber(0,100) < 50) { + this.speciesMembraneType = MEMBRANE_TYPE::WALL; + } + else { + this.speciesMembraneType = MEMBRANE_TYPE::CHITIN; + this.colour.W = randomOpacityChitin(); + } + } + else { + this.speciesMembraneType = parent.speciesMembraneType; + } commonConstructor(world); this.setupSpawn(world); @@ -987,9 +757,6 @@ class SpeciesSystem : ScriptSystem{ { @this.world = cast(w); assert(this.world !is null, "SpeciesSystem expected CellStageWorld"); - - // This is needed to actually have AI species in the world - createNewEcoSystem(); } void Release() @@ -1014,6 +781,7 @@ class SpeciesSystem : ScriptSystem{ LOG_INFO("Processing Auto-evo Step"); this.timeSinceLastCycle -= SPECIES_SIM_INTERVAL; bool ranEventThisStep=false; + countSpecies(); // Every 8 steps or so do a cambrian explosion style // Event, this should increase variablility significantly if(GetEngine().GetRandom().GetNumber(0, 200) <= 25){ @@ -1094,15 +862,10 @@ class SpeciesSystem : ScriptSystem{ // To prevent ridiculous population numbers currentSpecies.population=MAX_POP_SIZE; auto oldPop = currentSpecies.population; - auto newSpecies = Species(currentSpecies, world, + auto speciesComp = world.GetComponent_SpeciesComponent(currentSpecies.templateEntity); + auto newSpecies = Species(speciesComp, world, currentSpecies.isBacteria); - if (newSpecies.isBacteria){ - currentBacteriaAmount+=1; - } - else{ - currentEukaryoteAmount+=1; - } ranSpeciesEvent=true; species.insertLast(newSpecies); LOG_INFO("Species " + currentSpecies.name + @@ -1117,14 +880,14 @@ class SpeciesSystem : ScriptSystem{ // To prevent ridiculous population numbers currentSpecies.population=MAX_POP_SIZE; - auto newSpecies = Species(currentSpecies, world, + currentSpecies.population = int(floor(currentSpecies.population / 2.f)); + + auto speciesComp = world.GetComponent_SpeciesComponent(currentSpecies.templateEntity); + auto newSpecies = Species(speciesComp, world, currentSpecies.isBacteria); - if (newSpecies.isBacteria){ - currentBacteriaAmount+=1; - } - else{ - currentEukaryoteAmount+=1; - } + + newSpecies.population = int(ceil(currentSpecies.population)); + species.insertLast(newSpecies); LOG_INFO("Species " + currentSpecies.name + " split off a child species:" + newSpecies.name); @@ -1137,30 +900,8 @@ class SpeciesSystem : ScriptSystem{ LOG_INFO("Species " + currentSpecies.name + " went extinct"); currentSpecies.extinguish(); species.removeAt(index); - // Tweak numbers here - if (currentSpecies.isBacteria){ - currentBacteriaAmount-=1; - } - else{ - currentEukaryoteAmount-=1; - } } } - - // These are kind of arbitray, we should pronbabbly make it less arbitrary - // New species - while(currentEukaryoteAmount < MIN_SPECIES){ - LOG_INFO("Creating new species as there's too few"); - createSpecies(); - currentEukaryoteAmount++; - } - - // New bacteria - while(currentBacteriaAmount < MIN_BACTERIA){ - LOG_INFO("Creating new prokaryote as there's too few"); - createBacterium(); - currentBacteriaAmount++; - } } void Clear(){} @@ -1178,6 +919,15 @@ class SpeciesSystem : ScriptSystem{ } } + void splitSpecies(SpeciesComponent@ currentSpecies){ + auto newSpecies = Species(currentSpecies, world, + currentSpecies.isBacteria); + + int population = GetEngine().GetRandom().GetNumber(600,INITIAL_POPULATION); + newSpecies.population=GetEngine().GetRandom().GetNumber(600,INITIAL_POPULATION); + species.insertLast(newSpecies); + } + int getSpeciesPopulation(string speciesName) { auto numberOfSpecies = species.length(); @@ -1225,31 +975,17 @@ class SpeciesSystem : ScriptSystem{ } } - //! Adds a new AI species - private void createSpecies() - { - auto newSpecies = Species(world, false); - species.insertLast(newSpecies); - } - - //! Adds a new AI bacterium - private void createBacterium() - { - auto newSpecies = Species(world, true); - species.insertLast(newSpecies); - } - - void createNewEcoSystem() + void countSpecies() { - for(int i = 0; i < INITIAL_SPECIES; i++){ - createSpecies(); - currentEukaryoteAmount++; - } - - //generate bacteria aswell - for(int i = 0; i < INITIAL_BACTERIA; i++){ - createBacterium(); - currentBacteriaAmount++; + currentBacteriaAmount=0; + currentEukaryoteAmount=0; + for(uint i = 0; i < species.length(); i++){ + if (species[i].isBacteria){ + currentBacteriaAmount++; + } + else { + currentEukaryoteAmount++; + } } } @@ -1478,7 +1214,7 @@ ObjectID createSpecies(CellStageWorld@ world, const string &in name, organelle.rotation)); } - return createSpecies(world, name, "Player", "Species", convertedOrganelles, + return createSpecies(world, name, fromTemplate.genus, fromTemplate.epithet, convertedOrganelles, fromTemplate.colour, fromTemplate.isBacteria, fromTemplate.speciesMembraneType, fromTemplate.compounds, 100.0f, 100.0f, 100.0f, 200.0f, 100.0f); } diff --git a/src/microbe_stage/species.cpp b/src/microbe_stage/species.cpp index 0923f1f82f1..9b6fd7ce228 100644 --- a/src/microbe_stage/species.cpp +++ b/src/microbe_stage/species.cpp @@ -13,6 +13,9 @@ Species::Species(Json::Value value) // cast an int as a member of the enum (eg (0,1,2)(membrane,wall,chitin)) speciesMembraneType = static_cast(value["membranetype"].asInt()); + genus = value["genus"].asString(); + epithet = value["epithet"].asString(); + population = value["population"].asInt(); // Setting the cloud colour. float r = value["colour"]["r"].asFloat(); diff --git a/src/microbe_stage/species.h b/src/microbe_stage/species.h index 3aa53d0ea3d..67e53c0aca5 100644 --- a/src/microbe_stage/species.h +++ b/src/microbe_stage/species.h @@ -25,6 +25,7 @@ class Species : public RegistryType { double opportunism; double activity; double focus; + int population; MEMBRANE_TYPE speciesMembraneType; std::map startingCompounds; std::map organelles; // TODO: get a position as the key. diff --git a/src/microbe_stage/species_component.h b/src/microbe_stage/species_component.h index 53132e8f888..1a32d7d4017 100644 --- a/src/microbe_stage/species_component.h +++ b/src/microbe_stage/species_component.h @@ -33,6 +33,12 @@ class SpeciesComponent : public Leviathan::Component { std::string name; std::string genus; std::string epithet; + + // TODO: + // I really like this but we probabbly will have to remove it later since it + // doesnt code for location The only reason im leaving this here is because + // i dont feel like changing the mutation code at the moment + std::string stringCode; double aggression; double fear; double activity; diff --git a/src/scripting/script_initializer.cpp b/src/scripting/script_initializer.cpp index 43d34ec9d5b..7ae34f5c2a7 100644 --- a/src/scripting/script_initializer.cpp +++ b/src/scripting/script_initializer.cpp @@ -892,11 +892,15 @@ bool ANGELSCRIPT_REGISTERFAIL; } + if(engine->RegisterObjectProperty("SpeciesComponent", "string stringCode", + asOFFSET(SpeciesComponent, stringCode)) < 0) { + ANGELSCRIPT_REGISTERFAIL; + } + if(engine->RegisterObjectProperty("SpeciesComponent", "Float4 colour", asOFFSET(SpeciesComponent, colour)) < 0) { ANGELSCRIPT_REGISTERFAIL; } - if(engine->RegisterObjectProperty("SpeciesComponent", "string name", asOFFSET(SpeciesComponent, name)) < 0) { ANGELSCRIPT_REGISTERFAIL; From 686e085edbe8b6984d70f85afca38e5dd90829d8 Mon Sep 17 00:00:00 2001 From: Untrustedlife Date: Fri, 26 Apr 2019 15:35:15 -0500 Subject: [PATCH 2/8] all species now descend from the player species processor stuff is now reset in restoreOrganelleLayour fixed bug where species lacked a string code sometimes New epithets (instead of mutated epithets) are more likely to be generated when a species splits, and new genuses are more likely to split off, and changed how species colors work, the more derived a species the more color diference now. Started coming up with a way of coding locations,got rid of unused constants, moved mutation code to procedural_microbes, got rid of case that no longer exists gneralized mutation code so eukaryotes and prokaryotes use the same thing Game now keeps track of species organelle position so mor einteresting shapes can appear and spece sthat split from the player maintain their shape, but in the processi broke mutations commented out debug Prints renamed getPosition method to something more descriptive because ill be using it for that. cleaned up code a bunch, it now uses deleimiters and string.split instead of crazy substring shenanigans cleaned up code to be in line with crodnus suggestion Mutations that delete organelles now work removed useless todo that is now fixed simplified code even more using join, also added an experimental "replacing" mutation Changed replacement code a tad cleaned up species code even more, moved membrane stuff to its own function Rewrote a bunch of procedural_microbes.as adding organelles now works Cleaned up code more, also array gets shuffled when placing new organelles on NPC cells to ensure organelles do not always end up on the same side of the cell, reworded comments to be more accurate Changed AI a bit, to prevent randomly stopping while chasing prey. AI base speed is now equal to cell base speed, there is a bug where AI player cells move unusually fast (about double), and that still exists, but at least the player themselves and the other species AI cells are now on a more equal playing ground. Added some spacing in movement_organelle so its more readable. got rid of pointless normalize Got rid of the cast hhenri mentioned, AI now can choose to move more slowly if they have toxins so they don't ram into cells when trying to shoot toxins at them. --- scripts/microbe_stage/configs.as | 13 +- scripts/microbe_stage/microbe_ai.as | 49 +++- .../microbe_editor/microbe_editor.as | 14 +- scripts/microbe_stage/organelle.as | 2 +- .../movement_organelle.as | 3 + scripts/microbe_stage/procedural_microbes.as | 232 ++++++++++++------ scripts/microbe_stage/species_system.as | 224 ++++++----------- 7 files changed, 290 insertions(+), 247 deletions(-) diff --git a/scripts/microbe_stage/configs.as b/scripts/microbe_stage/configs.as index cdd1761bafe..83e592cf76c 100644 --- a/scripts/microbe_stage/configs.as +++ b/scripts/microbe_stage/configs.as @@ -23,15 +23,17 @@ const auto MAX_SPAWN_DISTANCE = 5000.0f; // Cell Colors const auto MIN_COLOR = 0.0f; const auto MAX_COLOR = 0.9f; + // Too subtle? -const auto MIN_COLOR_MUTATION = -0.005f; -const auto MAX_COLOR_MUTATION = 0.005f; +const auto MIN_COLOR_MUTATION = -0.2f; +const auto MAX_COLOR_MUTATION = 0.2f; const auto MIN_OPACITY = 0.5f; const auto MAX_OPACITY = 1.8f; const auto MIN_OPACITY_CHITIN = 0.4f; const auto MAX_OPACITY_CHITIN = 1.2f; + // Min Opacity Mutation const auto MIN_OPACITY_MUTATION = -0.01f; const auto MAX_OPACITY_MUTATION = 0.01f; @@ -40,9 +42,11 @@ const auto MAX_OPACITY_MUTATION = 0.01f; const auto MUTATION_BACTERIA_TO_EUKARYOTE = 1; const auto MUTATION_CREATION_RATE = 0.1f; const auto MUTATION_DELETION_RATE = 0.1f; +const auto MUTATION_REPLACEMENT_RATE = 0.1f; //Removal cost const auto ORGANELLE_REMOVE_COST = 10; + // Spawn Radius const auto MICROBE_SPAWN_RADIUS = 150; const auto BACTERIA_SPAWN_RADIUS = 150; @@ -101,8 +105,11 @@ const auto REGENERATION_RATE = 1.0f; const auto FLAGELLA_ENERGY_COST = 7.1f; const auto FLAGELLA_BASE_FORCE = 0.7f; const auto CELL_BASE_THRUST = 1.6f; + // is set by this and modified by applyCellMovement like the player later -const auto AI_BASE_MOVEMENT = 1.0f; +const auto AI_BASE_MOVEMENT = 1.6f; +const auto AI_FOCUSED_MOVEMENT = 1.0f; + //! The drag force is calculated by taking the current velocity and multiplying it by this. //! This must be negative! const auto CELL_DRAG_MULTIPLIER = -0.12f; diff --git a/scripts/microbe_stage/microbe_ai.as b/scripts/microbe_stage/microbe_ai.as index 512b00d2b5a..1d088e2be04 100644 --- a/scripts/microbe_stage/microbe_ai.as +++ b/scripts/microbe_stage/microbe_ai.as @@ -51,6 +51,8 @@ class MicrobeAIControllerComponent : ScriptComponent{ ObjectID prey = NULL_OBJECT; ObjectID targetChunk = NULL_OBJECT; ObjectID predator = NULL_OBJECT; + bool moveThisHunt = true; + bool moveFocused = false; bool preyPegged=false; // Prey and predator lists array predatoryMicrobes; @@ -521,12 +523,17 @@ class MicrobeAISystem : ScriptSystem{ aiComponent.hasTargetPosition = true; //Always set target Position, for use later in AI - if (aiComponent.speciesAggression+GetEngine().GetRandom().GetNumber(-100.0f,100.0f) > aiComponent.speciesActivity){ - microbeComponent.movementDirection = Float3(0, 0, -AI_BASE_MOVEMENT); + if (aiComponent.moveThisHunt){ + if (aiComponent.moveFocused){ + microbeComponent.movementDirection = Float3(0.0f,0.0f,-AI_FOCUSED_MOVEMENT); } else{ - microbeComponent.movementDirection = Float3(0, 0, 0); + microbeComponent.movementDirection = Float3(0.0f,0.0f,-AI_BASE_MOVEMENT); } + } + else{ + microbeComponent.movementDirection = Float3(0, 0, 0); + } // Turn off engulf if prey is Dead // This is probabbly not working @@ -614,11 +621,11 @@ class MicrobeAISystem : ScriptSystem{ aiComponent.targetPosition = world.GetComponent_Position(chunk)._Position; auto vec = (aiComponent.targetPosition - position._Position); aiComponent.direction = vec.Normalize(); - microbeComponent.facingTargetPoint = aiComponent.targetPosition; + microbeComponent.facingTargetPoint = aiComponent.targetPosition; aiComponent.hasTargetPosition = true; //Always set target Position, for use later in AI - microbeComponent.movementDirection = Float3(0, 0, -AI_BASE_MOVEMENT); + microbeComponent.movementDirection = Float3(0.0f,0.0f,-AI_BASE_MOVEMENT); // Turn off engulf if chunk is gone if (engulfableComponent is null){ @@ -707,7 +714,7 @@ class MicrobeAISystem : ScriptSystem{ auto vec = (position._Position-aiComponent.targetPosition); aiComponent.direction = vec.Normalize(); microbeComponent.facingTargetPoint = -aiComponent.targetPosition; - microbeComponent.movementDirection = Float3(0, 0, -(AI_BASE_MOVEMENT)); + microbeComponent.movementDirection = Float3(0.0f,0.0f,-AI_BASE_MOVEMENT); aiComponent.hasTargetPosition = true; //Freak out and fire toxins everywhere @@ -727,17 +734,17 @@ class MicrobeAISystem : ScriptSystem{ //LOG_INFO("evaluating"); MicrobeAIControllerComponent@ aiComponent = components.first; Position@ position = components.third; + MicrobeComponent@ microbeComponent = components.second; + CompoundId oxytoxyId = SimulationParameters::compoundRegistry().getTypeId("oxytoxy"); + int numberOfAgentVacuoles = int( + microbeComponent.specialStorageOrganelles[formatUInt(oxytoxyId)]); + //rollCheck(aiComponent.speciesOpportunism,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; - } else { if (prey != NULL_OBJECT && predator != NULL_OBJECT) { @@ -745,6 +752,12 @@ class MicrobeAISystem : ScriptSystem{ if (GetEngine().GetRandom().GetNumber(0.0f,aiComponent.speciesAggression) > GetEngine().GetRandom().GetNumber(0.0f,aiComponent.speciesFear) && (aiComponent.preyMicrobes.length() > 0)){ + aiComponent.moveThisHunt=!rollCheck(aiComponent.speciesActivity,500.0f); + + if (numberOfAgentVacuoles > 0){ + aiComponent.moveFocused = rollCheck(aiComponent.speciesFocus,500.0f); + } + aiComponent.lifeState = PREDATING_STATE; } else if (GetEngine().GetRandom().GetNumber(0.0f,aiComponent.speciesAggression) < @@ -756,6 +769,12 @@ class MicrobeAISystem : ScriptSystem{ else if (aiComponent.speciesAggression == aiComponent.speciesFear && (aiComponent.preyMicrobes.length() > 0)){ // Prefer predating (makes game more fun) + aiComponent.moveThisHunt=!rollCheck(aiComponent.speciesActivity,500.0f); + + if (numberOfAgentVacuoles > 0){ + aiComponent.moveFocused = rollCheck(aiComponent.speciesFocus,500.0f); + } + aiComponent.lifeState = PREDATING_STATE; } else if (rollCheck(aiComponent.speciesFocus,500.0f) && GetEngine().GetRandom().GetNumber(0,10) <= 2){ @@ -764,6 +783,12 @@ class MicrobeAISystem : ScriptSystem{ } else if (prey != NULL_OBJECT){ //LOG_INFO("prey only"); + aiComponent.moveThisHunt=!rollCheck(aiComponent.speciesActivity,500.0f); + + if (numberOfAgentVacuoles > 0){ + aiComponent.moveFocused = rollCheck(aiComponent.speciesFocus,500.0f); + } + aiComponent.lifeState = PREDATING_STATE; } else if (predator != NULL_OBJECT){ @@ -845,7 +870,7 @@ class MicrobeAISystem : ScriptSystem{ auto vec = (aiComponent.targetPosition - position._Position); aiComponent.direction = vec.Normalize(); microbeComponent.facingTargetPoint = aiComponent.targetPosition; - microbeComponent.movementDirection = Float3(0, 0, -AI_BASE_MOVEMENT); + microbeComponent.movementDirection = Float3(0.0f,0.0f,-AI_BASE_MOVEMENT); aiComponent.hasTargetPosition = true; } diff --git a/scripts/microbe_stage/microbe_editor/microbe_editor.as b/scripts/microbe_stage/microbe_editor/microbe_editor.as index c77f922fa56..64573f7dbf7 100644 --- a/scripts/microbe_stage/microbe_editor/microbe_editor.as +++ b/scripts/microbe_stage/microbe_editor/microbe_editor.as @@ -125,10 +125,20 @@ class MicrobeEditor{ playerSpecies.organelles); editedMicrobe.resize(0); + playerSpecies.stringCode=""; for(uint i = 0; i < templateOrganelles.length(); ++i){ - editedMicrobe.insertLast(cast(templateOrganelles[i])); + auto organelle = cast(templateOrganelles[i]); + editedMicrobe.insertLast(organelle); + playerSpecies.stringCode+=organelle._organelle.gene; + // This will always be added after each organelle so its safe to assume its there + playerSpecies.stringCode+=","+organelle.q+","+ + organelle.r+","+ + organelle.rotation; + if (i != templateOrganelles.length()-1){ + playerSpecies.stringCode+="|"; + } } - + LOG_INFO(playerSpecies.stringCode); LOG_INFO("Starting microbe editor with: " + editedMicrobe.length() + " organelles in the microbe"); diff --git a/scripts/microbe_stage/organelle.as b/scripts/microbe_stage/organelle.as index 76c49fdde5d..f7d18abcf39 100644 --- a/scripts/microbe_stage/organelle.as +++ b/scripts/microbe_stage/organelle.as @@ -873,7 +873,7 @@ class PlacedOrganelle : SpeciesStoredOrganelleType{ } } - private Organelle@ _organelle; + Organelle@ _organelle; // q and r are radial coordinates instead of cartesian // Could use the class AxialCoordinates here diff --git a/scripts/microbe_stage/organelle_components/movement_organelle.as b/scripts/microbe_stage/organelle_components/movement_organelle.as index aaeb013803d..45b58dfe6a1 100644 --- a/scripts/microbe_stage/organelle_components/movement_organelle.as +++ b/scripts/microbe_stage/organelle_components/movement_organelle.as @@ -205,9 +205,12 @@ class MovementOrganelle : OrganelleComponent{ MicrobeComponent@ microbeComponent = cast( organelle.world.GetScriptComponentHolder("MicrobeComponent").Find(microbeEntity)); auto pos = organelle.world.GetComponent_Position(microbeEntity); + + const auto force = calculateMovementForce(microbeEntity, organelle, logicTime, microbeComponent, pos); + if(force != Float3(0, 0, 0)) microbeComponent.addMovementForce(force); } diff --git a/scripts/microbe_stage/procedural_microbes.as b/scripts/microbe_stage/procedural_microbes.as index 0b1206d4cc0..48f8404bdf8 100644 --- a/scripts/microbe_stage/procedural_microbes.as +++ b/scripts/microbe_stage/procedural_microbes.as @@ -1,17 +1,7 @@ #include "configs.as" #include "nucleus_organelle.as" #include "hex.as" - -// Limits the size of the initial stringCodes -const auto MIN_INITIAL_LENGTH = 2; -const auto MAX_INITIAL_LENGTH = 15; - -const auto MIN_INITIAL_EPIC_LENGTH = 30; -const auto MAX_INITIAL_EPIC_LENGTH = 70; - -const auto MIN_INITIAL_EPIC_BACTERIA_LENGTH = 3; -const auto MAX_INITIAL_EPIC_BACTERIA_LENGTH = 30; - +// Lists of valid organelles to choose from for mutation dictionary organelleLetters = {}; array VALID_ORGANELLES = {}; array VALID_ORGANELLE_LETTERS = {}; @@ -55,6 +45,8 @@ void setupOrganelleLetters(){ // TODO: verify that this has a good chance of returning also the last organelle // TODO: is there a way to make this run faster? string getRandomLetter(bool isBacteria){ + + // This is actually essentially the entire mutation system here if (!isBacteria) { float i = GetEngine().GetRandom().GetNumber(0.f, maxEukaryoteScore); @@ -86,18 +78,19 @@ string getRandomLetter(bool isBacteria){ // Checks whether an organelle in a certain position would fit within a list of other organelles. bool isValidPlacement(const string &in organelleName, int q, int r, int rotation, - const array &in organelleList + array@ organelleList ) { - // This is super hacky :/ - // this is now slightly less hacky + + // this is now slightly less hacky but it could be btter auto organelleHexes = getOrganelleDefinition(organelleName).getRotatedHexes(rotation); for(uint i = 0; i < organelleList.length(); ++i){ auto otherOrganelle = organelleList[i]; + auto organelleDef = getOrganelleDefinition(otherOrganelle.organelle.name); - auto otherOrganelleHexes = getOrganelleDefinition(otherOrganelle.type).getRotatedHexes( - otherOrganelle.rotation); + // The organelles hexes + auto otherOrganelleHexes = organelleDef.getRotatedHexes(organelleList[i].rotation); for(uint thisHexIndex = 0; thisHexIndex < organelleHexes.length(); ++thisHexIndex){ @@ -119,101 +112,186 @@ bool isValidPlacement(const string &in organelleName, int q, int r, int rotation } // Finds a valid position to place the organelle and returns it -// Maybe the values should be saved? -OrganelleTemplatePlaced@ getPosition(const string &in organelleName, - const array &in organelleList +// We should be able to get far more creative with our cells now +OrganelleTemplatePlaced@ getRealisticPosition(const string &in organelleName, + array@ organelleList ) { int q = 0; int r = 0; - // Checks whether the center is free. - for(int j = 0; j <= 5; ++j){ - int rotation = 360 * j / 6; - if(isValidPlacement(organelleName, q, r, rotation, organelleList)){ - return OrganelleTemplatePlaced(organelleName, q, r, rotation); - } - } + auto organelleShuffledArray = organelleList; - // Moving the center one hex to the bottom. - // This way organelles are "encouraged" to be on the bottom, rather than on the top, - // which in turn means the flagellum are more likely to be on the back side of the cell. - auto initialOffset = Int2(HEX_NEIGHBOUR_OFFSET[formatInt(int(HEX_SIDE::TOP))]); - q = q + initialOffset.X; - r = r + initialOffset.Y; - - // Spiral search for space for the organelle - int radius = 1; - - while(true){ - //Moves into the ring of radius "radius" and center the old organelle - Int2 radiusOffset = Int2(HEX_NEIGHBOUR_OFFSET[ - formatInt(int(HEX_SIDE::BOTTOM_LEFT))]); - q = q + radiusOffset.X; - r = r + radiusOffset.Y; - - //Iterates in the ring - for(int side = 1; side <= 6; ++side){ - Int2 offset = Int2(HEX_NEIGHBOUR_OFFSET[formatInt(side)]); - //Moves "radius" times into each direction - for(int i = 1; i <= radius; ++i){ + // Shuffle the Array to make sure its not always placing at the same part of the cell + organelleShuffledArray.sort( function(a,b) { + return GetEngine().GetRandom().GetNumber(0,100) <= 50; + } + ); + + // Loop through all the organelles and find an open spot to place our new organelle attached to existing organelles + // This almost always is over at the first iteration, so its not a huge performance hog + for(uint i = 0; i < organelleShuffledArray.length(); ++i){ + // The organelle we wish to be next to + auto otherOrganelle = organelleShuffledArray[i].organelle; + auto organelleDef = getOrganelleDefinition(otherOrganelle.name); + + // The organelles hexes + auto hexes = organelleDef.getRotatedHexes(organelleShuffledArray[i].rotation); + + // Middle of our organelle + q = organelleShuffledArray[i].q; + r = organelleShuffledArray[i].r; + + for(uint z = 0; z < hexes.length(); ++z){ + // Off set by hexes in organelle we are looking at + q+=hexes[z].q; + r+=hexes[z].r; + + for(int side = 1; side <= 6; ++side){ + Int2 offset = Int2(HEX_NEIGHBOUR_OFFSET[formatInt(side)]); + // Offset by hex offset q = q + offset.X; r = r + offset.Y; - //Checks every possible rotation value. + //Check every possible rotation value. for(int j = 0; j <= 5; ++j){ - int rotation = (360 * j / 6); - - if(isValidPlacement(organelleName, q, r, rotation, organelleList)){ + if(isValidPlacement(organelleName, q, r, rotation, organelleShuffledArray)){ return OrganelleTemplatePlaced(organelleName, q, r, rotation); } } } - } - ++radius; - } + //Gotta reset each time + q = organelleShuffledArray[i].q; + r = organelleShuffledArray[i].r; + } + } + // We didnt find an open spot, that doesnt mak emuch sense return null; } +// This function takes in a positioning block from the string code and a name +// and returns an organelle with the correct position info +OrganelleTemplatePlaced@ getStringCodePosition(const string &in organelleName, string code){ + //LOG_INFO(code); + + array@ chromArray = code.split(","); + //TODO:Need to add some proper error handling + int q = 0; + int r = 0; + int rotation = 0; + + q=parseInt(chromArray[1]); + + //LOG_INFO(""+q); + r=parseInt(chromArray[2]); + + //LOG_INFO(""+r); + + rotation=parseInt(chromArray[3]); + + //LOG_INFO(""+rotation); + + return OrganelleTemplatePlaced(organelleName, q, r, rotation); +} + // Creates a list of organelles from the stringCode. array@ positionOrganelles(const string &in stringCode){ // TODO: remove once this works - LOG_INFO("DEBUG: positionOrganelles stringCode: " + stringCode); + //LOG_INFO("DEBUG: positionOrganelles stringCode: " + stringCode); array@ result = array(); - array organelleList; + array@ chromArray = stringCode.split("|"); + for(uint i = 0; i < chromArray.length(); ++i){ + OrganelleTemplatePlaced@ pos; + string geneCode = chromArray[i]; + + if (geneCode.length() > 0){ + const auto letter = CharacterToString(geneCode[0]); + //LOG_WRITE(formatUInt(i) + ": " + letter); + string name = string(organelleLetters[letter]); + @pos = getStringCodePosition(name,geneCode); + + if(pos.type == ""){ + assert(false, "positionOrganelles: organelleLetters didn't have the " + "current letter: " + letter); + } - for(uint i = 0; i < stringCode.length(); ++i){ + result.insertLast(PlacedOrganelle(getOrganelleDefinition(pos.type), pos.q, pos.r, + pos.rotation)); + } + } - OrganelleTemplatePlaced@ pos; - const auto letter = CharacterToString(stringCode[i]); - // LOG_WRITE(formatUInt(i) + ": " + letter); - string name = string(organelleLetters[letter]); - //this places the nucleus - if(i == 0){ + return result; +} - @pos = OrganelleTemplatePlaced(name, 0, 0, 360); +//! Mutates a species' dna code randomly - } else { - @pos = getPosition(name, organelleList); - } +string translateOrganelleToGene(OrganelleTemplatePlaced@ ourOrganelle){ + string completeString = ""; + auto organelle = getOrganelleDefinition(ourOrganelle.type); + completeString=organelle.gene+","+ + ourOrganelle.q+","+ + ourOrganelle.r+","+ + ourOrganelle.rotation; + return completeString; - if(pos.type == ""){ +} + +// Pass in the string code, isbacteria +string mutateMicrobe(const string &in stringCode, bool isBacteria) +{ + array@ chromArray = stringCode.split("|"); + array@ modifiedArray = chromArray; + LOG_INFO(chromArray[0]); + string completeString = ""; + + // Delete or replace an organelle randomly + for(uint i = 0; i < chromArray.length(); i++){ + string chromosomes = chromArray[i]; + // Removing last organelle would be silly + if(GetEngine().GetRandom().GetNumber(0.f, 1.f) < MUTATION_DELETION_RATE && chromosomes.length() > 0){ + if (i != chromArray.length()-1 && CharacterToString(chromosomes[0]) != "N"){ + //LOG_INFO("deleteing"); + //LOG_INFO("chromosomes:"+chromArray[i]); + // Delete organelle and its position + modifiedArray.removeAt(i); - assert(false, "positionOrganelles: organelleLetters didn't have the " - "current letter: " + letter); + } + }else if(GetEngine().GetRandom().GetNumber(0.f, 1.f) < MUTATION_REPLACEMENT_RATE && chromosomes.length() > 0){ + if (CharacterToString(chromosomes[0]) != "N"){ + //LOG_INFO("Replacing"); + //LOG_INFO("chromosomes:"+chromArray[i]); + chromosomes[0]=getRandomLetter(isBacteria)[0]; + if (i != chromArray.length()-1){ + modifiedArray.removeAt(i); + modifiedArray.insertAt(i,chromosomes); + } + else{ + modifiedArray.removeAt(i); + modifiedArray.insertLast(chromosomes); + } + } } - organelleList.insertLast(pos); - result.insertLast(PlacedOrganelle(getOrganelleDefinition(pos.type), pos.q, pos.r, - pos.rotation)); } - // Make sure all were added - assert(stringCode.length() == result.length()); - return result; + completeString = join(modifiedArray,"|"); + + // 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); + 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/species_system.as b/scripts/microbe_stage/species_system.as index ce4cd544d04..05c6ae09368 100644 --- a/scripts/microbe_stage/species_system.as +++ b/scripts/microbe_stage/species_system.as @@ -266,19 +266,20 @@ class Species{ Species(SpeciesComponent@ parent, CellStageWorld@ world, bool isBacteria) { this.isBacteria = parent.isBacteria; - + LOG_INFO("Gene Code Is:"+parent.stringCode); if (!isBacteria) { name = randomSpeciesName(); + //Mutate the epithet - if (GetEngine().GetRandom().GetNumber(0, 10) < 8){ + if (GetEngine().GetRandom().GetNumber(0, 10) < 5){ epithet = mutateWord(parent.epithet); } else { epithet = generateNameSection(); } genus = parent.genus; - + colour=parent.colour; mutateBehavior(parent); // Make sure not over or under our scales @@ -286,20 +287,19 @@ class Species{ // Subtly mutate color - if (GetEngine().GetRandom().GetNumber(0,5) == 0) - { - this.colour = Float4(parent.colour.X + randomMutationColourChannel(), - parent.colour.Y + randomMutationColourChannel(), - parent.colour.Z + randomMutationColourChannel(), - parent.colour.W + randomMutationColourChannel()); - } + this.colour = Float4(parent.colour.X + randomMutationColourChannel(), + parent.colour.Y + randomMutationColourChannel(), + parent.colour.Z + randomMutationColourChannel(), + parent.colour.W + randomMutationColourChannel()); + 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)==1) + if (GetEngine().GetRandom().GetNumber(0,100) <= 20) { LOG_INFO("New Genus"); // We can do more fun stuff here later - if (GetEngine().GetRandom().GetNumber(0, 10) < 8){ + if (GetEngine().GetRandom().GetNumber(0, 10) < 5){ genus = mutateWord(parent.genus); } else { @@ -312,28 +312,10 @@ class Species{ parent.colour.W + randomMutationColourChannel()); } - this.stringCode = Species::mutate(parent.stringCode); + this.stringCode = mutateMicrobe(parent.stringCode,false); - if (GetEngine().GetRandom().GetNumber(0,100)<=20){ - if (GetEngine().GetRandom().GetNumber(0,100) < 50){ - this.speciesMembraneType = MEMBRANE_TYPE::MEMBRANE; - } - else if (GetEngine().GetRandom().GetNumber(0,100) < 50) { - this.speciesMembraneType = MEMBRANE_TYPE::DOUBLEMEMBRANE; - this.colour.W = randomOpacityChitin();; - } - else if (GetEngine().GetRandom().GetNumber(0,100) < 50) { - this.speciesMembraneType = MEMBRANE_TYPE::WALL; - } - else { - this.speciesMembraneType = MEMBRANE_TYPE::CHITIN; - this.colour.W = randomOpacityChitin(); - } - } - else { - this.speciesMembraneType = parent.speciesMembraneType; - } + generateMembranes(parent); commonConstructor(world); @@ -347,6 +329,28 @@ class Species{ } } + private void generateMembranes(SpeciesComponent@ parent){ + if (GetEngine().GetRandom().GetNumber(0,100)<=20){ + if (GetEngine().GetRandom().GetNumber(0,100) < 50){ + this.speciesMembraneType = MEMBRANE_TYPE::MEMBRANE; + } + else if (GetEngine().GetRandom().GetNumber(0,100) < 50) { + this.speciesMembraneType = MEMBRANE_TYPE::DOUBLEMEMBRANE; + this.colour.W = randomOpacityChitin(); + } + else if (GetEngine().GetRandom().GetNumber(0,100) < 50) { + this.speciesMembraneType = MEMBRANE_TYPE::WALL; + } + else { + this.speciesMembraneType = MEMBRANE_TYPE::CHITIN; + this.colour.W = randomOpacityChitin(); + } + } + else{ + this.speciesMembraneType = parent.speciesMembraneType; + } + } + private void cleanPersonality() { this.aggression = clamp(this.aggression, 0.0f, MAX_SPECIES_AGRESSION); this.fear = clamp(this.fear, 0.0f, MAX_SPECIES_FEAR); @@ -373,7 +377,9 @@ class Species{ { @forWorld = world; + // This translates the genetic code into positions auto organelles = positionOrganelles(stringCode); + // If you have iron (f is the symbol for rusticyanin) if (stringCode.findFirst('f') >= 0) { @@ -585,8 +591,9 @@ class Species{ { name = randomBacteriaName(); genus = parent.genus; + colour=parent.colour; //Mutate the epithet - if (GetEngine().GetRandom().GetNumber(0, 10) < 8){ + if (GetEngine().GetRandom().GetNumber(0, 10) < 5){ epithet = mutateWord(parent.epithet); } else { @@ -600,21 +607,22 @@ class Species{ cleanPersonality(); // Subtly mutate color - if (GetEngine().GetRandom().GetNumber(0, 5)==0) - { - this.colour = Float4(parent.colour.X + randomMutationColourChannel(), - parent.colour.Y + randomMutationColourChannel(), - parent.colour.Z + randomMutationColourChannel(), - parent.colour.W + randomMutationColourChannel()); - } + this.colour = Float4(parent.colour.X + randomMutationColourChannel(), + parent.colour.Y + randomMutationColourChannel(), + parent.colour.Z + randomMutationColourChannel(), + parent.colour.W + randomMutationColourChannel()); - if (GetEngine().GetRandom().GetNumber(0, 100)==1) + + 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) { LOG_INFO("New Genus of bacteria"); // We can do more fun stuff here later //Mutate the genus - if (GetEngine().GetRandom().GetNumber(0, 10) < 8){ + if (GetEngine().GetRandom().GetNumber(0, 10) < 5){ genus = mutateWord(parent.genus); } else { @@ -628,27 +636,9 @@ class Species{ parent.colour.W + randomMutationColourChannel()); } - this.stringCode = Species::mutateProkaryote(parent.stringCode); + this.stringCode = mutateMicrobe(parent.stringCode,true); - if (GetEngine().GetRandom().GetNumber(0,100)<=20){ - if (GetEngine().GetRandom().GetNumber(0,100) < 50){ - this.speciesMembraneType = MEMBRANE_TYPE::MEMBRANE; - } - else if (GetEngine().GetRandom().GetNumber(0,100) < 50) { - this.speciesMembraneType = MEMBRANE_TYPE::DOUBLEMEMBRANE; - this.colour.W = randomOpacityChitin();; - } - else if (GetEngine().GetRandom().GetNumber(0,100) < 50) { - this.speciesMembraneType = MEMBRANE_TYPE::WALL; - } - else { - this.speciesMembraneType = MEMBRANE_TYPE::CHITIN; - this.colour.W = randomOpacityChitin(); - } - } - else { - this.speciesMembraneType = parent.speciesMembraneType; - } + generateMembranes(parent); commonConstructor(world); this.setupSpawn(world); @@ -1064,6 +1054,7 @@ void applyTemplate(CellStageWorld@ world, ObjectID microbe, SpeciesComponent@ sp InitialCompound amount = InitialCompound(species.avgCompoundAmounts[ids[i]]); MicrobeOperations::setCompound(world, microbe, compoundId, amount.amount); } + } void restoreOrganelleLayout(CellStageWorld@ world, ObjectID microbeEntity, @@ -1097,6 +1088,11 @@ void restoreOrganelleLayout(CellStageWorld@ world, ObjectID microbeEntity, // Cache isBacteria from species. This can be changed depending on // the added organelles in the editor 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, @@ -1237,11 +1233,20 @@ ObjectID createSpecies(CellStageWorld@ world, const string &in name, const strin @speciesComponent.avgCompoundAmounts = dictionary(); @speciesComponent.organelles = array(); - for(uint i = 0; i < organelles.length(); i++){ - - // This conversion does a little bit of extra calculations (that are in the - // end not used) - speciesComponent.organelles.insertLast(PlacedOrganelle(organelles[i])); + speciesComponent.stringCode=""; + + // Translate positions over + for(uint i = 0; i < organelles.length(); ++i){ + auto organelle = cast(organelles[i]); + speciesComponent.organelles.insertLast(organelle); + speciesComponent.stringCode+=organelle._organelle.gene; + // This will always be added after each organelle so its safe to assume its there + speciesComponent.stringCode+=","+organelle.q+","+ + organelle.r+","+ + organelle.rotation; + if (i != organelles.length()-1){ + speciesComponent.stringCode+="|"; + } } // Verify it // @@ -1297,91 +1302,6 @@ ObjectID createSpecies(CellStageWorld@ world, const string &in name, const strin return speciesEntity; } - -//! Mutates a species' dna code randomly -string mutate(const string &in stringCode) -{ - // Moving the stringCode to a table to facilitate changes - string chromosomes = stringCode.substr(2); - - // Try to insert a letter at the end of the table. - if(GetEngine().GetRandom().GetNumber(0.f, 1.f) < MUTATION_CREATION_RATE){ - chromosomes += getRandomLetter(false); - } - - // Modifies the rest of the table. - for(uint i = 0; i < stringCode.length(); i++){ - // Index we are adding or erasing chromosomes at - uint index = stringCode.length() - i - 1; - - if(GetEngine().GetRandom().GetNumber(0.f, 1.f) < MUTATION_DELETION_RATE){ - // Removing the last organelle is pointless, that would - // kill the creature (also caused errors). - if (index != stringCode.length()-1) - { - chromosomes.erase(index, 1); - } - } - - if(GetEngine().GetRandom().GetNumber(0.f, 1.f) < MUTATION_CREATION_RATE){ - // There is an error here when we try to insert at the end - // of the list so use insertlast instead in that case - if (index != stringCode.length()-1) - { - chromosomes.insert(index, getRandomLetter(false)); - } - else{ - chromosomes+=getRandomLetter(false); - } - } - } - - // Transforming the table back into a string - // TODO: remove Hardcoded microbe genes - auto newString = "NY" + chromosomes; - return newString; -} - -// Mutate a Bacterium -string mutateProkaryote(const string &in stringCode) -{ - // Moving the stringCode to a table to facilitate changes - string chromosomes = stringCode; - - // Try to insert a letter at the end of the table. - if(GetEngine().GetRandom().GetNumber(0.f, 1.f) < MUTATION_CREATION_RATE){ - chromosomes += getRandomLetter(true); - } - - // Modifies the rest of the table. - for(uint i = 0; i < stringCode.length(); i++){ - // Index we are adding or erasing chromosomes at - uint index = stringCode.length() - i -1; - // Bacteria can be size 1 so removing their only organelle is a bad idea - if(GetEngine().GetRandom().GetNumber(0.f, 1.f) < MUTATION_DELETION_RATE){ - if (index != stringCode.length()-1) - { - chromosomes.erase(index, 1); - } - } - - if(GetEngine().GetRandom().GetNumber(0.f, 1.f) < MUTATION_CREATION_RATE){ - // There is an error here when we try to insert at the end - // of the list so use insertlast instead in that case - if (index != stringCode.length()-1) - { - chromosomes.insert(index, getRandomLetter(true)); - } - else{ - chromosomes+=getRandomLetter(true); - } - } - } - - auto newString = "" + chromosomes; - return newString; -} - //! Calls resetAutoEvo on world's SpeciesSystem void resetAutoEvo(CellStageWorld@ world){ cast(world.GetScriptSystem("SpeciesSystem")).resetAutoEvo(); From ddbd0e58456c9bc1d52dba0d16e6746a414f41f5 Mon Sep 17 00:00:00 2001 From: Untrustedlife Date: Wed, 1 May 2019 19:46:46 -0500 Subject: [PATCH 3/8] did a massive amount of rebalancing Added new bathylpelagic biome, it has greenish light, slightly mor elight then the abyss, less free floating toxins, less free floating iron, a temperature of 4 degrees celsious and much more common marine snow Changed lighting in bathy biome to be better, fixed nitrogenase offset in editor. Fixed innacuracy in tooltip You now need to survive 20 generations to win with 500 population, also fixed bug that prevented players from not being able to win after winning and starting a new game Changed AI oxytoxy proteins into oxytoxisome, and changed the process it uses, and allowed players to add it in the editor Added information on the other process it does AI eukaryotic cells can now use oxytoxisomes, and reduced cost of cytoplasm from 30 to 22, which means two of them costs 44 , so they mesh better with your other options added new model for toxin vacuole --- materials/background.material | 47 ++- materials/oxytoxy_gland.material | 36 ++ .../MicrobeStage/BioProcesses.json | 13 + .../MicrobeStage/Biomes.json | 323 +++++++++++++----- scripts/gui/microbe_editor.mjs | 4 + scripts/gui/microbe_hud.mjs | 4 +- scripts/gui/thrive_gui.html | 34 +- .../microbe_editor/microbe_editor.as | 1 + scripts/microbe_stage/organelle_table.as | 14 +- .../compound_absorber_system.cpp | 2 +- 10 files changed, 375 insertions(+), 103 deletions(-) create mode 100644 materials/oxytoxy_gland.material diff --git a/materials/background.material b/materials/background.material index ce563b958ca..86532ea11a5 100644 --- a/materials/background.material +++ b/materials/background.material @@ -87,7 +87,7 @@ material Background_Vent } } -material Background_Bathypalagic +material Background_Abyssopelagic { technique { @@ -130,6 +130,51 @@ material Background_Bathypalagic } } } + +material Background_Bathypalagic +{ + technique + { + pass + { + // scene_blend alpha_blend + depth_write off + depth_check off + + vertex_program_ref Background_VS + { + } + fragment_program_ref Background_PS + { + } + texture_unit 0 + { + filtering none + tex_coord_set 0 + texture background/Thrive_bathy0.png 2d gamma + } + texture_unit 1 + { + filtering none + tex_coord_set 1 + texture background/Thrive_bathy1.png 2d gamma + } + texture_unit 2 + { + filtering none + tex_coord_set 2 + texture background/Thrive_bathy2.png 2d gamma + } + texture_unit 3 + { + filtering none + tex_coord_set 3 + texture background/Thrive_bathy3.png 2d gamma + } + } + } +} + material Background_Tidepool { technique diff --git a/materials/oxytoxy_gland.material b/materials/oxytoxy_gland.material new file mode 100644 index 00000000000..9ec124d054b --- /dev/null +++ b/materials/oxytoxy_gland.material @@ -0,0 +1,36 @@ +material oxytoxy_gland +{ + receive_shadows on + + technique + { + pass oxytoxy_gland + { + // lighting off + + scene_blend alpha_blend + depth_write on + point_sprites on + + vertex_program_ref Organelle_VS + { + param_named_auto worldViewProj worldviewproj_matrix + param_named_auto time time_0_2pi 20 + param_named size float 0.05 + param_named maxRot float 15 + } + fragment_program_ref Organelle_PS + { + param_named tex int 0 + param_named_auto organelleColour custom 1 + } + + texture_unit + { + texture oxytoxy_gland.png gamma + alpha_op_ex modulate src_manual src_texture .7 + colour_op_ex modulate src_manual src_texture 1.0 1.0 1.0 + } + } + } +} diff --git a/scripts/SimulationParameters/MicrobeStage/BioProcesses.json b/scripts/SimulationParameters/MicrobeStage/BioProcesses.json index 617f9cfda90..fdea9ba4194 100644 --- a/scripts/SimulationParameters/MicrobeStage/BioProcesses.json +++ b/scripts/SimulationParameters/MicrobeStage/BioProcesses.json @@ -60,6 +60,19 @@ "oxytoxy": 5.0 } }, + + "bacterial_oxytoxySynthesis": { + "name": "Bacterial Oxytoxy Synthesis", + + "inputs": { + "oxygen": 0.21, + "atp": 5.0 + }, + + "outputs": { + "oxytoxy": 0.5 + } + }, "chemoSynthesis": { "name": "Chemo Synthesis", diff --git a/scripts/SimulationParameters/MicrobeStage/Biomes.json b/scripts/SimulationParameters/MicrobeStage/Biomes.json index bceafb26cfe..b4852417e5d 100644 --- a/scripts/SimulationParameters/MicrobeStage/Biomes.json +++ b/scripts/SimulationParameters/MicrobeStage/Biomes.json @@ -51,12 +51,12 @@ "chunkScale": 1.0, "mass": 100, "size": 2, - "ventAmount": 3.0, + "ventAmount": 6.0, "damages": 0.0, "deleteOnTouch": false, "compounds": { "iron": { - "amount": 100.0 + "amount": 200.0 } } }, @@ -69,12 +69,12 @@ "chunkScale": 1.0, "mass": 100, "size": 100, - "ventAmount": 10.0, + "ventAmount": 20.0, "damages": 0.0, "deleteOnTouch": false, "compounds": { "iron": { - "amount": 30000.0 + "amount": 60000.0 } } } @@ -84,25 +84,25 @@ "compounds": { "ammonia": { - "amount": 300000, + "amount": 200000, "density": 0.00002, "dissolved": 0.0 }, "glucose": { - "amount": 350000, + "amount": 250000, "density": 0.00002, "dissolved": 0.0 }, "phosphates": { - "amount": 300000, + "amount": 200000, "density": 0.00002, "dissolved": 0.0 }, "hydrogensulfide": { - "amount": 325000, + "amount": 225000, "density": 0.00002, "dissolved": 0.0 }, @@ -179,18 +179,18 @@ "chunkScale": 1.0, "mass": 100, "size": 2, - "ventAmount": 3.0, + "ventAmount": 6.0, "damages": 0.0, "deleteOnTouch": false, "compounds": { "iron": { - "amount": 100.0 + "amount": 200.0 } } }, "marineSnow": { "name": "Marine snow", - "meshes": ["nucleus", "chloroplast", "oxytoxy","flagellum", + "meshes": ["oxytoxy_gland", "nucleus", "chloroplast", "oxytoxy","flagellum", "chemoplast","nitrogenplastid","metabolosome","chromatophores", "vacuole","mitochondrion","chemoproteins","nitrogenase","rusticyanin"], "density": 0.00004, @@ -226,12 +226,12 @@ "chunkScale": 1.0, "mass": 100, "size": 100, - "ventAmount": 10.0, + "ventAmount": 20.0, "damages": 0.0, "deleteOnTouch": false, "compounds": { "iron": { - "amount": 30000.0 + "amount": 60000.0 } } } @@ -241,25 +241,25 @@ "compounds": { "ammonia": { - "amount": 300000, + "amount": 200000, "density": 0.00002, "dissolved": 0.0 }, "glucose": { - "amount": 350000, + "amount": 250000, "density": 0.00002, "dissolved": 0.0 }, "phosphates": { - "amount": 300000, + "amount": 200000, "density": 0.00002, "dissolved": 0.0 }, "hydrogensulfide": { - "amount": 325000, + "amount": 225000, "density": 0.00002, "dissolved": 0.0 }, @@ -335,12 +335,12 @@ "chunkScale": 1.0, "mass": 100, "size": 2, - "ventAmount": 3.0, + "ventAmount": 6.0, "damages": 0.0, "deleteOnTouch": false, "compounds": { "iron": { - "amount": 100.0 + "amount": 200.0 } } }, @@ -353,12 +353,12 @@ "chunkScale": 1.0, "mass": 100, "size": 100, - "ventAmount": 10.0, + "ventAmount": 20.0, "damages": 0.0, "deleteOnTouch": false, "compounds": { "iron": { - "amount": 30000.0 + "amount": 60000.0 } } } @@ -368,25 +368,25 @@ "compounds": { "ammonia": { - "amount": 300000, + "amount": 200000, "density": 0.00002, "dissolved": 0.0 }, "glucose": { - "amount": 350000, + "amount": 250000, "density": 0.00002, "dissolved": 0.0 }, "phosphates": { - "amount": 300000, + "amount": 200000, "density": 0.00002, "dissolved": 0.0 }, "hydrogensulfide": { - "amount": 325000, + "amount": 225000, "density": 0.00002, "dissolved": 0.0 }, @@ -413,6 +413,161 @@ "bathypalagic": { "name": "Bathypalagic", "background": "Background_Bathypalagic", + "lightPower": 30.0, + "colors":{ + "specularColors": { + "r": 0, + "g": 0.4, + "b": 0.5 + }, + "diffuseColors": { + "r": 0, + "g": 0.4, + "b": 0.5 + }, + "upperAmbientColor": { + "r": 0.2, + "g": 0.5, + "b": 0.5 + }, + "lowerAmbientColor": { + "r": 0.1, + "g": 0.5, + "b": 0.5 + } + }, + + "chunks":{ + "floatingToxin": { + "name": "Floating Hazard", + "meshes": ["oxytoxy"], + "density": 0.000015, + "dissolves": false, + "radius": 1, + "chunkScale": 1.0, + "mass": 7, + "size": 10000, + "ventAmount": 3.0, + "damages": 10.0, + "deleteOnTouch": true, + "compounds": { + } + }, + "ironSmallChunk": { + "name": "Small Iron Chunk", + "meshes": ["iron_01", "iron_02", "iron_03","iron_04"], + "density": 0.000015, + "dissolves": true, + "radius": 1, + "chunkScale": 1.0, + "mass": 100, + "size": 2, + "ventAmount": 6.0, + "damages": 0.0, + "deleteOnTouch": false, + "compounds": { + "iron": { + "amount": 200.0 + } + } + }, + "ironBigChunk": { + "name": "Big Iron Chunk", + "meshes": [ "iron_05" ], + "density": 0.000015, + "dissolves": true, + "radius": 10, + "chunkScale": 1.0, + "mass": 100, + "size": 100, + "ventAmount": 20.0, + "damages": 0.0, + "deleteOnTouch": false, + "compounds": { + "iron": { + "amount": 60000.0 + } + } + }, + "marineSnow": { + "name": "Marine snow", + "meshes": ["oxytoxy_gland", "nucleus", "chloroplast", "oxytoxy","flagellum", + "chemoplast","nitrogenplastid","metabolosome","chromatophores", + "vacuole","mitochondrion","chemoproteins","nitrogenase","rusticyanin"], + "density": 0.0002, + "dissolves": true, + "radius": 1, + "chunkScale": 1.0, + "mass": 7, + "size": 2, + "ventAmount": 3.0, + "damages": 0.0, + "deleteOnTouch": false, + "compounds": { + "atp": { + "amount": 100.0 + }, + "ammonia": { + "amount": 100.0 + }, + "phosphates": { + "amount": 100.0 + }, + "glucose": { + "amount": 100.0 + } + } + } + }, + + "averageTemperature": 4, + "compounds": { + "ammonia": { + "amount": 200000, + "density": 0.00002, + "dissolved": 0.0 + }, + + "glucose": { + "amount": 250000, + "density": 0.00002, + "dissolved": 0.0 + }, + + "phosphates": { + "amount": 200000, + "density": 0.00002, + "dissolved": 0.0 + }, + + "hydrogensulfide": { + "amount": 225000, + "density": 0.00002, + "dissolved": 0.0 + }, + + "oxygen": { + "amount": 0, + "density": 0.0, + "dissolved": 0.21 + }, + + "carbondioxide": { + "amount": 0, + "density": 0.0, + "dissolved": 0.09 + }, + + "nitrogen": { + "amount": 0, + "density": 0.0, + "dissolved": 0.70 + } + } + }, + "abyssopelagic": { + "name": "Abyssopelagic", + "background": "Background_Abyssopelagic", "lightPower": 25.0, "colors":{ "specularColors": { @@ -462,12 +617,12 @@ "chunkScale": 1.0, "mass": 100, "size": 2, - "ventAmount": 3.0, + "ventAmount": 6.0, "damages": 0.0, "deleteOnTouch": false, "compounds": { "iron": { - "amount": 100.0 + "amount": 200.0 } } }, @@ -480,18 +635,18 @@ "chunkScale": 1.0, "mass": 100, "size": 100, - "ventAmount": 10.0, + "ventAmount": 20.0, "damages": 0.0, "deleteOnTouch": false, "compounds": { "iron": { - "amount": 30000.0 + "amount": 60000.0 } } }, "marineSnow": { "name": "Marine snow", - "meshes": ["nucleus", "chloroplast", "oxytoxy","flagellum", + "meshes": ["oxytoxy_gland", "nucleus", "chloroplast", "oxytoxy","flagellum", "chemoplast","nitrogenplastid","metabolosome","chromatophores", "vacuole","mitochondrion","chemoproteins","nitrogenase","rusticyanin"], "density": 0.00002, @@ -523,25 +678,25 @@ "averageTemperature": 2, "compounds": { "ammonia": { - "amount": 300000, + "amount": 200000, "density": 0.00002, "dissolved": 0.0 }, "glucose": { - "amount": 350000, + "amount": 250000, "density": 0.00002, "dissolved": 0.0 }, "phosphates": { - "amount": 300000, + "amount": 200000, "density": 0.00002, "dissolved": 0.0 }, "hydrogensulfide": { - "amount": 325000, + "amount": 225000, "density": 0.00002, "dissolved": 0.0 }, @@ -618,12 +773,12 @@ "chunkScale": 1.0, "mass": 100, "size": 2, - "ventAmount": 3.0, + "ventAmount": 6.0, "damages": 0.0, "deleteOnTouch": false, "compounds": { "iron": { - "amount": 100.0 + "amount": 200.0 } } }, @@ -636,18 +791,18 @@ "chunkScale": 1.0, "mass": 100, "size": 100, - "ventAmount": 10.0, + "ventAmount": 20.0, "damages": 0.0, "deleteOnTouch": false, "compounds": { "iron": { - "amount": 30000.0 + "amount": 60000.0 } } }, "marineSnow": { "name": "Marine snow", - "meshes": ["nucleus", "chloroplast", "oxytoxy","flagellum", + "meshes": ["oxytoxy_gland", "nucleus", "chloroplast", "oxytoxy","flagellum", "chemoplast","nitrogenplastid","metabolosome","chromatophores", "vacuole","mitochondrion","chemoproteins","nitrogenase","rusticyanin"], "density": 0.00002, @@ -679,25 +834,25 @@ "averageTemperature": 2, "compounds": { "ammonia": { - "amount": 300000, + "amount": 200000, "density": 0.00002, "dissolved": 0.0 }, "glucose": { - "amount": 350000, + "amount": 250000, "density": 0.00002, "dissolved": 0.0 }, "phosphates": { - "amount": 300000, + "amount": 200000, "density": 0.00002, "dissolved": 0.0 }, "hydrogensulfide": { - "amount": 325000, + "amount": 225000, "density": 0.00002, "dissolved": 0.0 }, @@ -774,12 +929,12 @@ "chunkScale": 1.0, "mass": 100, "size": 2, - "ventAmount": 3.0, + "ventAmount": 6.0, "damages": 0.0, "deleteOnTouch": false, "compounds": { "iron": { - "amount": 100.0 + "amount": 200.0 } } }, @@ -792,12 +947,12 @@ "chunkScale": 1.0, "mass": 100, "size": 100, - "ventAmount": 10.0, + "ventAmount": 20.0, "damages": 0.0, "deleteOnTouch": false, "compounds": { "iron": { - "amount": 30000.0 + "amount": 60000.0 } } } @@ -806,25 +961,25 @@ "averageTemperature": 17, "compounds": { "ammonia": { - "amount": 300000, + "amount": 200000, "density": 0.00002, "dissolved": 0.0 }, "glucose": { - "amount": 350000, + "amount": 250000, "density": 0.00002, "dissolved": 0.0 }, "phosphates": { - "amount": 300000, + "amount": 200000, "density": 0.00002, "dissolved": 0.0 }, "hydrogensulfide": { - "amount": 325000, + "amount": 225000, "density": 0.00002, "dissolved": 0.0 }, @@ -901,12 +1056,12 @@ "chunkScale": 1.0, "mass": 100, "size": 2, - "ventAmount": 3.0, + "ventAmount": 6.0, "damages": 0.0, "deleteOnTouch": false, "compounds": { "iron": { - "amount": 100.0 + "amount": 200.0 } } }, @@ -919,12 +1074,12 @@ "chunkScale": 1.0, "mass": 100, "size": 100, - "ventAmount": 10.0, + "ventAmount": 20.0, "damages": 0.0, "deleteOnTouch": false, "compounds": { "iron": { - "amount": 30000.0 + "amount": 60000.0 } } } @@ -933,25 +1088,25 @@ "averageTemperature": 23, "compounds": { "ammonia": { - "amount": 300000, + "amount": 200000, "density": 0.00002, "dissolved": 0.0 }, "glucose": { - "amount": 350000, + "amount": 250000, "density": 0.00002, "dissolved": 0.0 }, "phosphates": { - "amount": 300000, + "amount": 200000, "density": 0.00002, "dissolved": 0.0 }, "hydrogensulfide": { - "amount": 325000, + "amount": 225000, "density": 0.00002, "dissolved": 0.0 }, @@ -1028,12 +1183,12 @@ "chunkScale": 1.0, "mass": 100, "size": 2, - "ventAmount": 3.0, + "ventAmount": 6.0, "damages": 0.0, "deleteOnTouch": false, "compounds": { "iron": { - "amount": 100.0 + "amount": 200.0 } } }, @@ -1076,12 +1231,12 @@ "chunkScale": 1.0, "mass": 100, "size": 100, - "ventAmount": 10.0, + "ventAmount": 20.0, "damages": 0.0, "deleteOnTouch": false, "compounds": { "iron": { - "amount": 30000.0 + "amount": 60000.0 } } } @@ -1091,25 +1246,25 @@ "compounds": { "ammonia": { - "amount": 300000, + "amount": 200000, "density": 0.00002, "dissolved": 0.0 }, "glucose": { - "amount": 350000, + "amount": 250000, "density": 0.00002, "dissolved": 0.0 }, "phosphates": { - "amount": 300000, + "amount": 200000, "density": 0.00002, "dissolved": 0.0 }, "hydrogensulfide": { - "amount": 325000, + "amount": 225000, "density": 0.00002, "dissolved": 0.0 }, @@ -1186,12 +1341,12 @@ "chunkScale": 1.0, "mass": 100, "size": 2, - "ventAmount": 3.0, + "ventAmount": 6.0, "damages": 0.0, "deleteOnTouch": false, "compounds": { "iron": { - "amount": 100.0 + "amount": 200.0 } } }, @@ -1204,12 +1359,12 @@ "chunkScale": 1.0, "mass": 100, "size": 100, - "ventAmount": 10.0, + "ventAmount": 20.0, "damages": 0.0, "deleteOnTouch": false, "compounds": { "iron": { - "amount": 30000.0 + "amount": 60000.0 } } } @@ -1219,25 +1374,25 @@ "compounds": { "ammonia": { - "amount": 300000, + "amount": 200000, "density": 0.00002, "dissolved": 0.0 }, "glucose": { - "amount": 350000, + "amount": 250000, "density": 0.00002, "dissolved": 0.0 }, "phosphates": { - "amount": 300000, + "amount": 200000, "density": 0.00002, "dissolved": 0.0 }, "hydrogensulfide": { - "amount": 325000, + "amount": 225000, "density": 0.00002, "dissolved": 0.0 }, @@ -1314,12 +1469,12 @@ "chunkScale": 1.0, "mass": 100, "size": 2, - "ventAmount": 3.0, + "ventAmount": 6.0, "damages": 0.0, "deleteOnTouch": false, "compounds": { "iron": { - "amount": 100.0 + "amount": 200.0 } } }, @@ -1332,18 +1487,18 @@ "chunkScale": 1.0, "mass": 100, "size": 100, - "ventAmount": 10.0, + "ventAmount": 20.0, "damages": 0.0, "deleteOnTouch": false, "compounds": { "iron": { - "amount": 30000.0 + "amount": 60000.0 } } }, "marineSnow": { "name": "Marine snow", - "meshes": ["nucleus", "chloroplast", "oxytoxy","flagellum", + "meshes": ["oxytoxy_gland", "nucleus", "chloroplast", "oxytoxy","flagellum", "chemoplast","nitrogenplastid","metabolosome","chromatophores", "vacuole","mitochondrion","chemoproteins","nitrogenase","rusticyanin"], "density": 0.00004, @@ -1375,25 +1530,25 @@ "averageTemperature": 4, "compounds": { "ammonia": { - "amount": 300000, + "amount": 200000, "density": 0.00002, "dissolved": 0.0 }, "glucose": { - "amount": 350000, + "amount": 250000, "density": 0.00002, "dissolved": 0.0 }, "phosphates": { - "amount": 300000, + "amount": 200000, "density": 0.00002, "dissolved": 0.0 }, "hydrogensulfide": { - "amount": 325000, + "amount": 225000, "density": 0.00002, "dissolved": 0.0 }, diff --git a/scripts/gui/microbe_editor.mjs b/scripts/gui/microbe_editor.mjs index a63c1e7eb52..ffba89c5123 100644 --- a/scripts/gui/microbe_editor.mjs +++ b/scripts/gui/microbe_editor.mjs @@ -72,6 +72,10 @@ const organelleSelectionElements = [ element: document.getElementById("addNitrogenase"), organelle: "nitrogenase" }, + { + element: document.getElementById("addToxinProtein"), + organelle: "oxytoxyProteins" + }, { element: document.getElementById("addNucleus"), organelle: "nucleus" diff --git a/scripts/gui/microbe_hud.mjs b/scripts/gui/microbe_hud.mjs index f50ae958731..ff29ba110dd 100644 --- a/scripts/gui/microbe_hud.mjs +++ b/scripts/gui/microbe_hud.mjs @@ -355,6 +355,8 @@ function onExitToMenuClicked() { document.getElementById("extinctionBody").style.display = "none"; document.getElementById("extinctionContainer").style.display = "none"; hideWinText(); + // Gotta reset this + wonOnce=false; Thrive.exitToMenuClicked(); } else { @@ -441,7 +443,7 @@ function checkExtinction(population){ } function checkGeneration (generation, population){ - if(generation >= 15 && population >= 200 && wonOnce == false){ + if(generation >= 20 && population >= 500 && 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 17202e5a357..020882f8215 100644 --- a/scripts/gui/thrive_gui.html +++ b/scripts/gui/thrive_gui.html @@ -139,7 +139,7 @@
YOU HAVE THRIVED! - Congratulation- a winner is y... who am I kidding, you have thrived! You have won in the 0.4.1 build Good job, you may continue playing after this screen closes if you wish, or start a new game in a new world. + Congratulation- a winner is y... who am I kidding, you have thrived! You have won in the 0.4.2 dev build Good job, you may continue playing after this screen closes if you wish, or start a new game in a new world.
@@ -326,7 +326,7 @@

For this Release if your population (top tab) drops to zero you go extinct.
-But if you survive for fifteen generations with 200 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 500 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.

@@ -375,7 +375,7 @@ +
Cytoplasm
22 MP
-  
 30

+  
 22

Turns Glucose into ATP .

Fermentation
0.06 5.00 /second

@@ -389,10 +389,10 @@ Cytoplasm -
Cytoplasm
30 MP
PROKARYOTIC STRUCTURES
- +
-
 45

@@ -438,7 +438,7 @@  
 45



Turns Hydrogen Sulfide into Glucose . Rate scales with concentration of Carbon Dioxide  . Also turns Glucose into ATP .

Hydrogen Sulfide Chemosynthesis
- 0.21 0.21 /second @ 0.09%

+ 1.0 1.0 /second @ 0.09%

Fermentation
0.13 5.00 /second

+1 Storage
@@ -453,8 +453,8 @@ Chemosynth-
esizing Proteins
Chemosynthesizing Proteins
45 MP
- + + +
 45

@@ -490,6 +490,22 @@
Nitrogenase
55 MP
+ +  
 55

+ Turns ATP into Oxytoxy . Can release toxins by pressing E. Rate scales with concentration of Oxygen  .

+ Agent Synthesis
+ 5.00 0.5 /second @ 21.00%

+ Fermentation
+ 0.13 5.00 /second

+ +4 Storage
+ +1 Osmoregulation Cost


+ A modified metabolosome responsible for the production of a primitive form of the toxic agent Oxytoxy NT. +
+ + Oxytoxisome + +
Oxytoxisome
55 MP
EXTERNAL ORGANELLES
@@ -724,7 +740,7 @@ enter the Microbe Editor, where you can make changes to your species (by adding, moving, or removing organelles) to increase your species' success.

- Each visit to the editor in the Microbe Stage Represents 200 million years of evolution
+ Each visit to the editor in the Microbe Stage Represents 150 million years of evolution
Each generation, you have 100 mutation points to spend, and each change (or mutation) will cost a certain amount of that MP, removing costs mutation points aswell as adding.

You can rotate your organelles, with A and D

diff --git a/scripts/microbe_stage/microbe_editor/microbe_editor.as b/scripts/microbe_stage/microbe_editor/microbe_editor.as index 64573f7dbf7..0d7a0714b9d 100644 --- a/scripts/microbe_stage/microbe_editor/microbe_editor.as +++ b/scripts/microbe_stage/microbe_editor/microbe_editor.as @@ -65,6 +65,7 @@ class MicrobeEditor{ {"chemoSynthisizingProteins", PlacementFunctionType(this.addOrganelle)}, {"rusticyanin", PlacementFunctionType(this.addOrganelle)}, {"nitrogenase", PlacementFunctionType(this.addOrganelle)}, + {"oxytoxyProteins", PlacementFunctionType(this.addOrganelle)}, {"remove", PlacementFunctionType(this.removeOrganelle)} }; } diff --git a/scripts/microbe_stage/organelle_table.as b/scripts/microbe_stage/organelle_table.as index f986b2ec663..f26d10ad068 100644 --- a/scripts/microbe_stage/organelle_table.as +++ b/scripts/microbe_stage/organelle_table.as @@ -293,7 +293,7 @@ void setupOrganelles(){ cytoplasmParameters.mesh = ""; //it's an empty hex cytoplasmParameters.chanceToCreate = 1; cytoplasmParameters.prokaryoteChance = 1; - cytoplasmParameters.mpCost = 30; + cytoplasmParameters.mpCost = 22; cytoplasmParameters.initialComposition = { {"phosphates", 2}, {"ammonia", 2} @@ -347,7 +347,7 @@ void setupOrganelles(){ oxytoxyParameters.mass = 0.3; oxytoxyParameters.gene = "T"; - oxytoxyParameters.mesh = "oxytoxy.mesh"; + oxytoxyParameters.mesh = "oxytoxy_gland.mesh"; oxytoxyParameters.chanceToCreate = 1; oxytoxyParameters.prokaryoteChance = 0; oxytoxyParameters.mpCost = 70; @@ -575,20 +575,20 @@ void setupOrganelles(){ oxytoxyProtein.mass = 0.1; oxytoxyProtein.gene = "t"; oxytoxyProtein.mesh = "oxytoxy.mesh"; - oxytoxyProtein.chanceToCreate = 0; + oxytoxyProtein.chanceToCreate = 1; oxytoxyProtein.prokaryoteChance = 1; - oxytoxyProtein.mpCost = 15; + oxytoxyProtein.mpCost = 55; oxytoxyProtein.initialComposition = { {"phosphates", 1}, {"ammonia", 1} }; oxytoxyProtein.components = { - agentVacuoleFactory("oxytoxy", "oxytoxySynthesis"), - storageOrganelleFactory(2.0f), + agentVacuoleFactory("oxytoxy", "bacterial_oxytoxySynthesis"), + storageOrganelleFactory(4.0f), processorOrganelleFactory(1.0f) }; oxytoxyProtein.processes = { - TweakedProcess("oxytoxySynthesis", 1), + TweakedProcess("bacterial_oxytoxySynthesis", 1), TweakedProcess("glycolosis", 1) }; oxytoxyProtein.hexes = { diff --git a/src/microbe_stage/compound_absorber_system.cpp b/src/microbe_stage/compound_absorber_system.cpp index c293fdafb4a..5f274c1d624 100644 --- a/src/microbe_stage/compound_absorber_system.cpp +++ b/src/microbe_stage/compound_absorber_system.cpp @@ -311,7 +311,7 @@ void // " at (cloud local): " + std::to_string(x) + ", " + // std::to_string(y) + " amount: " + std::to_string(amount)); absorber.m_absorbedCompounds[id] += - compoundCloud->takeCompound(id, x, y, .2) / 20000.0f; + compoundCloud->takeCompound(id, x, y, .4) / 80000.0f; } // Absorb .2 (third parameter) of the available // compounds. From 92a74cb608b9931b5cdb3002a546b1a827175438 Mon Sep 17 00:00:00 2001 From: 1n48yg <37918520+1n48yg@users.noreply.github.com> Date: Fri, 3 May 2019 23:34:51 -0700 Subject: [PATCH 4/8] Cleaned up population GUI bar - Made the population text a bit indented, (that Oliveriver requested like 6 months ago but for some reason I forgot to do it) - Extended the population bar out a bit because before the bar always felt cut off at the end --- scripts/gui/thrive_style.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/gui/thrive_style.css b/scripts/gui/thrive_style.css index cacc4da1557..1bc8710b89b 100644 --- a/scripts/gui/thrive_style.css +++ b/scripts/gui/thrive_style.css @@ -699,12 +699,14 @@ video { #populationText { position: absolute; height: 40px; - width: 150px; + width: 160px; top: 0; left: 960px; font-size: 10pt; line-height: 40px; background-image: url("../../Textures/gui/bevel/LongTwoNormal.png"); + background-repeat: no-repeat; + text-indent: 10px; } #populationCount { @@ -715,6 +717,7 @@ video { left: 1040px; font-size: 10pt; line-height: 40px; + text-indent: 10px; } #oxygenTab { From 66b5bf0005a5d6b7cc1595e63c3d28a3d42f796b Mon Sep 17 00:00:00 2001 From: Untrustedlife Date: Sat, 4 May 2019 17:50:09 -0500 Subject: [PATCH 5/8] Added new oxytoxy_fluid model, also shooting agents now take sinto account whther you area bacteria or a eukaryote improved material for toxin Fixed material all oxytoxy things now show up under the membrane ice crystals no longer try to play damage sound effect --- materials/oxytoxy.material | 2 +- materials/oxytoxy_fluid.material | 34 +++++++++++++++++++ materials/oxytoxy_gland.material | 2 +- .../MicrobeStage/Biomes.json | 22 ++++++------ scripts/gui/microbe_hud.mjs | 3 +- scripts/microbe_stage/agents.as | 2 +- scripts/microbe_stage/microbe_operations.as | 8 +++-- scripts/microbe_stage/setup.as | 4 +-- 8 files changed, 58 insertions(+), 19 deletions(-) create mode 100644 materials/oxytoxy_fluid.material diff --git a/materials/oxytoxy.material b/materials/oxytoxy.material index e6d827865e4..21c84057ba0 100644 --- a/materials/oxytoxy.material +++ b/materials/oxytoxy.material @@ -9,7 +9,7 @@ material oxytoxy // lighting off scene_blend alpha_blend - depth_write on + depth_write off point_sprites on vertex_program_ref Organelle_VS diff --git a/materials/oxytoxy_fluid.material b/materials/oxytoxy_fluid.material new file mode 100644 index 00000000000..0a9201d397d --- /dev/null +++ b/materials/oxytoxy_fluid.material @@ -0,0 +1,34 @@ +material oxytoxy_fluid +{ + receive_shadows on + + technique + { + pass oxytoxy_fluid + { + //lighting on + scene_blend alpha_blend + depth_write on + + vertex_program_ref Organelle_VS + { + param_named_auto worldViewProj worldviewproj_matrix + param_named_auto time time_0_2pi 20 + param_named size float 0.05 + param_named maxRot float 15 + } + fragment_program_ref Organelle_PS + { + param_named tex int 0 + param_named_auto organelleColour custom 1 + } + + texture_unit + { + texture oxytoxy_fluid.png gamma + alpha_op_ex modulate src_manual src_texture 1.0 + colour_op_ex modulate src_manual src_texture 1.0 1.0 1.0 + } + } + } +} diff --git a/materials/oxytoxy_gland.material b/materials/oxytoxy_gland.material index 9ec124d054b..3eedac5512f 100644 --- a/materials/oxytoxy_gland.material +++ b/materials/oxytoxy_gland.material @@ -9,7 +9,7 @@ material oxytoxy_gland // lighting off scene_blend alpha_blend - depth_write on + depth_write off point_sprites on vertex_program_ref Organelle_VS diff --git a/scripts/SimulationParameters/MicrobeStage/Biomes.json b/scripts/SimulationParameters/MicrobeStage/Biomes.json index b4852417e5d..951a07d195e 100644 --- a/scripts/SimulationParameters/MicrobeStage/Biomes.json +++ b/scripts/SimulationParameters/MicrobeStage/Biomes.json @@ -29,7 +29,7 @@ "chunks":{ "floatingToxin": { "name": "Floating Hazard", - "meshes": ["oxytoxy"], + "meshes": ["oxytoxy_fluid"], "density": 0.00002, "dissolves": false, "radius": 1, @@ -157,7 +157,7 @@ "chunks":{ "floatingToxin": { "name": "Floating Hazard", - "meshes": ["oxytoxy"], + "meshes": ["oxytoxy_fluid"], "density": 0.00002, "dissolves": false, "radius": 1, @@ -313,7 +313,7 @@ "chunks":{ "floatingToxin": { "name": "Floating Hazard", - "meshes": ["oxytoxy"], + "meshes": ["oxytoxy_fluid"], "density": 0.00002, "dissolves": false, "radius": 1, @@ -440,7 +440,7 @@ "chunks":{ "floatingToxin": { "name": "Floating Hazard", - "meshes": ["oxytoxy"], + "meshes": ["oxytoxy_fluid"], "density": 0.000015, "dissolves": false, "radius": 1, @@ -595,7 +595,7 @@ "chunks":{ "floatingToxin": { "name": "Floating Hazard", - "meshes": ["oxytoxy"], + "meshes": ["oxytoxy_fluid"], "density": 0.00002, "dissolves": false, "radius": 1, @@ -751,7 +751,7 @@ "chunks":{ "floatingToxin": { "name": "Floating Hazard", - "meshes": ["oxytoxy"], + "meshes": ["oxytoxy_fluid"], "density": 0.00002, "dissolves": false, "radius": 1, @@ -907,7 +907,7 @@ "chunks":{ "floatingToxin": { "name": "Floating Hazard", - "meshes": ["oxytoxy"], + "meshes": ["oxytoxy_fluid"], "density": 0.00002, "dissolves": false, "radius": 1, @@ -1034,7 +1034,7 @@ "chunks":{ "floatingToxin": { "name": "Floating Hazard", - "meshes": ["oxytoxy"], + "meshes": ["oxytoxy_fluid"], "density": 0.0002, "dissolves": false, "radius": 1, @@ -1161,7 +1161,7 @@ "chunks":{ "floatingToxin": { "name": "Floating Hazard", - "meshes": ["oxytoxy"], + "meshes": ["oxytoxy_fluid"], "density": 0.00002, "dissolves": false, "radius": 1, @@ -1319,7 +1319,7 @@ "chunks":{ "floatingToxin": { "name": "Floating Hazard", - "meshes": ["oxytoxy"], + "meshes": ["oxytoxy_fluid"], "density": 0.00002, "dissolves": false, "radius": 1, @@ -1447,7 +1447,7 @@ "chunks":{ "floatingToxin": { "name": "Floating Hazard", - "meshes": ["oxytoxy"], + "meshes": ["oxytoxy_fluid"], "density": 0.00002, "dissolves": false, "radius": 1, diff --git a/scripts/gui/microbe_hud.mjs b/scripts/gui/microbe_hud.mjs index ff29ba110dd..4cdf037fbbb 100644 --- a/scripts/gui/microbe_hud.mjs +++ b/scripts/gui/microbe_hud.mjs @@ -355,8 +355,9 @@ function onExitToMenuClicked() { document.getElementById("extinctionBody").style.display = "none"; document.getElementById("extinctionContainer").style.display = "none"; hideWinText(); + // Gotta reset this - wonOnce=false; + wonOnce = false; Thrive.exitToMenuClicked(); } else { diff --git a/scripts/microbe_stage/agents.as b/scripts/microbe_stage/agents.as index 32dc4c2bd8f..b34a58aef2f 100644 --- a/scripts/microbe_stage/agents.as +++ b/scripts/microbe_stage/agents.as @@ -34,7 +34,7 @@ class OxytoxyEffect : AgentEffect{ const dictionary AGENTS = { - {"oxytoxy", Agent("OxyToxy NT", 1, "oxytoxy.mesh", 0.3, OxytoxyEffect())} + {"oxytoxy", Agent("OxyToxy NT", 1, "oxytoxy_fluid.mesh", 0.3, OxytoxyEffect())} }; diff --git a/scripts/microbe_stage/microbe_operations.as b/scripts/microbe_stage/microbe_operations.as index c3eb65a422a..e4ef6bf3abe 100644 --- a/scripts/microbe_stage/microbe_operations.as +++ b/scripts/microbe_stage/microbe_operations.as @@ -728,10 +728,14 @@ void emitAgent(CellStageWorld@ world, ObjectID microbeEntity, CompoundId compoun auto finalAngle = (angle + microbeAngle) % 360; auto s = sin(finalAngle/180*PI); auto c = cos(finalAngle/180*PI); + //Bacteria need to be able to shoot closer to themselves + auto ourHex = HEX_SIZE; + if (microbeComponent.isBacteria) + ourHex/=2; // Membrane coords to world coords // Plus bunch more space in world coordinates like we added before with maxr but cleaner - auto xnew = -(membraneCoords.x) * c + (membraneCoords.z+maxR*HEX_SIZE) * s; - auto ynew = (membraneCoords.x)* s + (membraneCoords.z+maxR*HEX_SIZE) * c; + auto xnew = -(membraneCoords.x) * c + (membraneCoords.z+maxR*ourHex) * s; + auto ynew = (membraneCoords.x)* s + (membraneCoords.z+maxR*ourHex) * c; // Find the direction the microbe is facing auto vec = ( microbeComponent.facingTargetPoint - cellPosition._Position); auto direction = vec.Normalize(); diff --git a/scripts/microbe_stage/setup.as b/scripts/microbe_stage/setup.as index 233a8b95617..c70f8b58e89 100644 --- a/scripts/microbe_stage/setup.as +++ b/scripts/microbe_stage/setup.as @@ -374,7 +374,7 @@ void cellHitDamageChunk(GameWorld@ world, ObjectID firstEntity, ObjectID secondE disappear=true; } else if (!damage.getDeletes() && !microbeComponent.dead){ - MicrobeOperations::damage(asCellWorld, cellEntity, double(damage.getDamage()), "toxin"); + MicrobeOperations::damage(asCellWorld, cellEntity, double(damage.getDamage()), "chunk"); } } @@ -646,7 +646,7 @@ void createAgentCloud(CellStageWorld@ world, CompoundId compoundId, body.SetVelocity(normalizedDirection * AGENT_EMISSION_VELOCITY); rigidBody.JumpTo(position); auto sceneNode = world.Create_RenderNode(agentEntity); - auto model = world.Create_Model(agentEntity, sceneNode.Node, "oxytoxy.mesh"); + auto model = world.Create_Model(agentEntity, sceneNode.Node, "oxytoxy_fluid.mesh"); // Need to set the tint model.GraphicalObject.setCustomParameter(1, Ogre::Vector4(1, 1, 1, 1)); From 47be487625fcd7a12d4fba4071148a75801dc959 Mon Sep 17 00:00:00 2001 From: Untrustedlife Date: Sun, 5 May 2019 00:27:49 -0500 Subject: [PATCH 6/8] Species can now add up to 6 new organelles when they evolve (Though usually they add from 0-2, i listed the probabilities) increased chance of new organelles increased chance of organelles being replaced. Changed max pop size so species split and go extinct more frequently Cleaned up name gen code to make more sense and to creat emor epronouncable names higher chance of new genus's emerging Auto evo steps now happen outside of editor at double the frequncy so if the player is going slow they may in fact become prey. This encourage sthe player to actually compete. In my test game almost every single species had its own genus so this creates proper geneological lines aswell. changed name mutator to avoid ridiculousness even more (Changing Th to stuff like Tb(which is unprouncable)), changed new name chances, etc. commented out logs 400 pop to win now Got rid of species level processor component replaced with rebuildProcessList fixed bug where cells could engulf each other from a mile away. --- scripts/gui/microbe_hud.mjs | 2 +- scripts/gui/thrive_gui.html | 2 +- scripts/microbe_stage/configs.as | 9 +- scripts/microbe_stage/microbe.as | 9 +- scripts/microbe_stage/microbe_operations.as | 31 +-- scripts/microbe_stage/procedural_microbes.as | 20 ++ scripts/microbe_stage/setup.as | 5 +- scripts/microbe_stage/species_system.as | 251 ++++++++----------- 8 files changed, 147 insertions(+), 182 deletions(-) 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; } From 62d5446860809fd52d4dff6fa3b6a9ed2d9c54ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henri=20Hyyryl=C3=A4inen?= Date: Thu, 9 May 2019 19:36:35 +0300 Subject: [PATCH 7/8] Restored _organelle to private, there's a reason it's private to stop people from modifying it --- scripts/microbe_stage/microbe_editor/microbe_editor.as | 2 +- scripts/microbe_stage/organelle.as | 2 +- scripts/microbe_stage/species_system.as | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/microbe_stage/microbe_editor/microbe_editor.as b/scripts/microbe_stage/microbe_editor/microbe_editor.as index 0d7a0714b9d..4161e86c6e4 100644 --- a/scripts/microbe_stage/microbe_editor/microbe_editor.as +++ b/scripts/microbe_stage/microbe_editor/microbe_editor.as @@ -130,7 +130,7 @@ class MicrobeEditor{ for(uint i = 0; i < templateOrganelles.length(); ++i){ auto organelle = cast(templateOrganelles[i]); editedMicrobe.insertLast(organelle); - playerSpecies.stringCode+=organelle._organelle.gene; + playerSpecies.stringCode += organelle.organelle.gene; // This will always be added after each organelle so its safe to assume its there playerSpecies.stringCode+=","+organelle.q+","+ organelle.r+","+ diff --git a/scripts/microbe_stage/organelle.as b/scripts/microbe_stage/organelle.as index f7d18abcf39..76c49fdde5d 100644 --- a/scripts/microbe_stage/organelle.as +++ b/scripts/microbe_stage/organelle.as @@ -873,7 +873,7 @@ class PlacedOrganelle : SpeciesStoredOrganelleType{ } } - Organelle@ _organelle; + private Organelle@ _organelle; // q and r are radial coordinates instead of cartesian // Could use the class AxialCoordinates here diff --git a/scripts/microbe_stage/species_system.as b/scripts/microbe_stage/species_system.as index 78360f6556a..b0d0dc0ccd0 100644 --- a/scripts/microbe_stage/species_system.as +++ b/scripts/microbe_stage/species_system.as @@ -1208,7 +1208,7 @@ ObjectID createSpecies(CellStageWorld@ world, const string &in name, const strin for(uint i = 0; i < organelles.length(); ++i){ auto organelle = cast(organelles[i]); speciesComponent.organelles.insertLast(organelle); - speciesComponent.stringCode+=organelle._organelle.gene; + speciesComponent.stringCode += organelle.organelle.gene; // This will always be added after each organelle so its safe to assume its there speciesComponent.stringCode+=","+organelle.q+","+ organelle.r+","+ From 24aa954c32163ddddc573b7703a18abe79ea9aa6 Mon Sep 17 00:00:00 2001 From: Untrustedlife Date: Sat, 11 May 2019 12:32:25 -0500 Subject: [PATCH 8/8] added a bunch of const and const & in in various places especially in getStringCodePosition and isValidPlacement Added another const, got rid of a log --- scripts/microbe_stage/procedural_microbes.as | 22 ++++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/scripts/microbe_stage/procedural_microbes.as b/scripts/microbe_stage/procedural_microbes.as index 7a5e26bf76e..2f90cccfe29 100644 --- a/scripts/microbe_stage/procedural_microbes.as +++ b/scripts/microbe_stage/procedural_microbes.as @@ -78,11 +78,11 @@ string getRandomLetter(bool isBacteria){ // Checks whether an organelle in a certain position would fit within a list of other organelles. bool isValidPlacement(const string &in organelleName, int q, int r, int rotation, - array@ organelleList + const array@ &in organelleList ) { // this is now slightly less hacky but it could be btter - auto organelleHexes = getOrganelleDefinition(organelleName).getRotatedHexes(rotation); + const auto organelleHexes = getOrganelleDefinition(organelleName).getRotatedHexes(rotation); for(uint i = 0; i < organelleList.length(); ++i){ @@ -119,7 +119,7 @@ OrganelleTemplatePlaced@ getRealisticPosition(const string &in organelleName, int q = 0; int r = 0; - auto organelleShuffledArray = organelleList; + array@ organelleShuffledArray = organelleList; // Shuffle the Array to make sure its not always placing at the same part of the cell organelleShuffledArray.sort( function(a,b) { @@ -173,7 +173,7 @@ OrganelleTemplatePlaced@ getRealisticPosition(const string &in organelleName, // This function takes in a positioning block from the string code and a name // and returns an organelle with the correct position info -OrganelleTemplatePlaced@ getStringCodePosition(const string &in organelleName, string code){ +OrganelleTemplatePlaced@ getStringCodePosition(const string &in organelleName, const string &in code){ //LOG_INFO(code); array@ chromArray = code.split(","); @@ -202,7 +202,7 @@ array@ positionOrganelles(const string &in stringCode){ //LOG_INFO("DEBUG: positionOrganelles stringCode: " + stringCode); array@ result = array(); - array@ chromArray = stringCode.split("|"); + const array@ chromArray = stringCode.split("|"); for(uint i = 0; i < chromArray.length(); ++i){ OrganelleTemplatePlaced@ pos; string geneCode = chromArray[i]; @@ -244,8 +244,8 @@ string translateOrganelleToGene(OrganelleTemplatePlaced@ ourOrganelle){ string mutateMicrobe(const string &in stringCode, bool isBacteria) { array@ chromArray = stringCode.split("|"); - array@ modifiedArray = chromArray; - LOG_INFO(chromArray[0]); + auto modifiedArray = chromArray; + //LOG_INFO(chromArray[0]); string completeString = ""; // Delete or replace an organelle randomly @@ -284,10 +284,10 @@ string mutateMicrobe(const string &in stringCode, bool isBacteria) // 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); + const auto organelleList = positionOrganelles(completeString); const auto letter = getRandomLetter(isBacteria); string name = string(organelleLetters[letter]); - string returnedGenome = translateOrganelleToGene(getRealisticPosition(name,organelleList)); + const string returnedGenome = translateOrganelleToGene(getRealisticPosition(name,organelleList)); //LOG_INFO("Adding"); //LOG_INFO("chromosomes:"+returnedGenome); completeString+="|"+returnedGenome; @@ -302,10 +302,10 @@ string mutateMicrobe(const string &in stringCode, bool isBacteria) 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 organelleList = positionOrganelles(completeString); const auto letter = getRandomLetter(isBacteria); string name = string(organelleLetters[letter]); - string returnedGenome = translateOrganelleToGene(getRealisticPosition(name,organelleList)); + const string returnedGenome = translateOrganelleToGene(getRealisticPosition(name,organelleList)); //LOG_INFO("Adding"); //LOG_INFO("chromosomes:"+returnedGenome); completeString+="|"+returnedGenome;