diff --git a/source/EngineInterface/DescValidationService.cpp b/source/EngineInterface/DescValidationService.cpp index 54e682f46..3a72c4835 100644 --- a/source/EngineInterface/DescValidationService.cpp +++ b/source/EngineInterface/DescValidationService.cpp @@ -284,8 +284,10 @@ void DescValidationService::validateAndCorrect(GenomeDesc& genome) } } - // Validate optional constructor field (void cells cannot have a constructor) - if (nodeType == CellType_Void) { + // Validate optional constructor field. A void node normally cannot have a constructor, but in a homogeneous gene the + // effective cell type is taken from the first node, so a void node is actually expressed as that type and keeps its + // constructor (see MutationProcessor::applyMutations and ConstructorProcessor::createConstructionData). + if (nodeType == CellType_Void && !gene._homogeneousCellType) { node._constructor = std::nullopt; } else if (node._constructor.has_value()) { auto& constructor = node._constructor.value(); diff --git a/source/EngineInterfaceTests/DescValidationServiceTests.cpp b/source/EngineInterfaceTests/DescValidationServiceTests.cpp index 9ec3c8a59..8f66ce69f 100644 --- a/source/EngineInterfaceTests/DescValidationServiceTests.cpp +++ b/source/EngineInterfaceTests/DescValidationServiceTests.cpp @@ -29,6 +29,23 @@ TEST_F(DescValidationServiceTests, genome_removesConstructorFromVoidCell) EXPECT_FALSE(genome._genes.at(0)._nodes.at(1)._constructor.has_value()); } +TEST_F(DescValidationServiceTests, genome_keepsConstructorOnVoidCellInHomogeneousGene) +{ + // In a homogeneous gene the effective cell type comes from the first node, so a void node is expressed as that type + // and legitimately keeps its constructor (matching ConstructorProcessor and MutationProcessor). + auto genome = GenomeDesc().genes({ + GeneDesc().homogeneousCellType(true).nodes({ + NodeDesc(), + NodeDesc().cellType(VoidGenomeDesc()).constructor(ConstructorGenomeDesc().geneIndex(0).separation(true)), + NodeDesc(), + }), + }); + + _descValidationService.validateAndCorrect(genome); + + EXPECT_TRUE(genome._genes.at(0)._nodes.at(1)._constructor.has_value()); +} + TEST_F(DescValidationServiceTests, genome_keepsConstructorOnNonVoidCell) { auto genome = GenomeDesc().genes({