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.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 new file mode 100644 index 00000000000..3eedac5512f --- /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 off + 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..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, @@ -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 }, @@ -157,7 +157,7 @@ "chunks":{ "floatingToxin": { "name": "Floating Hazard", - "meshes": ["oxytoxy"], + "meshes": ["oxytoxy_fluid"], "density": 0.00002, "dissolves": false, "radius": 1, @@ -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 }, @@ -313,7 +313,7 @@ "chunks":{ "floatingToxin": { "name": "Floating Hazard", - "meshes": ["oxytoxy"], + "meshes": ["oxytoxy_fluid"], "density": 0.00002, "dissolves": false, "radius": 1, @@ -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_fluid"], + "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": { @@ -440,7 +595,7 @@ "chunks":{ "floatingToxin": { "name": "Floating Hazard", - "meshes": ["oxytoxy"], + "meshes": ["oxytoxy_fluid"], "density": 0.00002, "dissolves": false, "radius": 1, @@ -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 }, @@ -596,7 +751,7 @@ "chunks":{ "floatingToxin": { "name": "Floating Hazard", - "meshes": ["oxytoxy"], + "meshes": ["oxytoxy_fluid"], "density": 0.00002, "dissolves": false, "radius": 1, @@ -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 }, @@ -752,7 +907,7 @@ "chunks":{ "floatingToxin": { "name": "Floating Hazard", - "meshes": ["oxytoxy"], + "meshes": ["oxytoxy_fluid"], "density": 0.00002, "dissolves": false, "radius": 1, @@ -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 }, @@ -879,7 +1034,7 @@ "chunks":{ "floatingToxin": { "name": "Floating Hazard", - "meshes": ["oxytoxy"], + "meshes": ["oxytoxy_fluid"], "density": 0.0002, "dissolves": false, "radius": 1, @@ -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 }, @@ -1006,7 +1161,7 @@ "chunks":{ "floatingToxin": { "name": "Floating Hazard", - "meshes": ["oxytoxy"], + "meshes": ["oxytoxy_fluid"], "density": 0.00002, "dissolves": false, "radius": 1, @@ -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 }, @@ -1164,7 +1319,7 @@ "chunks":{ "floatingToxin": { "name": "Floating Hazard", - "meshes": ["oxytoxy"], + "meshes": ["oxytoxy_fluid"], "density": 0.00002, "dissolves": false, "radius": 1, @@ -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 }, @@ -1292,7 +1447,7 @@ "chunks":{ "floatingToxin": { "name": "Floating Hazard", - "meshes": ["oxytoxy"], + "meshes": ["oxytoxy_fluid"], "density": 0.00002, "dissolves": false, "radius": 1, @@ -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/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/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..a1924640dfa 100644 --- a/scripts/gui/microbe_hud.mjs +++ b/scripts/gui/microbe_hud.mjs @@ -355,6 +355,9 @@ 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 +444,7 @@ function checkExtinction(population){ } function checkGeneration (generation, population){ - if(generation >= 15 && population >= 200 && 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 17202e5a357..9bde8728e47 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 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.

@@ -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/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 { 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/configs.as b/scripts/microbe_stage/configs.as index 22f36a593e7..3930895c47a 100644 --- a/scripts/microbe_stage/configs.as +++ b/scripts/microbe_stage/configs.as @@ -23,26 +23,35 @@ 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; // 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.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; + // Spawn Radius const auto MICROBE_SPAWN_RADIUS = 150; const auto BACTERIA_SPAWN_RADIUS = 150; @@ -101,8 +110,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; @@ -312,7 +324,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 +334,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 +386,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.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_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 66c727a155d..4161e86c6e4 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)} }; } @@ -125,15 +126,29 @@ 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"); // 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..9b5902f25b5 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(); @@ -902,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, @@ -954,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 @@ -1047,30 +1033,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); @@ -1107,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"); @@ -1128,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); // ------------------------------------ // @@ -1135,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/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/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/scripts/microbe_stage/procedural_microbes.as b/scripts/microbe_stage/procedural_microbes.as index 0b1206d4cc0..2f90cccfe29 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 + const array@ &in organelleList ) { - // This is super hacky :/ - // this is now slightly less hacky - auto organelleHexes = getOrganelleDefinition(organelleName).getRotatedHexes(rotation); + + // this is now slightly less hacky but it could be btter + const 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,206 @@ 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); - } - } + array@ 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, const string &in 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; + const 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("|"); + auto 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,"|"); + + // 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){ + const auto organelleList = positionOrganelles(completeString); + const auto letter = getRandomLetter(isBacteria); + string name = string(organelleLetters[letter]); + const string returnedGenome = translateOrganelleToGene(getRealisticPosition(name,organelleList)); + //LOG_INFO("Adding"); + //LOG_INFO("chromosomes:"+returnedGenome); + 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){ + const auto organelleList = positionOrganelles(completeString); + const auto letter = getRandomLetter(isBacteria); + string name = string(organelleLetters[letter]); + const 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 137d94c36d8..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 @@ -374,7 +371,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 +643,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)); @@ -663,7 +660,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..b0d0dc0ccd0 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() @@ -253,172 +323,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,43 +332,44 @@ 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; - + 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, 100) < MUTATION_WORD_EDIT){ epithet = mutateWord(parent.epithet); } else { epithet = generateNameSection(); } genus = parent.genus; - + colour=parent.colour; mutateBehavior(parent); // Make sure not over or under our scales 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()); + 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) <= MUTATION_CHANGE_GENUS) { LOG_INFO("New Genus"); // We can do more fun stuff here later - if (GetEngine().GetRandom().GetNumber(0, 10) < 8){ + if (GetEngine().GetRandom().GetNumber(0, 100) < MUTATION_WORD_EDIT){ genus = mutateWord(parent.genus); } else { @@ -477,11 +382,11 @@ 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.stringCode = mutateMicrobe(parent.stringCode,false); + + + generateMembranes(parent); - this.speciesMembraneType = parent.speciesMembraneType; commonConstructor(world); @@ -494,6 +399,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); @@ -502,21 +429,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); @@ -534,7 +447,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) { @@ -742,97 +657,13 @@ 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; + colour=parent.colour; //Mutate the epithet - if (GetEngine().GetRandom().GetNumber(0, 10) < 8){ + if (GetEngine().GetRandom().GetNumber(0, 100) < MUTATION_WORD_EDIT){ epithet = mutateWord(parent.epithet); } else { @@ -846,21 +677,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) <= 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) < 8){ + if (GetEngine().GetRandom().GetNumber(0, 100) < MUTATION_WORD_EDIT){ genus = mutateWord(parent.genus); } else { @@ -874,11 +706,9 @@ class Species{ parent.colour.W + randomMutationColourChannel()); } - this.population = int(floor(parent.population / 2.f)); - parent.population = int(ceil(parent.population / 2.f)); + this.stringCode = mutateMicrobe(parent.stringCode,true); - this.stringCode = Species::mutateProkaryote(parent.stringCode); - this.speciesMembraneType = parent.speciesMembraneType; + generateMembranes(parent); commonConstructor(world); this.setupSpawn(world); @@ -956,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; @@ -987,9 +817,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 +841,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 +922,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 +940,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 +960,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 +979,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 +1035,17 @@ class SpeciesSystem : ScriptSystem{ } } - //! Adds a new AI species - private void createSpecies() + void countSpecies() { - 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() - { - 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++; + } } } @@ -1314,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); @@ -1328,6 +1123,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, @@ -1361,107 +1157,12 @@ 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; -} - -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); - } - } + // Call this to reset processor component + 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 @@ -1478,7 +1179,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); } @@ -1501,11 +1202,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 // @@ -1520,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; @@ -1555,95 +1262,9 @@ 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; -} - - -//! 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; + return speciesEntity; } //! Calls resetAutoEvo on world's SpeciesSystem 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. 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;