diff --git a/source/EngineImpl/DescConverterService.cpp b/source/EngineImpl/DescConverterService.cpp index 0f3c257c2..440cdfa43 100644 --- a/source/EngineImpl/DescConverterService.cpp +++ b/source/EngineImpl/DescConverterService.cpp @@ -865,11 +865,7 @@ GenomeDesc DescConverterService::createGenomeDesc(TOs const& to, int genomeIndex result._id = genomeTO.id; NumberGenerator::get().adaptMaxEntityId(genomeTO.id); result._name = char64ToString(genomeTO.name); - result._lineageId = genomeTO.lineageId; - NumberGenerator::get().adaptMaxLineageId(genomeTO.lineageId); - result._prevLineageId = genomeTO.prevLineageId != 0 ? std::make_optional(genomeTO.prevLineageId) : std::nullopt; result._frontAngle = genomeTO.frontAngle; - result._accumulatedMutations = genomeTO.accumulatedMutations; result._resistanceToInjection = genomeTO.resistanceToInjection; result._applyMetaMutations = genomeTO.applyMetaMutations; for (int i = 0; i < 2; ++i) { @@ -931,6 +927,10 @@ CreatureDesc DescConverterService::createCreatureDesc(TOs const& to, int creatur result._generation = creatureTO.generation; result._numCells = creatureTO.numCells; result._mutationState = creatureTO.mutationState; + result._lineageId = creatureTO.lineageId; + NumberGenerator::get().adaptMaxLineageId(creatureTO.lineageId); + result._prevLineageId = creatureTO.prevLineageId != VALUE_NOT_SET_UINT32 ? std::make_optional(static_cast(creatureTO.prevLineageId)) : std::nullopt; + result._accumulatedMutations = creatureTO.accumulatedMutations; result._headUpdateId = creatureTO.headUpdateId; return result; @@ -967,10 +967,7 @@ void DescConverterService::convertGenomeToTO( stringToChar64(genomeTO.name, genome._name); genomeTO.id = genome._id; - genomeTO.lineageId = genome._lineageId; - genomeTO.prevLineageId = genome._prevLineageId.value_or(0); genomeTO.frontAngle = genome._frontAngle; - genomeTO.accumulatedMutations = genome._accumulatedMutations; genomeTO.resistanceToInjection = genome._resistanceToInjection; genomeTO.applyMetaMutations = genome._applyMetaMutations; for (int i = 0; i < 2; ++i) { @@ -1246,6 +1243,9 @@ void DescConverterService::convertCreatureToTO( creatureTO.headUpdateId = creatureDesc._headUpdateId; creatureTO.numCells = creatureDesc._numCells; creatureTO.mutationState = creatureDesc._mutationState; + creatureTO.lineageId = creatureDesc._lineageId; + creatureTO.prevLineageId = creatureDesc._prevLineageId.value_or(VALUE_NOT_SET_UINT32); + creatureTO.accumulatedMutations = creatureDesc._accumulatedMutations; creatureTO.genomeArrayIndex = genomeTOIndexById.at(creatureDesc._genomeId); } diff --git a/source/EngineInterface/Desc.h b/source/EngineInterface/Desc.h index 5329816b7..6f3995ede 100644 --- a/source/EngineInterface/Desc.h +++ b/source/EngineInterface/Desc.h @@ -588,6 +588,9 @@ struct CreatureDesc MEMBER(CreatureDesc, int, numCells, 0); MEMBER(CreatureDesc, uint64_t, genomeId, 0); MEMBER(CreatureDesc, MutationState, mutationState, MutationState_Mutated); + MEMBER(CreatureDesc, int, lineageId, 0); + MEMBER(CreatureDesc, std::optional, prevLineageId, std::nullopt); + MEMBER(CreatureDesc, float, accumulatedMutations, 0.0f); // Process data MEMBER(CreatureDesc, int, headUpdateId, 0); diff --git a/source/EngineInterface/DescEditService.cpp b/source/EngineInterface/DescEditService.cpp index b47ff1395..06d3e7353 100644 --- a/source/EngineInterface/DescEditService.cpp +++ b/source/EngineInterface/DescEditService.cpp @@ -515,9 +515,9 @@ void DescEditService::randomizeCountdowns(Desc& description, int minValue, int m void DescEditService::randomizeLineageIds(Desc& description) const { - for (auto& genome : description._genomes) { - genome._lineageId = NumberGenerator::get().getRandomInt(); - genome._prevLineageId = 0; + for (auto& creature : description._creatures) { + creature._lineageId = NumberGenerator::get().getRandomInt(); + creature._prevLineageId = std::nullopt; } } diff --git a/source/EngineInterface/DescValidationService.cpp b/source/EngineInterface/DescValidationService.cpp index 0247a3569..203ae5a21 100644 --- a/source/EngineInterface/DescValidationService.cpp +++ b/source/EngineInterface/DescValidationService.cpp @@ -14,11 +14,6 @@ void DescValidationService::validateAndCorrect(GenomeDesc& genome) genome._frontAngle = Math::getNormalizedAngle(genome._frontAngle, -180.0f); // Validate mutation rate fields - genome._lineageId = std::max(genome._lineageId, 0); - if (genome._prevLineageId.has_value()) { - genome._prevLineageId = std::max(genome._prevLineageId.value(), 0); - } - genome._accumulatedMutations = std::max(genome._accumulatedMutations, 0.0f); auto validateCellTypePropertiesMutation = [](CellTypePropertiesMutationDesc& mutation) { mutation._nodeProbability = std::clamp(mutation._nodeProbability, 0.0f, 1.0f); mutation._valueChangeSigma = std::clamp(mutation._valueChangeSigma, 0.0f, 1.0f); @@ -303,11 +298,21 @@ void DescValidationService::validateAndCorrect(GenomeDesc& genome) } } -void DescValidationService::validateAndCorrect(ObjectDesc& object) +void DescValidationService::validateAndCorrect(ExtendedObjectDesc& extendedObject) { + auto& object = extendedObject.object; object._stiffness = std::clamp(object._stiffness, 0.0f, 1.0f); object._color = std::clamp(object._color, 0, MAX_COLORS - 1); + if (extendedObject.creature.has_value()) { + auto& creature = extendedObject.creature.value(); + creature._lineageId = std::max(creature._lineageId, 0); + if (creature._prevLineageId.has_value()) { + creature._prevLineageId = std::max(creature._prevLineageId.value(), 0); + } + creature._accumulatedMutations = std::max(creature._accumulatedMutations, 0.0f); + } + if (object.getObjectType() == ObjectType_Cell) { auto& cell = object.getCellRef(); cell._usableEnergy = std::max(0.0f, cell._usableEnergy); diff --git a/source/EngineInterface/DescValidationService.h b/source/EngineInterface/DescValidationService.h index 94ced5b25..1371deee1 100644 --- a/source/EngineInterface/DescValidationService.h +++ b/source/EngineInterface/DescValidationService.h @@ -11,5 +11,5 @@ class DescValidationService public: void validateAndCorrect(GenomeDesc& genome); - void validateAndCorrect(ObjectDesc& object); + void validateAndCorrect(ExtendedObjectDesc& extendedObject); }; diff --git a/source/EngineInterface/EngineConstants.h b/source/EngineInterface/EngineConstants.h index 4b6555471..e7c9003a7 100644 --- a/source/EngineInterface/EngineConstants.h +++ b/source/EngineInterface/EngineConstants.h @@ -1,6 +1,7 @@ #pragma once auto constexpr VALUE_NOT_SET_UINT64 = 0x7fffffffffffffff; +auto constexpr VALUE_NOT_SET_UINT32 = 0x7fffffff; auto constexpr VALUE_NOT_SET_FLOAT = 1e16f; auto constexpr MAX_OBJECT_CONNECTIONS = 6; diff --git a/source/EngineInterface/GenomeDesc.h b/source/EngineInterface/GenomeDesc.h index 41b936352..81350a364 100644 --- a/source/EngineInterface/GenomeDesc.h +++ b/source/EngineInterface/GenomeDesc.h @@ -552,10 +552,7 @@ struct GenomeDesc GenomeDesc id(uint64_t id); MEMBER(GenomeDesc, std::string, name, ""); MEMBER(GenomeDesc, std::vector, genes, {}) - MEMBER(GenomeDesc, int, lineageId, 0); - MEMBER(GenomeDesc, std::optional, prevLineageId, std::nullopt); MEMBER(GenomeDesc, float, frontAngle, 0.0f); - MEMBER(GenomeDesc, float, accumulatedMutations, 0.0f); MEMBER(GenomeDesc, bool, resistanceToInjection, false); MEMBER(GenomeDesc, bool, applyMetaMutations, true); diff --git a/source/EngineInterface/GenomeDescEditService.cpp b/source/EngineInterface/GenomeDescEditService.cpp index bfeea9e2f..c7e83c91b 100644 --- a/source/EngineInterface/GenomeDescEditService.cpp +++ b/source/EngineInterface/GenomeDescEditService.cpp @@ -492,8 +492,6 @@ namespace void adaptGenomeAttributesForPreview(GenomeDesc& genome, bool detailSimulation) { - genome._lineageId = 0; - genome._accumulatedMutations = 0; genome._mutationRates._neuronMutations[0] = NeuronMutationDesc(); genome._mutationRates._neuronMutations[1] = NeuronMutationDesc(); genome._mutationRates._connectionMutations[0] = ConnectionMutationDesc(); diff --git a/source/EngineInterface/GenomeDescHash.h b/source/EngineInterface/GenomeDescHash.h index 4fdd97b45..208ad50d9 100644 --- a/source/EngineInterface/GenomeDescHash.h +++ b/source/EngineInterface/GenomeDescHash.h @@ -540,10 +540,8 @@ struct std::hash hash_combine(seed, std::hash{}(gene)); } hash_combine(seed, desc._frontAngle); - hash_combine(seed, desc._accumulatedMutations); hash_combine(seed, desc._resistanceToInjection); hash_combine(seed, desc._applyMetaMutations); - hash_combine(seed, desc._prevLineageId); for (int i = 0; i < 2; ++i) { hash_combine(seed, desc._mutationRates._neuronMutations[i]._nodeProbability); hash_combine(seed, desc._mutationRates._neuronMutations[i]._weightChangeSigma); diff --git a/source/EngineKernels/AttackerProcessor.cuh b/source/EngineKernels/AttackerProcessor.cuh index 0c1ba7160..79ea1f76b 100644 --- a/source/EngineKernels/AttackerProcessor.cuh +++ b/source/EngineKernels/AttackerProcessor.cuh @@ -207,7 +207,7 @@ __device__ __inline__ void AttackerProcessor::processCell(SimulationData& data, ParameterCalculator::calcParameter(cudaSimulationParameters.attackerFoodChainColorMatrix, data, object->pos, color, otherColor); // Evaluate lineage - if (cell->creature->genome->isRelatedLineage(otherCell->creature->genome)) { + if (cell->creature->isRelatedLineage(otherCell->creature)) { energyToTransfer *= (1.0f - cudaSimulationParameters.attackerRelatedLineageProtection.value[object->color]); } diff --git a/source/EngineKernels/CommunicatorProcessor.cuh b/source/EngineKernels/CommunicatorProcessor.cuh index 691bc36e3..3f1018c81 100644 --- a/source/EngineKernels/CommunicatorProcessor.cuh +++ b/source/EngineKernels/CommunicatorProcessor.cuh @@ -98,11 +98,11 @@ __device__ __inline__ void CommunicatorProcessor::processSender(SimulationData& // Check lineage restriction if (receiver.restrictToLineage != LineageRestriction_No) { if (receiver.restrictToLineage == LineageRestriction_RelatedLineage) { - if (!object->typeData.cell.creature->genome->isRelatedLineage(otherObject->typeData.cell.creature->genome)) { + if (!object->typeData.cell.creature->isRelatedLineage(otherObject->typeData.cell.creature)) { return false; } } else if (receiver.restrictToLineage == LineageRestriction_UnrelatedLineage) { - if (object->typeData.cell.creature->genome->isRelatedLineage(otherObject->typeData.cell.creature->genome)) { + if (object->typeData.cell.creature->isRelatedLineage(otherObject->typeData.cell.creature)) { return false; } } diff --git a/source/EngineKernels/DataAccessKernels.cu b/source/EngineKernels/DataAccessKernels.cu index e4477aedd..bed7a61c8 100644 --- a/source/EngineKernels/DataAccessKernels.cu +++ b/source/EngineKernels/DataAccessKernels.cu @@ -31,10 +31,7 @@ namespace } auto& genomeTO = to.genomes[genomeTOIndex]; genomeTO.id = genome->id; - genomeTO.lineageId = genome->lineageId; - genomeTO.prevLineageId = genome->prevLineageId; genomeTO.frontAngle = genome->frontAngle; - genomeTO.accumulatedMutations = genome->accumulatedMutations; genomeTO.resistanceToInjection = genome->resistanceToInjection; genomeTO.applyMetaMutations = genome->applyMetaMutations; for (int i = 0; i < 2; ++i) { @@ -293,6 +290,9 @@ namespace creatureTO.generation = creature->generation; creatureTO.numCells = creature->numCells; creatureTO.mutationState = creature->mutationState; + creatureTO.lineageId = creature->lineageId; + creatureTO.prevLineageId = creature->prevLineageId; + creatureTO.accumulatedMutations = creature->accumulatedMutations; creatureTO.headUpdateId = creature->headUpdateId; creatureTO.genomeArrayIndex = creature->genome->genomeIndex; @@ -1042,6 +1042,7 @@ __global__ void cudaAdaptNumberGenerator(CudaNumberGenerator numberGen, TOs to) for (int index = partition.startIndex; index <= partition.endIndex; index += partition.step) { auto const& creature = to.creatures[index]; maxIds.entityId = max(maxIds.entityId, creature.id); + maxIds.lineageId = max(maxIds.lineageId, creature.lineageId); } } { @@ -1050,7 +1051,6 @@ __global__ void cudaAdaptNumberGenerator(CudaNumberGenerator numberGen, TOs to) for (int index = partition.startIndex; index <= partition.endIndex; index += partition.step) { auto const& genome = to.genomes[index]; maxIds.entityId = max(maxIds.entityId, genome.id); - maxIds.lineageId = max(maxIds.lineageId, genome.lineageId); } } numberGen.adaptMaxIds(maxIds); diff --git a/source/EngineKernels/EditKernels.cu b/source/EngineKernels/EditKernels.cu index 97d6a5de1..7244bc25e 100644 --- a/source/EngineKernels/EditKernels.cu +++ b/source/EngineKernels/EditKernels.cu @@ -30,6 +30,10 @@ __global__ void cudaChangeObject(SimulationData data, TOs changeTO) EntityFactory entityFactory; entityFactory.init(&data); entityFactory.changeObjectFromTO(changeTO, objectTO, object); + if (objectTO.type == ObjectType_Cell) { + auto const& creatureTO = changeTO.creatures[objectTO.typeData.cell.creatureIndex]; + entityFactory.changeCreatureFromTO(creatureTO, object->typeData.cell.creature); + } } } } diff --git a/source/EngineKernels/Entities.cuh b/source/EngineKernels/Entities.cuh index 4a7305fcc..7d5826ca1 100644 --- a/source/EngineKernels/Entities.cuh +++ b/source/EngineKernels/Entities.cuh @@ -450,11 +450,25 @@ struct Creature Genome* genome; MutationState mutationState; + uint32_t lineageId; + uint32_t prevLineageId; + float accumulatedMutations; + // Process data uint32_t headUpdateId; // Will be updated regularly to trigger head updates // Temporary data uint64_t creatureIndex; // May be invalid + + __device__ __inline__ bool isRelatedLineage(Creature* other) + { + if (prevLineageId != VALUE_NOT_SET_UINT32 && other->prevLineageId != VALUE_NOT_SET_UINT32) { + return lineageId == other->lineageId || lineageId == other->prevLineageId || prevLineageId == other->lineageId + || prevLineageId == other->prevLineageId; + } else { + return lineageId == other->lineageId; + } + } }; struct Solid diff --git a/source/EngineKernels/EntityFactory.cuh b/source/EngineKernels/EntityFactory.cuh index d6185f15e..586bd6c25 100644 --- a/source/EngineKernels/EntityFactory.cuh +++ b/source/EngineKernels/EntityFactory.cuh @@ -17,6 +17,7 @@ public: __inline__ __device__ Genome* createGenomeFromTO(TOs const& to, int genomeIndex); __inline__ __device__ Object* createObjectFromTO(TOs const& to, int objectIndex, Object* objectArray); __inline__ __device__ void changeObjectFromTO(TOs const& to, ObjectTO const& objectTO, Object* object); + __inline__ __device__ void changeCreatureFromTO(CreatureTO const& creatureTO, Creature* creature); __inline__ __device__ void changeEnergyFromTO(EnergyTO const& particleTO, Energy* particle); __inline__ __device__ Energy* createEnergy(float energy, float2 const& pos, float2 const& vel, int color); @@ -86,10 +87,7 @@ __inline__ __device__ Genome* EntityFactory::createGenomeFromTO(TOs const& to, i auto genome = _data->entities.heap.getTypedSubArray(1); genomeTO.genomeIndexOnGpu = static_cast(reinterpret_cast(genome) - _data->entities.heap.getArray()); genome->id = genomeTO.id; - genome->lineageId = genomeTO.lineageId; - genome->prevLineageId = genomeTO.prevLineageId; genome->frontAngle = genomeTO.frontAngle; - genome->accumulatedMutations = genomeTO.accumulatedMutations; genome->resistanceToInjection = genomeTO.resistanceToInjection; genome->applyMetaMutations = genomeTO.applyMetaMutations; for (int i = 0; i < 2; ++i) { @@ -327,11 +325,7 @@ __inline__ __device__ Creature* EntityFactory::createCreatureFromTO(TOs const& t creatureTO.creatureIndexOnGpu = static_cast(reinterpret_cast(creature) - _data->entities.heap.getArray()); creature->id = creatureTO.id; - creature->ancestorId = creatureTO.ancestorId; - creature->generation = creatureTO.generation; - creature->numCells = creatureTO.numCells; - creature->mutationState = creatureTO.mutationState; - creature->headUpdateId = creatureTO.headUpdateId; + changeCreatureFromTO(creatureTO, creature); auto const& genomeTO = to.genomes[creatureTO.genomeArrayIndex]; creature->genome = &_data->entities.heap.atType(genomeTO.genomeIndexOnGpu); @@ -609,6 +603,18 @@ __inline__ __device__ void EntityFactory::changeObjectFromTO(TOs const& to, Obje } } +__inline__ __device__ void EntityFactory::changeCreatureFromTO(CreatureTO const& creatureTO, Creature* creature) +{ + creature->ancestorId = creatureTO.ancestorId; + creature->generation = creatureTO.generation; + creature->numCells = creatureTO.numCells; + creature->mutationState = creatureTO.mutationState; + creature->lineageId = creatureTO.lineageId; + creature->prevLineageId = creatureTO.prevLineageId; + creature->accumulatedMutations = creatureTO.accumulatedMutations; + creature->headUpdateId = creatureTO.headUpdateId; +} + __inline__ __device__ void EntityFactory::changeEnergyFromTO(EnergyTO const& particleTO, Energy* particle) { particle->energy = particleTO.energy; diff --git a/source/EngineKernels/Genome.cuh b/source/EngineKernels/Genome.cuh index 6d98945fa..cb9fd1f56 100644 --- a/source/EngineKernels/Genome.cuh +++ b/source/EngineKernels/Genome.cuh @@ -426,24 +426,11 @@ struct Genome int numGenes; Gene* genes; - uint32_t lineageId; - uint32_t prevLineageId; float frontAngle; - float accumulatedMutations; bool resistanceToInjection; bool applyMetaMutations; MutationRates mutationRates; // Temporary data uint64_t genomeIndex; // May be invalid - - __device__ __inline__ bool isRelatedLineage(Genome* other) - { - if (prevLineageId != 0 && other->prevLineageId != 0) { - return lineageId == other->lineageId || lineageId == other->prevLineageId || prevLineageId == other->lineageId - || prevLineageId == other->prevLineageId; - } else { - return lineageId == other->lineageId; - } - } }; diff --git a/source/EngineKernels/GenomeTO.cuh b/source/EngineKernels/GenomeTO.cuh index af73f128b..e89f0872b 100644 --- a/source/EngineKernels/GenomeTO.cuh +++ b/source/EngineKernels/GenomeTO.cuh @@ -431,10 +431,7 @@ struct GenomeTO int numGenes; uint64_t geneArrayIndex; - uint32_t lineageId; - uint32_t prevLineageId; float frontAngle; - float accumulatedMutations; bool resistanceToInjection; bool applyMetaMutations; MutationRatesTO mutationRates; diff --git a/source/EngineKernels/GeometryKernels.cu b/source/EngineKernels/GeometryKernels.cu index d30d01acb..4e91b5fa6 100644 --- a/source/EngineKernels/GeometryKernels.cu +++ b/source/EngineKernels/GeometryKernels.cu @@ -138,7 +138,7 @@ namespace float b = fminf(1.0f, fmaxf(0.0f, color.b)); float h, s, v; rgbToHsv(r, g, b, h, s, v); - auto lineageId = object->typeData.cell.creature->genome->lineageId; + auto lineageId = object->typeData.cell.creature->lineageId; uint32_t hash = lineageId * 2654435761u; float hueOffset = (static_cast(hash & 0xFFFFu) / 65535.0f) * 0.2f - 0.1f; h += hueOffset; @@ -149,7 +149,7 @@ namespace if (object->type != ObjectType_Cell) { return getCustomizationColor(object->color); } - auto lineageId = object->typeData.cell.creature->genome->lineageId; + auto lineageId = object->typeData.cell.creature->lineageId; uint32_t hash1 = lineageId * 2654435761u; uint32_t hash2 = lineageId * 2246822519u; uint32_t hash3 = lineageId * 3266489917u; diff --git a/source/EngineKernels/MutationProcessor.cuh b/source/EngineKernels/MutationProcessor.cuh index d2b47ab23..c7bf407f2 100644 --- a/source/EngineKernels/MutationProcessor.cuh +++ b/source/EngineKernels/MutationProcessor.cuh @@ -20,7 +20,7 @@ class MutationProcessor { public: __inline__ __device__ static void process(SimulationData& data, SimulationStatistics& statistics); - __inline__ __device__ static void applyMutations(SimulationData& data, Genome* genome); + __inline__ __device__ static void applyMutations(SimulationData& data, Creature* creature, Genome* genome); private: // Upper bound to avoid heap exhaustion. @@ -48,7 +48,8 @@ private: __inline__ __device__ static void removeNode(SimulationData& data, Gene& gene, int position); __inline__ __device__ static void correctGenome(SimulationData& data, Genome* genome); - __inline__ __device__ static void updateAccumulatedMutationsAndLineageId(SimulationData& data, Genome* genome, float& accumulatedMutations); + __inline__ __device__ static void + updateAccumulatedMutationsAndLineageId(SimulationData& data, Creature* creature, Genome* genome, float& accumulatedMutations); __inline__ __device__ static float generateGaussian(SimulationData& data); __inline__ __device__ static bool isRandomEvent(SimulationData& data, float probability); @@ -99,7 +100,7 @@ __inline__ __device__ void MutationProcessor::process(SimulationData& data, Simu if (clonedGenome != nullptr) { // Apply mutations to cloned genome - applyMutations(data, clonedGenome); + applyMutations(data, object->typeData.cell.creature, clonedGenome); if (laneId == 0) { object->typeData.cell.creature->genome = clonedGenome; @@ -109,7 +110,7 @@ __inline__ __device__ void MutationProcessor::process(SimulationData& data, Simu } } -__inline__ __device__ void MutationProcessor::applyMutations(SimulationData& data, Genome* genome) +__inline__ __device__ void MutationProcessor::applyMutations(SimulationData& data, Creature* creature, Genome* genome) { __shared__ float accumulatedMutations; auto block = cg_mutation::this_thread_block(); @@ -147,7 +148,7 @@ __inline__ __device__ void MutationProcessor::applyMutations(SimulationData& dat } block.sync(); - updateAccumulatedMutationsAndLineageId(data, genome, accumulatedMutations); + updateAccumulatedMutationsAndLineageId(data, creature, genome, accumulatedMutations); } __inline__ __device__ void MutationProcessor::applyMutations_neurons(SimulationData& data, Genome* genome, float& accumulatedMutations) @@ -1206,7 +1207,8 @@ __inline__ __device__ void MutationProcessor::applyMutations_meta(SimulationData } } -__inline__ __device__ void MutationProcessor::updateAccumulatedMutationsAndLineageId(SimulationData& data, Genome* genome, float& accumulatedMutations) +__inline__ __device__ void +MutationProcessor::updateAccumulatedMutationsAndLineageId(SimulationData& data, Creature* creature, Genome* genome, float& accumulatedMutations) { auto laneId = cg_mutation::this_thread_block().thread_rank(); if (laneId == 0) { @@ -1214,11 +1216,11 @@ __inline__ __device__ void MutationProcessor::updateAccumulatedMutationsAndLinea auto denominator = numberOfNodes > 0 ? toFloat(numberOfNodes) : 1.0f; - genome->accumulatedMutations += accumulatedMutations / denominator; - if (genome->accumulatedMutations > cudaSimulationParameters.newLineageThreshold.value) { - genome->prevLineageId = genome->lineageId; - genome->lineageId = data.primaryNumberGen.createLineageId(); - genome->accumulatedMutations = 0; + creature->accumulatedMutations += accumulatedMutations / denominator; + if (creature->accumulatedMutations > cudaSimulationParameters.newLineageThreshold.value) { + creature->prevLineageId = creature->lineageId; + creature->lineageId = data.primaryNumberGen.createLineageId(); + creature->accumulatedMutations = 0; } } } diff --git a/source/EngineKernels/ReconnectorProcessor.cuh b/source/EngineKernels/ReconnectorProcessor.cuh index 29f746d55..4540d7662 100644 --- a/source/EngineKernels/ReconnectorProcessor.cuh +++ b/source/EngineKernels/ReconnectorProcessor.cuh @@ -101,11 +101,11 @@ __inline__ __device__ void ReconnectorProcessor::tryCreateConnection(SimulationD // Filter by lineage restriction if (reconnector.modeData.reconnectCreature.restrictToLineage != LineageRestriction_No) { if (reconnector.modeData.reconnectCreature.restrictToLineage == LineageRestriction_RelatedLineage) { - if (!object->typeData.cell.creature->genome->isRelatedLineage(otherObject->typeData.cell.creature->genome)) { + if (!object->typeData.cell.creature->isRelatedLineage(otherObject->typeData.cell.creature)) { return; } } else if (reconnector.modeData.reconnectCreature.restrictToLineage == LineageRestriction_UnrelatedLineage) { - if (object->typeData.cell.creature->genome->isRelatedLineage(otherObject->typeData.cell.creature->genome)) { + if (object->typeData.cell.creature->isRelatedLineage(otherObject->typeData.cell.creature)) { return; } } diff --git a/source/EngineKernels/SensorProcessor.cuh b/source/EngineKernels/SensorProcessor.cuh index 475461fdf..9dfa14502 100644 --- a/source/EngineKernels/SensorProcessor.cuh +++ b/source/EngineKernels/SensorProcessor.cuh @@ -398,11 +398,11 @@ SensorProcessor::getMatchInfo(SimulationData& data, Object* object, float2 const } if (matches && restrictToLineage != LineageRestriction_No) { if (restrictToLineage == LineageRestriction_RelatedLineage) { - if (!object->typeData.cell.creature->genome->isRelatedLineage(otherObject->typeData.cell.creature->genome)) { + if (!object->typeData.cell.creature->isRelatedLineage(otherObject->typeData.cell.creature)) { matches = false; } } else if (restrictToLineage == LineageRestriction_UnrelatedLineage) { - if (object->typeData.cell.creature->genome->isRelatedLineage(otherObject->typeData.cell.creature->genome)) { + if (object->typeData.cell.creature->isRelatedLineage(otherObject->typeData.cell.creature)) { matches = false; } } diff --git a/source/EngineKernels/TOs.cuh b/source/EngineKernels/TOs.cuh index ee3bdc662..d2b7a823f 100644 --- a/source/EngineKernels/TOs.cuh +++ b/source/EngineKernels/TOs.cuh @@ -496,6 +496,10 @@ struct CreatureTO uint64_t genomeArrayIndex; MutationState mutationState; + uint32_t lineageId; + uint32_t prevLineageId; + float accumulatedMutations; + // Process data uint32_t headUpdateId; diff --git a/source/EngineKernels/TestKernels.cu b/source/EngineKernels/TestKernels.cu index 4e66d3991..d98d9fdd9 100644 --- a/source/EngineKernels/TestKernels.cu +++ b/source/EngineKernels/TestKernels.cu @@ -25,7 +25,7 @@ __global__ void cudaTestMutate(SimulationData data, uint64_t objectId) block.sync(); if (shouldMutate) { - MutationProcessor::applyMutations(data, object->typeData.cell.creature->genome); + MutationProcessor::applyMutations(data, object->typeData.cell.creature, object->typeData.cell.creature->genome); } block.sync(); } diff --git a/source/EngineTestData/DescTestDataFactory.cpp b/source/EngineTestData/DescTestDataFactory.cpp index 4b3467383..848076590 100644 --- a/source/EngineTestData/DescTestDataFactory.cpp +++ b/source/EngineTestData/DescTestDataFactory.cpp @@ -195,10 +195,7 @@ std::pair DescTestDataFactory::createNonDefaultCreatur auto genome = GenomeDesc() .name("Test Genome") - .lineageId(502) - .prevLineageId(501) .frontAngle(270.0f) - .accumulatedMutations(0.05f) .resistanceToInjection(true) .applyMetaMutations(false) .mutationRates(mutation) @@ -214,8 +211,16 @@ std::pair DescTestDataFactory::createNonDefaultCreatur }), }); - auto creature = - CreatureDesc().ancestorId(1001).generation(7).numCells(25).headUpdateId(42).mutationState(MutationState_MutationInProgress).genomeId(genome._id); + auto creature = CreatureDesc() + .ancestorId(1001) + .generation(7) + .numCells(25) + .headUpdateId(42) + .mutationState(MutationState_MutationInProgress) + .lineageId(502) + .prevLineageId(501) + .accumulatedMutations(0.05f) + .genomeId(genome._id); return {creature, genome}; } diff --git a/source/EngineTests/AccumulatedMutationTests.cpp b/source/EngineTests/AccumulatedMutationTests.cpp index 34fd75b59..c8a00f1d7 100644 --- a/source/EngineTests/AccumulatedMutationTests.cpp +++ b/source/EngineTests/AccumulatedMutationTests.cpp @@ -48,7 +48,7 @@ INSTANTIATE_TEST_SUITE_P( TEST_P(AccumulatedMutationTests_AllTypes, accumulatedMutations_increases) { - auto genome = createTestGenome().lineageId(42).prevLineageId(41); + auto genome = createTestGenome(); switch (GetParam()) { case MutationType::Neuron: genome._mutationRates._neuronMutations[0] = @@ -87,7 +87,7 @@ TEST_P(AccumulatedMutationTests_AllTypes, accumulatedMutations_increases) break; } - auto data = Desc().addCreature({ObjectDesc().id(1)}, CreatureDesc(), genome); + auto data = Desc().addCreature({ObjectDesc().id(1)}, CreatureDesc().lineageId(42).prevLineageId(41), genome); auto parameters = _parameters; parameters.newLineageThreshold.value = 1.0e30f; @@ -98,15 +98,15 @@ TEST_P(AccumulatedMutationTests_AllTypes, accumulatedMutations_increases) _simulationFacade->testOnly_mutate(1); } - auto actualGenome = getMutatedGenome(); - EXPECT_GT(actualGenome._accumulatedMutations, genome._accumulatedMutations); + auto actualCreature = getMutatedCreature(); + EXPECT_GT(actualCreature._accumulatedMutations, 0.0f); } TEST_F(AccumulatedMutationTests, accumulatedMutations_metaMutationDoesNotAccount) { - auto genome = GenomeDesc().lineageId(42).prevLineageId(41); + auto genome = GenomeDesc(); - auto data = Desc().addCreature({ObjectDesc().id(1)}, CreatureDesc(), genome); + auto data = Desc().addCreature({ObjectDesc().id(1)}, CreatureDesc().lineageId(42).prevLineageId(41), genome); _parameters.neuronsMetaMutationsSigma.value = 1.0f; _parameters.connectionsMetaMutationsSigma.value = 1.0f; @@ -124,18 +124,17 @@ TEST_F(AccumulatedMutationTests, accumulatedMutations_metaMutationDoesNotAccount _simulationFacade->setSimulationData(data); _simulationFacade->testOnly_mutate(1); - auto actualGenome = getMutatedGenome(); - EXPECT_EQ(actualGenome._accumulatedMutations, 0.0f); - EXPECT_EQ(actualGenome._lineageId, 42); - EXPECT_EQ(actualGenome._prevLineageId, 41); + auto actualCreature = getMutatedCreature(); + EXPECT_EQ(actualCreature._accumulatedMutations, 0.0f); + EXPECT_EQ(actualCreature._lineageId, 42); + EXPECT_EQ(actualCreature._prevLineageId, 41); } TEST_F(AccumulatedMutationTests, accumulatedMutations_createsNewLineageId) { - auto genome = createTestGenome().lineageId(42).prevLineageId(41); - genome._accumulatedMutations = 11.0f; + auto genome = createTestGenome(); - auto data = Desc().addCreature({ObjectDesc().id(1)}, CreatureDesc(), genome); + auto data = Desc().addCreature({ObjectDesc().id(1)}, CreatureDesc().lineageId(42).prevLineageId(41).accumulatedMutations(11.0f), genome); _parameters.newLineageThreshold.value = 0.1f; _simulationFacade->setSimulationParameters(_parameters); @@ -143,8 +142,8 @@ TEST_F(AccumulatedMutationTests, accumulatedMutations_createsNewLineageId) _simulationFacade->setSimulationData(data); _simulationFacade->testOnly_mutate(1); - auto actualGenome = getMutatedGenome(); - ASSERT_TRUE(actualGenome._prevLineageId.has_value()); - EXPECT_EQ(*actualGenome._prevLineageId, 42); - EXPECT_GT(actualGenome._lineageId, 42); + auto actualCreature = getMutatedCreature(); + ASSERT_TRUE(actualCreature._prevLineageId.has_value()); + EXPECT_EQ(*actualCreature._prevLineageId, 42); + EXPECT_GT(actualCreature._lineageId, 42); } diff --git a/source/EngineTests/BalanceTests.cpp b/source/EngineTests/BalanceTests.cpp index 96cd52b94..4ebd79677 100644 --- a/source/EngineTests/BalanceTests.cpp +++ b/source/EngineTests/BalanceTests.cpp @@ -31,8 +31,8 @@ class BalanceTests : public IntegrationTestFramework .pos({numberGen.getRandomFloat(0.0f, worldSize.x), numberGen.getRandomFloat(0.0f, worldSize.y)}) .type(CellDesc().headCell(true).constructor(ConstructorDesc().provideEnergy(ProvideEnergy_Free).separation(true))), }, - CreatureDesc(), - GenomeDesc().lineageId(0).prevLineageId(0).frontAngle(225.0f).genes( + CreatureDesc().lineageId(0).prevLineageId(0), + GenomeDesc().frontAngle(225.0f).genes( { GeneDesc() @@ -73,8 +73,8 @@ class BalanceTests : public IntegrationTestFramework .pos({numberGen.getRandomFloat(0.0f, worldSize.x), numberGen.getRandomFloat(0.0f, worldSize.y)}) .type(CellDesc().headCell(true).constructor(ConstructorDesc().provideEnergy(ProvideEnergy_Free).separation(true))), }, - CreatureDesc(), - GenomeDesc().lineageId(1).prevLineageId(1).frontAngle(225.0f).genes( + CreatureDesc().lineageId(1).prevLineageId(1), + GenomeDesc().frontAngle(225.0f).genes( { GeneDesc() @@ -129,16 +129,10 @@ TEST_F(BalanceTests, longRunning_smallCreatures_vs_largeCreatures_fewDigestionCa _simulationFacade->calcTimesteps(20000); auto actualData = _simulationFacade->getSimulationData(); - // Create a map of genomeId to lineageId - std::unordered_map genomeIdToLineageId; - for (const auto& genome : actualData._genomes) { - genomeIdToLineageId[genome._id] = genome._lineageId; - } - int numSmallCreatures = 0; int numLargeCreatures = 0; for (const auto& creature : actualData._creatures) { - auto lineageId = genomeIdToLineageId.at(creature._genomeId); + auto lineageId = creature._lineageId; if (lineageId == 0) { ++numSmallCreatures; } else if (lineageId == 1) { @@ -173,16 +167,10 @@ TEST_F(BalanceTests, longRunning_smallCreatures_vs_largeCreatures_highDigestionC _simulationFacade->calcTimesteps(20000); auto actualData = _simulationFacade->getSimulationData(); - // Create a map of genomeId to lineageId - std::unordered_map genomeIdToLineageId; - for (const auto& genome : actualData._genomes) { - genomeIdToLineageId[genome._id] = genome._lineageId; - } - int numSmallCreatures = 0; int numLargeCreatures = 0; for (const auto& creature : actualData._creatures) { - auto lineageId = genomeIdToLineageId.at(creature._genomeId); + auto lineageId = creature._lineageId; if (lineageId == 0) { ++numSmallCreatures; } else if (lineageId == 1) { diff --git a/source/EngineTests/CellTypeModeMutationTests.cpp b/source/EngineTests/CellTypeModeMutationTests.cpp index 6b2173289..8d11d2c19 100644 --- a/source/EngineTests/CellTypeModeMutationTests.cpp +++ b/source/EngineTests/CellTypeModeMutationTests.cpp @@ -28,9 +28,6 @@ class CellTypeModeMutationTests : public MutationTestsBase bool compareAllExceptCellTypeMode(GenomeDesc expected, GenomeDesc actual) { auto reset = [](GenomeDesc& genome) { - genome._lineageId = 0; - genome._prevLineageId = std::nullopt; - genome._accumulatedMutations = 0.0f; for (auto& gene : genome._genes) { for (auto& node : gene._nodes) { resetCellTypeMode(node._cellType); diff --git a/source/EngineTests/CellTypeMutationTests.cpp b/source/EngineTests/CellTypeMutationTests.cpp index 63193c07f..c9f9eb390 100644 --- a/source/EngineTests/CellTypeMutationTests.cpp +++ b/source/EngineTests/CellTypeMutationTests.cpp @@ -15,9 +15,6 @@ class CellTypeMutationTests : public MutationTestsBase bool compareAllExceptCellTypeAndHomogeneousFlag(GenomeDesc expected, GenomeDesc actual) { auto reset = [](GenomeDesc& genome) { - genome._lineageId = 0; - genome._prevLineageId = std::nullopt; - genome._accumulatedMutations = 0.0f; for (auto& gene : genome._genes) { gene._homogeneousCellType = false; // canonicalize: the cell type mutation may also flip this flag for (auto& node : gene._nodes) { diff --git a/source/EngineTests/CellTypePropertiesMutationTests.cpp b/source/EngineTests/CellTypePropertiesMutationTests.cpp index 3ea06c1d0..18710156d 100644 --- a/source/EngineTests/CellTypePropertiesMutationTests.cpp +++ b/source/EngineTests/CellTypePropertiesMutationTests.cpp @@ -44,9 +44,6 @@ class CellTypePropertiesMutationTests : public MutationTestsBase bool compareAllExceptCellTypeProperties(GenomeDesc expected, GenomeDesc actual) { auto reset = [](GenomeDesc& genome) { - genome._lineageId = 0; - genome._prevLineageId = std::nullopt; - genome._accumulatedMutations = 0.0f; for (auto& gene : genome._genes) { for (auto& node : gene._nodes) { resetCellTypeProperties(node._cellType); diff --git a/source/EngineTests/CommunicatorTests.cpp b/source/EngineTests/CommunicatorTests.cpp index 02d61b25d..e1f3c369b 100644 --- a/source/EngineTests/CommunicatorTests.cpp +++ b/source/EngineTests/CommunicatorTests.cpp @@ -422,8 +422,8 @@ TEST_P(CommunicatorTests_LineageRestriction, sender_lineageRestriction) ObjectDesc().id(100).pos({100.0f, 100.0f}).type(CellDesc().cellType(CommunicatorDesc().mode(SenderDesc().range(50).maxTimesSent(4)))), ObjectDesc().id(101).pos({101.0f, 100.0f}).type(CellDesc().signal(SignalDesc().channels({1.0f, 0.5f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}))), }, - CreatureDesc().id(1), - GenomeDesc().lineageId(senderLineageId)); + CreatureDesc().id(1).lineageId(senderLineageId), + GenomeDesc()); data.addConnection(100, 101); data.addCreature( @@ -431,8 +431,8 @@ TEST_P(CommunicatorTests_LineageRestriction, sender_lineageRestriction) ObjectDesc().id(200).pos({120.0f, 100.0f}).type(CellDesc().cellType(CommunicatorDesc().mode(ReceiverDesc().restrictToLineage(params.restriction)))), ObjectDesc().id(201).pos({121.0f, 100.0f}), }, - CreatureDesc().id(2), - GenomeDesc().lineageId(receiverLineageId)); + CreatureDesc().id(2).lineageId(receiverLineageId), + GenomeDesc()); data.addConnection(200, 201); _simulationFacade->setSimulationData(data); diff --git a/source/EngineTests/ConnectionMutationTests.cpp b/source/EngineTests/ConnectionMutationTests.cpp index 99c8c16b2..7341aa456 100644 --- a/source/EngineTests/ConnectionMutationTests.cpp +++ b/source/EngineTests/ConnectionMutationTests.cpp @@ -14,9 +14,6 @@ class ConnectionMutationTests : public MutationTestsBase bool compareAllExceptConnectionWeights(GenomeDesc expected, GenomeDesc actual) { auto reset = [](GenomeDesc& genome) { - genome._lineageId = 0; - genome._prevLineageId = std::nullopt; - genome._accumulatedMutations = 0.0f; for (auto& gene : genome._genes) { for (auto& node : gene._nodes) { std::fill(node._neuralNetwork._connectionWeights.begin(), node._neuralNetwork._connectionWeights.end(), 0.0f); diff --git a/source/EngineTests/ConstructorMutationTests.cpp b/source/EngineTests/ConstructorMutationTests.cpp index bcec59d84..e5c3558c7 100644 --- a/source/EngineTests/ConstructorMutationTests.cpp +++ b/source/EngineTests/ConstructorMutationTests.cpp @@ -15,9 +15,6 @@ class ConstructorMutationTests : public MutationTestsBase bool compareAllExceptConstructor(GenomeDesc expected, GenomeDesc actual) { auto reset = [](GenomeDesc& genome) { - genome._lineageId = 0; - genome._prevLineageId = std::nullopt; - genome._accumulatedMutations = 0.0f; for (auto& gene : genome._genes) { for (auto& node : gene._nodes) { node._constructor.reset(); diff --git a/source/EngineTests/DataTransferTests.cpp b/source/EngineTests/DataTransferTests.cpp index ab6cc2d14..55687f46f 100644 --- a/source/EngineTests/DataTransferTests.cpp +++ b/source/EngineTests/DataTransferTests.cpp @@ -310,6 +310,42 @@ TEST_F(DataTransferTests, injectGenomeToSelectedCreatures_multipleCreatures_only } } +TEST_F(DataTransferTests, changeCell_creatureLineage) +{ + auto genome = GenomeDesc(); + Desc data; + data.addCreature({ObjectDesc().id(1)}, CreatureDesc().id(1).lineageId(5), genome); + _simulationFacade->setSimulationData(data); + + auto inspectedData = _simulationFacade->getInspectedSimulationData({1}); + auto objects = DescEditService::get().getObjects(inspectedData); + ASSERT_EQ(1, objects.size()); + auto extended = std::get(objects.front()); + ASSERT_TRUE(extended.creature.has_value()); + EXPECT_EQ(5, extended.creature->_lineageId); + EXPECT_FALSE(extended.creature->_prevLineageId.has_value()); // unset optional round-trips through the TO sentinel + + extended.creature->_lineageId = 9; + extended.creature->_prevLineageId = 7; + extended.creature->_accumulatedMutations = 3.5f; + _simulationFacade->changeCell(extended); + + auto after = _simulationFacade->getSimulationData(); + auto creature = after.getCreatureRef(1); + EXPECT_EQ(9, creature._lineageId); + ASSERT_TRUE(creature._prevLineageId.has_value()); + EXPECT_EQ(7, *creature._prevLineageId); + EXPECT_EQ(3.5f, creature._accumulatedMutations); + + // Same readback path the GUI uses for its periodic refresh + auto reinspected = _simulationFacade->getInspectedSimulationData({1}); + auto creature2 = reinspected.getCreatureRef(1); + EXPECT_EQ(9, creature2._lineageId); + ASSERT_TRUE(creature2._prevLineageId.has_value()); + EXPECT_EQ(7, *creature2._prevLineageId); + EXPECT_EQ(3.5f, creature2._accumulatedMutations); +} + TEST_F(DataTransferTests, getInspectedSimulationData) { auto constexpr CreatureId1 = 1; diff --git a/source/EngineTests/MutationTestsBase.h b/source/EngineTests/MutationTestsBase.h index 5141472f4..204e29f22 100644 --- a/source/EngineTests/MutationTestsBase.h +++ b/source/EngineTests/MutationTestsBase.h @@ -47,4 +47,11 @@ class MutationTestsBase : public IntegrationTestFramework auto actualCreature = actualData.getCreatureRef(actualCell._creatureId); return actualData.getGenomeRef(actualCreature._genomeId); } + + CreatureDesc getMutatedCreature(uint64_t objectId = 1) const + { + auto actualData = _simulationFacade->getSimulationData(); + auto actualCell = actualData.getObjectRef(objectId).getCellRef(); + return actualData.getCreatureRef(actualCell._creatureId); + } }; diff --git a/source/EngineTests/NeuronMutationTests.cpp b/source/EngineTests/NeuronMutationTests.cpp index 63ce1e750..7d4d19b1e 100644 --- a/source/EngineTests/NeuronMutationTests.cpp +++ b/source/EngineTests/NeuronMutationTests.cpp @@ -15,9 +15,6 @@ class NeuronMutationTests : public MutationTestsBase bool compareAllExceptNeuronWeights(GenomeDesc expected, GenomeDesc actual) { auto reset = [](GenomeDesc& genome) { - genome._lineageId = 0; - genome._prevLineageId = std::nullopt; - genome._accumulatedMutations = 0.0f; for (auto& gene : genome._genes) { for (auto& node : gene._nodes) { std::fill(node._neuralNetwork._weights.begin(), node._neuralNetwork._weights.end(), 0.0f); @@ -32,9 +29,6 @@ class NeuronMutationTests : public MutationTestsBase bool compareAllExceptNeuronBiases(GenomeDesc expected, GenomeDesc actual) { auto reset = [](GenomeDesc& genome) { - genome._lineageId = 0; - genome._prevLineageId = std::nullopt; - genome._accumulatedMutations = 0.0f; for (auto& gene : genome._genes) { for (auto& node : gene._nodes) { std::fill(node._neuralNetwork._biases.begin(), node._neuralNetwork._biases.end(), 0.0f); @@ -49,9 +43,6 @@ class NeuronMutationTests : public MutationTestsBase bool compareAllExceptActivationFunctions(GenomeDesc expected, GenomeDesc actual) { auto reset = [](GenomeDesc& genome) { - genome._lineageId = 0; - genome._prevLineageId = std::nullopt; - genome._accumulatedMutations = 0.0f; for (auto& gene : genome._genes) { for (auto& node : gene._nodes) { std::fill(node._neuralNetwork._activationFunctions.begin(), node._neuralNetwork._activationFunctions.end(), ActivationFunction_Identity); diff --git a/source/EngineTests/ReconnectorTests.cpp b/source/EngineTests/ReconnectorTests.cpp index 7b47ea872..8d8db3221 100644 --- a/source/EngineTests/ReconnectorTests.cpp +++ b/source/EngineTests/ReconnectorTests.cpp @@ -36,8 +36,8 @@ class ReconnectorTests : public IntegrationTestFramework .color(color) .type(CellDesc().signal({1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})), // Signal on connected cell will propagate }, - CreatureDesc(), - GenomeDesc().lineageId(lineageId)); + CreatureDesc().lineageId(lineageId), + GenomeDesc()); data.addConnection(1, 2); return data; } @@ -54,8 +54,8 @@ class ReconnectorTests : public IntegrationTestFramework .color(color) .type(CellDesc().signal({-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})), // Signal on connected cell will propagate }, - CreatureDesc(), - GenomeDesc().lineageId(lineageId)); + CreatureDesc().lineageId(lineageId), + GenomeDesc()); data.addConnection(1, 2); return data; } @@ -407,8 +407,8 @@ TEST_F(ReconnectorTests, creatureMode_relatedLineage_success) ObjectDesc().id(10).pos({99.0f, 100.0f}), ObjectDesc().id(11).pos({98.0f, 100.0f}), }, - CreatureDesc(), - GenomeDesc().lineageId(5)); + CreatureDesc().lineageId(5), + GenomeDesc()); data.addConnection(10, 11); _simulationFacade->setSimulationData(data); @@ -429,8 +429,8 @@ TEST_F(ReconnectorTests, creatureMode_relatedLineage_failed) ObjectDesc().id(10).pos({99.0f, 100.0f}), ObjectDesc().id(11).pos({98.0f, 100.0f}), }, - CreatureDesc(), - GenomeDesc().lineageId(6)); + CreatureDesc().lineageId(6), + GenomeDesc()); data.addConnection(10, 11); _simulationFacade->setSimulationData(data); @@ -451,8 +451,8 @@ TEST_F(ReconnectorTests, creatureMode_unrelatedLineage_success) ObjectDesc().id(10).pos({99.0f, 100.0f}), ObjectDesc().id(11).pos({98.0f, 100.0f}), }, - CreatureDesc(), - GenomeDesc().lineageId(6)); + CreatureDesc().lineageId(6), + GenomeDesc()); data.addConnection(10, 11); _simulationFacade->setSimulationData(data); @@ -473,8 +473,8 @@ TEST_F(ReconnectorTests, creatureMode_unrelatedLineage_failed) ObjectDesc().id(10).pos({99.0f, 100.0f}), ObjectDesc().id(11).pos({98.0f, 100.0f}), }, - CreatureDesc(), - GenomeDesc().lineageId(5)); + CreatureDesc().lineageId(5), + GenomeDesc()); data.addConnection(10, 11); _simulationFacade->setSimulationData(data); diff --git a/source/EngineTests/SensorTests.cpp b/source/EngineTests/SensorTests.cpp index 1054e52c2..5b062c4b6 100644 --- a/source/EngineTests/SensorTests.cpp +++ b/source/EngineTests/SensorTests.cpp @@ -1504,13 +1504,13 @@ TEST_F(SensorTests, detectCreature_restrictToLineage_relatedLineage_found) SensorDesc().autoTrigger(true).mode(DetectCreatureDesc().restrictToLineage(LineageRestriction_RelatedLineage)))), ObjectDesc().id(2).pos({101.0f, 100.0f}), }, - CreatureDesc().id(0), - GenomeDesc().lineageId(42)); + CreatureDesc().id(0).lineageId(42), + GenomeDesc()); data.addConnection(1, 2); // Create a large creature with same lineage auto creatureData = createCreature(); - creatureData._genomes.front()._lineageId = 42; + creatureData._creatures.front()._lineageId = 42; data.add(std::move(creatureData)); _simulationFacade->setSimulationData(data); @@ -1534,13 +1534,13 @@ TEST_F(SensorTests, detectCreature_restrictToLineage_relatedLineage2_found) SensorDesc().autoTrigger(true).mode(DetectCreatureDesc().restrictToLineage(LineageRestriction_RelatedLineage)))), ObjectDesc().id(2).pos({101.0f, 100.0f}), }, - CreatureDesc().id(0), - GenomeDesc().lineageId(41).prevLineageId(42)); + CreatureDesc().id(0).lineageId(41).prevLineageId(42), + GenomeDesc()); data.addConnection(1, 2); // Create a large creature with same lineage auto creatureData = createCreature(); - creatureData._genomes.front().lineageId(43).prevLineageId(42); + creatureData._creatures.front().lineageId(43).prevLineageId(42); data.add(std::move(creatureData)); _simulationFacade->setSimulationData(data); @@ -1565,13 +1565,13 @@ TEST_F(SensorTests, detectCreature_restrictToLineage_relatedLineage_notFound) SensorDesc().autoTrigger(true).mode(DetectCreatureDesc().restrictToLineage(LineageRestriction_RelatedLineage)))), ObjectDesc().id(2).pos({101.0f, 100.0f}), }, - CreatureDesc().id(0), - GenomeDesc().lineageId(42)); + CreatureDesc().id(0).lineageId(42), + GenomeDesc()); data.addConnection(1, 2); // Create a large creature with different lineage auto creatureData = createCreature(); - creatureData._genomes.front()._lineageId = 41; + creatureData._creatures.front()._lineageId = 41; data.add(std::move(creatureData)); _simulationFacade->setSimulationData(data); @@ -1594,13 +1594,13 @@ TEST_F(SensorTests, detectCreature_restrictToLineage_unrelatedLineage_found) SensorDesc().autoTrigger(true).mode(DetectCreatureDesc().restrictToLineage(LineageRestriction_UnrelatedLineage)))), ObjectDesc().id(2).pos({101.0f, 100.0f}), }, - CreatureDesc().id(0), - GenomeDesc().lineageId(42)); + CreatureDesc().id(0).lineageId(42), + GenomeDesc()); data.addConnection(1, 2); // Create a large creature with different lineage auto creatureData = createCreature(); - creatureData._genomes.front()._lineageId = 41; + creatureData._creatures.front()._lineageId = 41; data.add(std::move(creatureData)); _simulationFacade->setSimulationData(data); @@ -1624,13 +1624,13 @@ TEST_F(SensorTests, detectCreature_restrictToLineage_unrelatedLineage_notFound) SensorDesc().autoTrigger(true).mode(DetectCreatureDesc().restrictToLineage(LineageRestriction_UnrelatedLineage)))), ObjectDesc().id(2).pos({101.0f, 100.0f}), }, - CreatureDesc().id(0), - GenomeDesc().lineageId(42)); + CreatureDesc().id(0).lineageId(42), + GenomeDesc()); data.addConnection(1, 2); // Create a large creature with same lineage auto creatureData = createCreature(); - creatureData._genomes.front()._lineageId = 42; + creatureData._creatures.front()._lineageId = 42; data.add(std::move(creatureData)); _simulationFacade->setSimulationData(data); diff --git a/source/Gui/GenomeEditorWidget.cpp b/source/Gui/GenomeEditorWidget.cpp index 3412bff56..10298e2be 100644 --- a/source/Gui/GenomeEditorWidget.cpp +++ b/source/Gui/GenomeEditorWidget.cpp @@ -75,9 +75,6 @@ void _GenomeEditorWidget::processHeaderData() AlienGui::Group(AlienGui::GroupParameters().text("Base properties and info")); AlienGui::InputText(AlienGui::InputTextParameters().name("Genome name").textWidth(rightColumnWidth), _editData->genome._name); - if (AlienGui::InputInt(AlienGui::InputIntParameters().name("Lineage").textWidth(rightColumnWidth), _editData->genome._lineageId)) { - _editData->genome._prevLineageId.reset(); - } auto numNodesString = std::to_string(GenomeDescInfoService::get().getNumberOfNodes(_editData->genome)); AlienGui::InputText(AlienGui::InputTextParameters().name("Node count").readOnly(true).textWidth(rightColumnWidth), numNodesString); @@ -103,15 +100,6 @@ void _GenomeEditorWidget::processHeaderData() MutationRatesWidget::process(_editData->genome._mutationRates, rightColumnWidth); AlienGui::Checkbox(AlienGui::CheckboxParameters().name("Apply meta-mutations").textWidth(rightColumnWidth), _editData->genome._applyMetaMutations); - AlienGui::SliderFloat( - AlienGui::SliderFloatParameters() - .name("Accumulated mutations") - .format("%.5f") - .min(0.0f) - .max(10000.0f) - .logarithmic(true) - .textWidth(rightColumnWidth), - &_editData->genome._accumulatedMutations); table.next(); diff --git a/source/Gui/InspectionWindow.cpp b/source/Gui/InspectionWindow.cpp index bea42eee9..ef5bf074b 100644 --- a/source/Gui/InspectionWindow.cpp +++ b/source/Gui/InspectionWindow.cpp @@ -235,11 +235,11 @@ void _InspectionWindow::process() auto width = calcWindowWidth(); float height; if (_creatureMode) { - height = StyleRepository::get().scale(280.0f); - } else if (isObject()) { - height = StyleRepository::get().scale(500.0f); + height = scale(295.0f); + } else if (isExtendedObject()) { + height = scale(500.0f); } else { - height = StyleRepository::get().scale(180.0f); + height = scale(180.0f); } auto borderlessRendering = _SimulationFacade::get()->getSimulationParameters().borderlessRendering.value; ImGui::SetNextWindowBgAlpha(Const::WindowAlpha * ImGui::GetStyle().Alpha); @@ -251,9 +251,13 @@ void _InspectionWindow::process() ImGui::SetScrollY(*_savedScrollY); } auto windowPos = ImGui::GetWindowPos(); - if (isObject()) { + if (isExtendedObject()) { auto extendedObject = std::get(entity); - processObject(extendedObject); + if (_creatureMode) { + processCreature(extendedObject); + } else { + processObject(extendedObject); + } EditorModel::get().addInspectedEntity(extendedObject); } else { processParticle(std::get(entity)); @@ -262,7 +266,7 @@ void _InspectionWindow::process() _isFirstFrame = false; ImDrawList* drawList = ImGui::GetBackgroundDrawList(); auto entityPos = Viewport::get().mapWorldToViewPosition(DescEditService::get().getPos(entity), borderlessRendering); - auto factor = StyleRepository::get().scale(1); + auto factor = scale(1); drawList->AddLine({windowPos.x + 15.0f * factor, windowPos.y - 5.0f * factor}, {entityPos.x, entityPos.y}, Const::InspectorLineColor, 1.5f); drawList->AddRectFilled( @@ -283,7 +287,7 @@ uint64_t _InspectionWindow::getId() const return _entityId; } -bool _InspectionWindow::isObject() const +bool _InspectionWindow::isExtendedObject() const { auto entity = EditorModel::get().getInspectedEntity(_entityId); return std::holds_alternative(entity); @@ -296,7 +300,7 @@ std::string _InspectionWindow::generateTitle() const auto entity = EditorModel::get().getInspectedEntity(_entityId); auto const& creature = std::get(entity).creature; ss << "Creature with id 0x" << std::hex << std::uppercase << (creature.has_value() ? creature->_id : _entityId); - } else if (isObject()) { + } else if (isExtendedObject()) { ss << "Cell with id 0x" << std::hex << std::uppercase << _entityId; } else { ss << "Energy particle with id 0x" << std::hex << std::uppercase << _entityId; @@ -304,17 +308,23 @@ std::string _InspectionWindow::generateTitle() const return ss.str(); } -void _InspectionWindow::processObject(ExtendedObjectDesc& extendedObject) +void _InspectionWindow::processCreature(ExtendedObjectDesc& extendedObject) { - if (_creatureMode) { - if (extendedObject.creature.has_value() && extendedObject.genome.has_value()) { - processCreatureProperties(extendedObject); + if (extendedObject.creature.has_value() && extendedObject.genome.has_value()) { + auto origCreature = extendedObject.creature; + processCreatureProperties(extendedObject); + DescValidationService::get().validateAndCorrect(extendedObject); + if (extendedObject.creature != origCreature) { + _SimulationFacade::get()->changeCell(extendedObject); } - return; } +} +void _InspectionWindow::processObject(ExtendedObjectDesc& extendedObject) +{ auto& object = extendedObject.object; auto origObject = object; + auto origCreature = extendedObject.creature; AlienGui::DynamicTableLayout table(TableColumnWidth); if (table.begin()) { @@ -349,10 +359,10 @@ void _InspectionWindow::processObject(ExtendedObjectDesc& extendedObject) table.end(); } - DescValidationService::get().validateAndCorrect(object); + DescValidationService::get().validateAndCorrect(extendedObject); applyPendingSignalEntries(extendedObject); - if (object != origObject) { + if (object != origObject || extendedObject.creature != origCreature) { _SimulationFacade::get()->changeCell(extendedObject); } } @@ -564,11 +574,11 @@ void _InspectionWindow::processCreatureProperties(ExtendedObjectDesc& extendedOb inspectorHexId("Creature id", creature._id); inspectorText("Generation", std::to_string(creature._generation)); inspectorText("Num cells", std::to_string(creature._numCells)); + AlienGui::InputInt(AlienGui::InputIntParameters().name("Lineage id").textWidth(TextWidth), creature._lineageId); + AlienGui::InputOptionalInt(AlienGui::InputIntParameters().name("Prev lineage id").textWidth(TextWidth), creature._prevLineageId); + AlienGui::InputFloat(AlienGui::InputFloatParameters().name("Accumulated mutations").format("%.5f").textWidth(TextWidth), creature._accumulatedMutations); auto& genome = extendedObject.genome.value(); - std::stringstream frontAngle; - frontAngle << std::fixed << std::setprecision(1) << genome._frontAngle; inspectorText("Genome name", genome._name); - inspectorText("Lineage id", std::to_string(genome._lineageId)); inspectorText("Resistance to injection", genome._resistanceToInjection ? "Yes" : "No"); inspectorText("Apply meta-mutations", genome._applyMetaMutations ? "Yes" : "No"); if (AlienGui::Button(AlienGui::ButtonParameters().buttonText("Edit").name("Edit genome").textWidth(TextWidth))) { @@ -870,7 +880,7 @@ float _InspectionWindow::calcWindowWidth() const if (_creatureMode) { return StyleRepository::get().scale(CreatureWindowWidth); } - if (isObject()) { + if (isExtendedObject()) { return StyleRepository::get().scale(CellWindowWidth); } return StyleRepository::get().scale(ParticleWindowWidth); diff --git a/source/Gui/InspectionWindow.h b/source/Gui/InspectionWindow.h index a9afb7b27..1f0f8b8c2 100644 --- a/source/Gui/InspectionWindow.h +++ b/source/Gui/InspectionWindow.h @@ -21,10 +21,11 @@ class _InspectionWindow uint64_t getId() const; private: - bool isObject() const; + bool isExtendedObject() const; std::string generateTitle() const; void processObject(ExtendedObjectDesc& extendedObject); + void processCreature(ExtendedObjectDesc& extendedObject); void processParticle(EnergyDesc particle); void applyPendingSignalEntries(ExtendedObjectDesc& extendedObject); diff --git a/source/PersisterInterface/SerializerService.cpp b/source/PersisterInterface/SerializerService.cpp index a23b444aa..75635dba1 100644 --- a/source/PersisterInterface/SerializerService.cpp +++ b/source/PersisterInterface/SerializerService.cpp @@ -284,9 +284,6 @@ namespace auto constexpr Id_Genome_Id = 0; auto constexpr Id_Genome_Name = 1; auto constexpr Id_Genome_FrontAngle = 2; - auto constexpr Id_Genome_LineageId = 3; - auto constexpr Id_Genome_AccumulatedMutations = 4; - auto constexpr Id_Genome_PrevLineageId = 5; auto constexpr Id_Genome_ResistanceToInjection = 6; auto constexpr Id_Genome_ApplyMetaMutations = 7; @@ -1030,9 +1027,6 @@ namespace cereal auto scope = getSerializationScope(task, ar); scope.addMember(Id_Genome_Id, data._id, defaultObject._id); scope.addMember(Id_Genome_Name, data._name, defaultObject._name); - scope.addMember(Id_Genome_LineageId, data._lineageId, defaultObject._lineageId); - scope.addMember(Id_Genome_AccumulatedMutations, data._accumulatedMutations, defaultObject._accumulatedMutations); - scope.addMember(Id_Genome_PrevLineageId, data._prevLineageId, defaultObject._prevLineageId); scope.addMember(Id_Genome_FrontAngle, data._frontAngle, defaultObject._frontAngle); scope.addMember(Id_Genome_ResistanceToInjection, data._resistanceToInjection, defaultObject._resistanceToInjection); scope.addMember(Id_Genome_ApplyMetaMutations, data._applyMetaMutations, defaultObject._applyMetaMutations); @@ -1060,6 +1054,9 @@ namespace auto constexpr Id_Creature_HeadUpdateId = 5; auto constexpr Id_Creature_GenomeId = 6; auto constexpr Id_Creature_MutationState = 7; + auto constexpr Id_Creature_LineageId = 3; + auto constexpr Id_Creature_PrevLineageId = 8; + auto constexpr Id_Creature_AccumulatedMutations = 9; auto constexpr Id_Solid_Energy = 0; @@ -1789,6 +1786,9 @@ namespace cereal scope.addMember(Id_Creature_HeadUpdateId, data._headUpdateId, defaultObject._headUpdateId); scope.addMember(Id_Creature_GenomeId, data._genomeId, defaultObject._genomeId); scope.addMember(Id_Creature_MutationState, data._mutationState, defaultObject._mutationState); + scope.addMember(Id_Creature_LineageId, data._lineageId, defaultObject._lineageId); + scope.addMember(Id_Creature_PrevLineageId, data._prevLineageId, defaultObject._prevLineageId); + scope.addMember(Id_Creature_AccumulatedMutations, data._accumulatedMutations, defaultObject._accumulatedMutations); } SPLIT_SERIALIZATION(CreatureDesc)