void CreatureEvolver::AttachmentPositionMutate_Parent(Vec3f &position) { position.x = Clamp(position.x + Randf(-m_maxRelativeOffsetRatioPerturbation, m_maxRelativeOffsetRatioPerturbation), 0.0f, 1.0f); // x position always positive, so doesn't loop back on self too badly position.y = Clamp(position.y + Randf(-m_maxRelativeOffsetRatioPerturbation, m_maxRelativeOffsetRatioPerturbation), -1.0f, 1.0f); position.z = Clamp(position.z + Randf(-m_maxRelativeOffsetRatioPerturbation, m_maxRelativeOffsetRatioPerturbation), -1.0f, 1.0f); // If none are at limits, set one to limit if(position.x != 1.0f && position.y != 1.0f && position.y != -1.0f && position.z != 1.0f && position.z != -1.0f) { switch(rand() % 6) { case 0: // No negative x, only positive (or else loops back on self) case 1: position.x = 1.0f; break; case 2: position.y = 1.0f; break; case 3: position.y = -1.0f; break; case 4: position.z = 1.0f; break; case 5: position.z = -1.0f; break; } } }
void CreatureEvolver::AttachmentPositionInit_Parent(Vec3f &position) { position.x = Randf(0.0f, 1.0f); // x position always positive, so doesn't loop back on self too badly position.y = Randf(-1.0f, 1.0f); position.z = Randf(-1.0f, 1.0f); // If none are at limits, set one to limit if(position.x != 1.0f && position.y != 1.0f && position.y != -1.0f && position.z != 1.0f && position.z != -1.0f) { switch(rand() % 6) { case 0: // No negative x, only positive (or else loops back on self) case 1: position.x = 1.0f; break; case 2: position.y = 1.0f; break; case 3: position.y = -1.0f; break; case 4: position.z = 1.0f; break; case 5: position.z = -1.0f; break; } } }
void SceneObject_VirtualCreatureSimulator::CreatePhenotypes() { assert(GetScene() != NULL); assert(m_pPhenotypes.empty()); assert(m_startingPositions.empty()); assert(m_fitnesses.empty()); assert(m_evolver.GetNumCreatures() != 0); m_pPhenotypes.clear(); m_pPhenotypes.reserve(m_evolver.GetNumCreatures()); m_startingPositions.reserve(m_evolver.GetNumCreatures()); m_fitnesses.assign(m_evolver.GetNumCreatures(), 0.0f); for(unsigned int i = 0, size = m_evolver.GetNumCreatures(); i < size; i++) { CreatureAndTracker creatureAndTracker; creatureAndTracker.m_pCreature = new SceneObject_Creature(); creatureAndTracker.m_tracker.Set(creatureAndTracker.m_pCreature); m_pPhenotypes.push_back(creatureAndTracker); btTransform trans; trans.setIdentity(); m_startingPositions.push_back(Vec3f(Randf() * 192.0f + 32.0f, 12.0f, Randf() * 192.0f + 32.0f)); trans.setOrigin(bt(m_startingPositions[i])); GetScene()->Add(creatureAndTracker.m_pCreature, true); creatureAndTracker.m_pCreature->CreateFromGenes(*m_evolver.GetGenotype(i), trans); } }
/// Initialize with random seed. void Random::Init(int64 seed) { x = seed * 3; y = seed * 7; z = seed * 15; w = seed * 16; p = seed % 15 + 1; s[0] = seed; s[1] = 1181783497276652981; for (int i = 2; i < XOR_SHIFT_STAR_VALUES; ++i) { s[i] = i; } // std::cout<<"\nInitial values: "; for (int i = 0; i < XOR_SHIFT_STAR_VALUES; ++i) { // std::cout<<"\n"<<i<<": "<<s[i]; } /// Randomize it a few times to get it started? for (int i = 0; i < XOR_SHIFT_STAR_VALUES * 3 + seed % 50; ++i) { Randf(1.f); // std::cout<<"\nRandf: "<<Randf(1.f); } }
unsigned int CreatureEvolver::RouletteSelection() { // Get the random value to overcome float randomCusp = Randf() * m_totalFitness - 0.005f; // Subtract small amount to avoid error due to precision issues float fitnessSum = 0.0f; for(std::list<FitnessInfo>::iterator it = m_fitnesses.begin(); it != m_fitnesses.end(); it++) { fitnessSum += (*it).m_fitness; if(fitnessSum >= randomCusp) { // Found the member. Remove the member from the array so it cannot be re-chosen. // The member's fitness will be re-added in the next generation when new fitness values are loaded after simulation. // In addition, update the total fitness so that the next selection will function properly. This, too, is updated when // new fitness values are loaded. int index = (*it).m_creatureIndex; m_totalFitness -= (*it).m_fitness; m_fitnesses.erase(it); return index; } } std::cerr << "Was unable to find a creature!" << std::endl; abort(); return 0; }
DynamicTileProperty::DynamicTileProperty(Tile* tile) : m_tileToUpdate(tile) , m_age(0.f) , m_whenToFlip(0.f) { m_whenToFlip = Randf(1.5f, 2.2f); m_possibleWaterColors = { RGBA(0x76, 0x01, 0xff, 0xAA), RGBA(0x00, 0x36, 0xff, 0xAA), RGBA(0x48, 0x4c, 0xea, 0xAA), RGBA(0x00, 0x78, 0xff, 0xAA) }; if (tile->GetCurrentTileType() == TILE_LAVA) { m_age = Randf(0.f, 10.f); } }
void CreatureEvolver::Generation() { assert(m_fitnesses.size() == m_populationSize); // Get elites std::vector<CreatureGenes> eliteGenes; std::vector<unsigned int> chumpIndices; FindElites(eliteGenes); RemoveChumps(chumpIndices); GetTotalFitness(); // Obtain their genes from the neuron data CreatureGenes* pGene1, * pGene2; //float halfNumFitnesses = static_cast<float>(m_fitnesses.size()) / 2.0f; while(m_fitnesses.size() >= 2) { // Choose the two members to procreate by index unsigned int index1 = RouletteSelection(); unsigned int index2 = RouletteSelection(); pGene1 = m_genotypePopulation[index1]; pGene2 = m_genotypePopulation[index2]; // Determine whether should crossover if(Randf() < m_crossoverRate) // if(Randf() * halfNumFitnesses < m_crossoverRate) Crossover(pGene1, pGene2); //halfNumFitnesses -= 1.0f; // Mutate both chromosomes Mutate(pGene1); Mutate(pGene2); } // Replace chumps with elites for(unsigned int i = 0; i < m_numElites; i++) { #ifdef MUTATE_ELITES Mutate(&eliteGenes[i]); #endif (*m_genotypePopulation[chumpIndices[i]]) = eliteGenes[i]; } }
Particle_Sprite* SceneObject_ParticleEmitter_Sprite::EmitParticle() { assert(GetScene() != NULL); Particle_Sprite* pParticle = new Particle_Sprite(); pParticle->m_pScene = GetScene(); // Select random sprite assert(!m_sprites.empty()); int index = rand() % m_sprites.size(); pParticle->m_pSprite = &m_sprites[index].m_sprite; pParticle->m_radius = m_sprites[index].m_radius; pParticle->m_despawnTime = Randf(m_minDespawnTime, m_maxDespawnTime); SetParticle(pParticle); return pParticle; }
// 变异 void CGA::Mut() { for ( int i = 0; i < m_vecChromosomes.size(); ++ i ) { float fRate = Randf(); if ( fRate <= m_fpMutRate ) { // 为每个染色体产生一个随机的变异位置(基因,哪个点) // 为该基因(点)随机生成一个坐标,来代替之前的基因 // 随机位置的范围[0, 点个数 - 1] int nRandPos = Rand(0, g_graph.graph.numVertexes - 1); int nRandX = Rand(m_nXBegin, m_nXEnd); int nRandY = Rand(m_nYBegin, m_nYEnd); Gene gene; gene.nX = nRandX; gene.nY = nRandY; m_vecChromosomes[ i ].SetGene(nRandPos, gene); } } }
void CreatureEvolver::AttachmentPositionMutate_This(Vec3f &position) { position.x = -1.0f; // Doesn't change position.y = Clamp(position.y + Randf(-m_maxRelativeOffsetRatioPerturbation, m_maxRelativeOffsetRatioPerturbation), -1.0f, 1.0f); position.z = Clamp(position.z + Randf(-m_maxRelativeOffsetRatioPerturbation, m_maxRelativeOffsetRatioPerturbation), -1.0f, 1.0f); }
void CreatureEvolver::AttachmentPositionInit_This(Vec3f &position) { position.x = -1.0f; position.y = Randf(-1.0f, 1.0f); position.z = Randf(-1.0f, 1.0f); }
bool BgEffectTile::ShouldChangeDir() const { return Randf(0, 1) < ConfigManager::GetFloat("[Bg Effect]fChangeDirChance"); }
void CGA::Cross() { // 种群中染色体个数 int nSize = m_vecChromosomes.size(); // 先把当前种群拷贝出来 ChromosomeGroup groupCopy(m_vecChromosomes.begin(), m_vecChromosomes.end()); // 相邻染色体两两杂交 for ( int i = 0; i < ( m_vecChromosomes.size() / 2 ) * 2; i += 2 ) { #if 0 float fRate = 0.0F; #else float fRate = Randf(); #endif if ( fRate <= m_fpCrossRate ) { // 计算i 和 i + 1中 // 记录该染色体中每个基因(点V)与给定向量(V1V2), 向量V1V 在向量 V1V2上的投影的长度 和 该点V的索引 std::vector<Index2Dist> vecIndeies1; auto genes = m_vecChromosomes[ i ].GetGenes(); for (int index = 0; index < genes.size(); ++ index ) { int nVX = genes[ index ].nX; int nVY = genes[ index ].nY; int nV1X = 10; int nV1Y = 2000; int nV2X = 10; int nV2Y = -2000; // 向量V1V(nVX - nV1X, nVY - nV1Y) // 向量V1V2(nV2X - nV1X, nV1Y - nV2Y) int x1 = nVX - nV1X; int y1 = nVY - nV1Y; int x2 = nV2X - nV1X; int y2 = nV2Y - nV1Y; // 计算V1V与V1V2 float fArcCos = (x1 * x2 + y1 * y2) / ( sqrt(1.0F * x1 * x1 + y1 * y1) * sqrt(1.0F * x2 * x2 + y2 * y2) ); // 投影 = |V1V| * cosX float fLength = sqrt( 1.0F * x1 * x1 + y1 * y1 ) * fArcCos; Index2Dist id; id.nIndex = index; id.fDist = fLength; id.gene = genes[ index ]; vecIndeies1.push_back(id); } // for // 按照fDist排序 std::sort(vecIndeies1.begin(), vecIndeies1.end()); ////////////////////////////////////////////////////////////////////////// // 记录该染色体中每个基因(点V)与给定向量(V1V2), 向量V1V 在向量 V1V2上的投影的长度 和 该点V的索引 std::vector<Index2Dist> vecIndeies2; auto genes2 = m_vecChromosomes[ i + 1 ].GetGenes(); for (int index = 0; index < genes2.size(); ++ index ) { int nVX = genes2[ index ].nX; int nVY = genes2[ index ].nY; int nV1X = 100; int nV1Y = 1000; int nV2X = 100; int nV2Y = -1000; // 向量V1V(nVX - nV1X, nVY - nV1Y) // 向量V1V2(nV2X - nV1X, nV1Y - nV2Y) int x1 = nVX - nV1X; int y1 = nVY - nV1Y; int x2 = nV2X - nV1X; int y2 = nV2Y - nV1Y; // 计算V1V与V1V2 float fArcCos = (x1 * x2 + y1 * y2) / ( sqrt(1.0F * x1 * x1 + y1 * y1) * sqrt(1.0F * x2 * x2 + y2 * y2) ); // 投影 = |V1V| * cosX float fLength = sqrt( 1.0F * x1 * x1 + y1 * y1 ) * fArcCos; Index2Dist id; id.nIndex = index; id.fDist = fLength; id.gene = genes2[ index ]; vecIndeies2.push_back(id); } // for // 按照dist从小到大排序 std::sort(vecIndeies2.begin(), vecIndeies2.end()); // 杂交后的两个新个体(染色体) GeneGroup g1, g2; // 拷贝两个排序后的vec std::vector<Index2Dist> vec1Copy(vecIndeies1.begin(), vecIndeies1.end()); std::vector<Index2Dist> vec2Copy(vecIndeies2.begin(), vecIndeies2.end()); int cnt1 = 0; int cnt2 = vecIndeies2.size() - 1; for ( ; cnt1 < vecIndeies1.size() && cnt2 >= 0 && g1.size() < vecIndeies1.size(); ++ cnt1, -- cnt2 ) { auto it1 = std::find(g1.begin(), g1.end(), vecIndeies1[ cnt1 ].gene ); if ( it1 == g1.end() ) { g1.push_back( vecIndeies1[ cnt1 ].gene ); auto itTemp = std::find(vec1Copy.begin(), vec1Copy.end(), vecIndeies1[ cnt1 ].gene); if ( itTemp != vec1Copy.end() ) { vec1Copy.erase(itTemp); } } auto it2 = std::find(g1.begin(), g1.end(), vecIndeies2[ cnt2 ].gene ); if ( it2 == g1.end() ) { g1.push_back( vecIndeies2[ cnt2 ].gene); auto itTemp = std::find(vec2Copy.begin(), vec2Copy.end(), vecIndeies2[ cnt2 ].gene); if ( itTemp != vec2Copy.end() ) { vec2Copy.erase(itTemp); } } } // for // 将vec1Copy 和 vec2Copy 中剩余的点放入g2 for ( auto iter = vec1Copy.begin(); iter != vec1Copy.end(); ++ iter ) { g2.push_back(iter->gene); } for ( auto iter = vec2Copy.begin(); iter != vec2Copy.end(); ++ iter ) { g2.push_back(iter->gene); } // 用新个体代替两个父个体 // g1代替i位置染色体, g2代替i+1位置染色体 m_vecChromosomes[ i ].SetGenes(g1); m_vecChromosomes[ i + 1 ].SetGenes(g2); } // if } // for }
float Randf(float pl_min,float pl_max) { float dif = pl_max - pl_min; return Randf() * dif + pl_min; }
/// Returns a random value between 0 and max (inclusive) uint32 Random::Randi(uint32 max) { uint32 lall = Randf(max); assert(lall <= max); return lall; }
void CreatureEvolver::InitGenes(LimbGenes* pGenes, unsigned int index) { if(index != 0) // Not root pGenes->m_parentIndexOffset = rand() % index + 1; else pGenes->m_parentIndexOffset = -1; if(Randf() < m_initRecursiveLimbChance) pGenes->m_recursiveUnits = rand() % (m_maxInitRecursiveUnits - m_minInitRecursiveUnits) + m_minInitRecursiveUnits; else pGenes->m_recursiveUnits = 0; pGenes->m_symmetrical = Randf() < m_initSymetricalLimbChance; pGenes->m_inheritsRecursion = Randf() < m_initInheritRecursionChance; pGenes->m_inheritsSymmetry = Randf() < m_initInheritSymmetryChance; pGenes->m_numBranches = rand() % m_maxNumBranches; pGenes->m_dims.x = Randf(m_minLimbDimension, m_maxLimbDimension); pGenes->m_dims.y = Randf(m_minLimbDimension, m_maxLimbDimension); pGenes->m_dims.z = Randf(m_minLimbDimension, m_maxLimbDimension); AttachmentPositionInit_Parent(pGenes->m_relativeAttachmentPositionOnParent); Quaternion normalQuat(pGenes->m_relativeAttachmentPositionOnParent); AttachmentPositionInit_This(pGenes->m_relativeAttachmentPositionOnThis); pGenes->m_bendLimit = Randf() * m_maxLimbBend; pGenes->m_twistLimit = Randf() * m_maxLimbTwist; // Random axis, rotate around it Quaternion perturbedNormal(0.0f, 1.0f, 0.0f, 0.0f); // Set relative rotation as normal to surface Vec3f axis(Randf(-1.0f, 1.0f), Randf(-1.0f, 1.0f), Randf(-1.0f, 1.0f)); axis.NormalizeThis(); perturbedNormal.Rotate(Randf() * pGenes->m_bendLimit, axis); pGenes->m_relativeRotation = normalQuat * perturbedNormal; pGenes->m_density = Randf(m_minDensity, m_maxDensity); pGenes->m_friction = Randf(m_minFriction, m_maxFriction); pGenes->m_strength = Randf(m_minLimbStrength, m_maxLimbStrength); pGenes->m_hasContactSensor = Randf() < m_initContactSensorChance; pGenes->m_numTimerSensors = static_cast<int>(Randf(m_minInitTimerCount, m_maxInitTimerCount)); for(int i = 0, numMainBrainInputNeurons = rand() % m_maxNumMainBrainInputNeurons; i < numMainBrainInputNeurons; i++) pGenes->m_mainBrainInputNeurons.push_back(rand() % (m_maxNumMainBrainInputNeurons + 1)); for(int i = 0, numParentLimbInputNeurons = rand() % m_maxNumParentLimbInputNeurons; i < numParentLimbInputNeurons; i++) pGenes->m_parentLimbInputNeurons.push_back(rand() % (m_maxNumParentLimbInputNeurons + 1)); for(int i = 0, numChildLimbInputNeurons = rand() % m_maxNumChildLimbInputNeurons; i < numChildLimbInputNeurons; i++) { LimbGenes::ChildAndOutputIndex coai; coai.m_childIndex = rand() % m_maxNumBranches; coai.m_outputIndex = rand() % m_maxNumChildLimbInputNeurons; pGenes->m_childLimbInputNeurons.push_back(coai); } // Structure if(m_minHiddenLayers == m_maxHiddenLayers) pGenes->m_numHiddenLayers = m_minHiddenLayers; else pGenes->m_numHiddenLayers = rand() % (m_maxHiddenLayers - m_minHiddenLayers) + m_minHiddenLayers; pGenes->m_numNeuronsPerHiddenLayer = rand() % (m_maxNeuronsPerHiddenLayer - m_minNeuronsPerHiddenLayer) + m_minNeuronsPerHiddenLayer; }
void CreatureEvolver::Crossover(CreatureGenes* pGenes1, CreatureGenes* pGenes2) { // Swap around limbs CrossOver_VaryingSize(pGenes1->m_pLimbGenes, pGenes2->m_pLimbGenes); // Shuffle around if they are below the minimum size if(pGenes1->m_pLimbGenes.size() < static_cast<unsigned>(m_minNumLimbs)) { while(pGenes1->m_pLimbGenes.size() < static_cast<unsigned>(m_minNumLimbs)) { unsigned int randIndex = rand() % pGenes2->m_pLimbGenes.size(); pGenes1->m_pLimbGenes.push_back(pGenes2->m_pLimbGenes[randIndex]); pGenes2->m_pLimbGenes.erase(pGenes2->m_pLimbGenes.begin() + randIndex); } } else if(pGenes2->m_pLimbGenes.size() < static_cast<unsigned>(m_minNumLimbs)) { while(pGenes2->m_pLimbGenes.size() < static_cast<unsigned>(m_minNumLimbs)) { unsigned int randIndex = rand() % pGenes1->m_pLimbGenes.size(); pGenes2->m_pLimbGenes.push_back(pGenes1->m_pLimbGenes[randIndex]); pGenes1->m_pLimbGenes.erase(pGenes1->m_pLimbGenes.begin() + randIndex); } } unsigned int minNumLimbs, maxNumLimbs; std::vector<LimbGenes*>* pLargerGene; if(pGenes1->m_pLimbGenes.size() < pGenes2->m_pLimbGenes.size()) { minNumLimbs = pGenes1->m_pLimbGenes.size(); maxNumLimbs = pGenes2->m_pLimbGenes.size(); pLargerGene = &pGenes2->m_pLimbGenes; } else { maxNumLimbs = pGenes1->m_pLimbGenes.size(); minNumLimbs = pGenes2->m_pLimbGenes.size(); pLargerGene = &pGenes1->m_pLimbGenes; } // For each limb, perform crossovers (partially uniform, partially point) for(unsigned int i = 0; i < minNumLimbs; i++) { // Make sure parent is in bounds if(i != 0) { if(static_cast<signed>(i) - pGenes1->m_pLimbGenes[i]->m_parentIndexOffset < 0) pGenes1->m_pLimbGenes[i]->m_parentIndexOffset = i; if(static_cast<signed>(i) - pGenes2->m_pLimbGenes[i]->m_parentIndexOffset < 0) pGenes2->m_pLimbGenes[i]->m_parentIndexOffset = i; } // Continuity properties if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_symmetrical, pGenes2->m_pLimbGenes[i]->m_symmetrical); if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_recursiveUnits, pGenes2->m_pLimbGenes[i]->m_recursiveUnits); if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_inheritsRecursion, pGenes2->m_pLimbGenes[i]->m_inheritsRecursion); if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_inheritsSymmetry, pGenes2->m_pLimbGenes[i]->m_inheritsSymmetry); if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_numBranches, pGenes2->m_pLimbGenes[i]->m_numBranches); // Dimensions if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_dims.x, pGenes2->m_pLimbGenes[i]->m_dims.x); if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_dims.y, pGenes2->m_pLimbGenes[i]->m_dims.y); if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_dims.z, pGenes2->m_pLimbGenes[i]->m_dims.z); // Joint if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_bendLimit, pGenes2->m_pLimbGenes[i]->m_bendLimit); if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_twistLimit, pGenes2->m_pLimbGenes[i]->m_twistLimit); if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_strength, pGenes2->m_pLimbGenes[i]->m_strength); if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_relativeAttachmentPositionOnParent.x, pGenes2->m_pLimbGenes[i]->m_relativeAttachmentPositionOnParent.x); if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_relativeAttachmentPositionOnParent.y, pGenes2->m_pLimbGenes[i]->m_relativeAttachmentPositionOnParent.y); if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_relativeAttachmentPositionOnParent.z, pGenes2->m_pLimbGenes[i]->m_relativeAttachmentPositionOnParent.z); if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_relativeAttachmentPositionOnThis.x, pGenes2->m_pLimbGenes[i]->m_relativeAttachmentPositionOnThis.x); if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_relativeAttachmentPositionOnThis.y, pGenes2->m_pLimbGenes[i]->m_relativeAttachmentPositionOnThis.y); if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_relativeAttachmentPositionOnThis.z, pGenes2->m_pLimbGenes[i]->m_relativeAttachmentPositionOnThis.z); // Swap entire axis for rotation to avoid illegal angles if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_relativeRotation, pGenes2->m_pLimbGenes[i]->m_relativeRotation); // Physical if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_density, pGenes2->m_pLimbGenes[i]->m_density); if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_friction, pGenes2->m_pLimbGenes[i]->m_friction); // Sensors if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_hasContactSensor, pGenes2->m_pLimbGenes[i]->m_hasContactSensor); // Neural structure if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_numHiddenLayers, pGenes2->m_pLimbGenes[i]->m_numHiddenLayers); if(Randf() > 0.5f) std::swap(pGenes1->m_pLimbGenes[i]->m_numNeuronsPerHiddenLayer, pGenes2->m_pLimbGenes[i]->m_numNeuronsPerHiddenLayer); CrossOver_VaryingSize(pGenes1->m_pLimbGenes[i]->m_mainBrainInputNeurons, pGenes2->m_pLimbGenes[i]->m_mainBrainInputNeurons); CrossOver_VaryingSize(pGenes1->m_pLimbGenes[i]->m_parentLimbInputNeurons, pGenes2->m_pLimbGenes[i]->m_parentLimbInputNeurons); CrossOver_VaryingSize(pGenes1->m_pLimbGenes[i]->m_childLimbInputNeurons, pGenes2->m_pLimbGenes[i]->m_childLimbInputNeurons); CrossOver_VaryingSize(pGenes1->m_pLimbGenes[i]->m_timerSensorData, pGenes2->m_pLimbGenes[i]->m_timerSensorData); CrossOver_VaryingSize(pGenes1->m_pLimbGenes[i]->m_neuronData, pGenes2->m_pLimbGenes[i]->m_neuronData); } // For remaining limbs, simly make sure no values are out of bounds for(unsigned int i = minNumLimbs; i < maxNumLimbs; i++) { if(static_cast<signed>(i) - (*pLargerGene)[i]->m_parentIndexOffset < 0) (*pLargerGene)[i]->m_parentIndexOffset = i; } }
void SceneObject_ParticleEmitter_Sprite::Logic() { // ----------------------- Spawning ----------------------- if(m_emit) { m_spawnTimer += GetScene()->m_frameTimer.GetTimeMultiplier(); if(m_spawnTimer > m_spawnTime) { // Spawn multiple per frame, if went over more than one multiple of the spawn time int numSpawn = static_cast<int>(m_spawnTimer / m_spawnTime); // Spawn particles for(int i = 0; i < numSpawn; i++) m_pParticles.push_back(EmitParticle()); // Reset timer, keep overflow (fmodf equivalent) m_spawnTimer -= numSpawn * m_spawnTime; // Pick new random spawn time m_spawnTime = Randf(m_minSpawnTime, m_maxSpawnTime); } } // ----------------------- Updating ----------------------- if(m_pParticles.empty()) { if(m_autoDestruct) Destroy(); } else { // Recalculate AABB while at it m_aabb.m_lowerBound = m_pParticles.front()->m_position; m_aabb.m_upperBound = m_aabb.m_lowerBound; for(std::list<Particle_Sprite*>::iterator it = m_pParticles.begin(); it != m_pParticles.end();) { Particle_Sprite* pParticle = *it; if(pParticle->Logic()) { // Destroy particle delete pParticle; it = m_pParticles.erase(it); } else { // Affect particle for(unsigned int i = 0, size = m_pAffectorFuncs.size(); i < size; i++) m_pAffectorFuncs[i](pParticle); // Grow AABB float radius = pParticle->GetRadius(); Vec3f particleLower(pParticle->m_position - Vec3f(radius, radius, radius)); Vec3f particleUpper(pParticle->m_position + Vec3f(radius, radius, radius)); if(particleLower.x < m_aabb.m_lowerBound.x) m_aabb.m_lowerBound.x = pParticle->m_position.x - pParticle->m_radius; if(particleLower.y < m_aabb.m_lowerBound.y) m_aabb.m_lowerBound.y = pParticle->m_position.y - pParticle->m_radius; if(particleLower.z < m_aabb.m_lowerBound.z) m_aabb.m_lowerBound.z = pParticle->m_position.z - pParticle->m_radius; if(particleUpper.x > m_aabb.m_upperBound.x) m_aabb.m_upperBound.x = pParticle->m_position.x + pParticle->m_radius; if(particleUpper.y > m_aabb.m_upperBound.y) m_aabb.m_upperBound.y = pParticle->m_position.y + pParticle->m_radius; if(particleUpper.z > m_aabb.m_upperBound.z) m_aabb.m_upperBound.z = pParticle->m_position.z + pParticle->m_radius; it++; } } if(IsSPTManaged()) TreeUpdate(); } }
void CreatureEvolver::Mutate(CreatureGenes* pGenes) { // Change limb count if(Randf() < m_limbCountMutationRate) { int dCount = Round_Nearest(Randf(-m_maxLimbPerturbation, m_maxLimbPerturbation)); const int newSize = pGenes->m_pLimbGenes.size() + dCount; if(newSize < m_minNumLimbs) dCount = m_minNumLimbs - pGenes->m_pLimbGenes.size(); else if(newSize > m_maxNumLimbs) dCount = m_maxNumLimbs - pGenes->m_pLimbGenes.size(); if(dCount > 0) { for(int i = 0; i < dCount; i++) { LimbGenes* pNewLimbGenes = new LimbGenes(); InitGenes(pNewLimbGenes, pGenes->m_pLimbGenes.size() + 1); pGenes->m_pLimbGenes.push_back(pNewLimbGenes); } } else if(dCount < 0) // Remove random limbs { dCount = -dCount; for(int i = 0; i < dCount && static_cast<signed>(pGenes->m_pLimbGenes.size()) > m_minNumLimbs; i++) { unsigned int index = rand() % pGenes->m_pLimbGenes.size(); delete pGenes->m_pLimbGenes[index]; pGenes->m_pLimbGenes[index] = NULL; pGenes->m_pLimbGenes.erase(pGenes->m_pLimbGenes.begin() + index); } } assert(pGenes->m_pLimbGenes.size() >= static_cast<unsigned>(m_minNumLimbs)); } for(unsigned int i = 0, size = pGenes->m_pLimbGenes.size(); i < size; i++) { LimbGenes* pLG = pGenes->m_pLimbGenes[i]; if(i != 0 && Randf() < m_limbParentMutationRate) { pLG->m_parentIndexOffset = pLG->m_parentIndexOffset + rand() % 3 - 1; if(pLG->m_parentIndexOffset < 1) pLG->m_parentIndexOffset = 1; else if(pLG->m_parentIndexOffset > static_cast<signed>(i)) pLG->m_parentIndexOffset = static_cast<signed>(i); } if(pLG->m_recursiveUnits != 0 && Randf() < m_recursiveLimbMutationRate_whenRecursive) pLG->m_recursiveUnits = 0; else if(Randf() < m_recursiveLimbMutationRate_whenNotRecursive) pLG->m_recursiveUnits = rand() % (m_maxInitRecursiveUnits - m_minInitRecursiveUnits) + m_minInitRecursiveUnits; else if(Randf() < m_recursiveLimbUnitCountChangeRate) pLG->m_recursiveUnits = Clamp(pLG->m_recursiveUnits + rand() % 3 - 1, 0, m_maxInitRecursiveUnits); if(pLG->m_symmetrical && Randf() < m_symmetricalLimbMutationRate_whenSymmetrical) pLG->m_symmetrical = false; else if(Randf() < m_symmetricalLimbMutationRate_whenNotSymmetrical) pLG->m_symmetrical = true; if(Randf() < m_numBranchesMutationRate) pLG->m_numBranches = Clamp(pLG->m_numBranches + rand() % 3 - 1, 0, m_maxNumBranches); if(Randf() < m_inheritRecursionMutationRate) pLG->m_inheritsRecursion = Randf() < m_initInheritRecursionChance; if(Randf() < m_inheritSymmetryMutationRate) pLG->m_inheritsSymmetry = Randf() < m_initInheritSymmetryChance; if(Randf() < m_dimensionalMutationRate) { pLG->m_dims.x = Clamp(pLG->m_dims.x + Randf(-m_maxLimbDimensionPerturbation, m_maxLimbDimensionPerturbation), m_minLimbDimension, m_maxLimbDimension); pLG->m_dims.y = Clamp(pLG->m_dims.y + Randf(-m_maxLimbDimensionPerturbation, m_maxLimbDimensionPerturbation), m_minLimbDimension, m_maxLimbDimension); pLG->m_dims.z = Clamp(pLG->m_dims.z + Randf(-m_maxLimbDimensionPerturbation, m_maxLimbDimensionPerturbation), m_minLimbDimension, m_maxLimbDimension); } if(Randf() < m_relativeOffsetRatioMutationRate) AttachmentPositionMutate_Parent(pLG->m_relativeAttachmentPositionOnParent); if(Randf() < m_relativeOffsetRatioMutationRate) AttachmentPositionMutate_This(pLG->m_relativeAttachmentPositionOnThis); if(Randf() < m_limbAngleMutationRate) { Quaternion newRotation(pLG->m_relativeRotation); newRotation.x += Randf(-m_maxLimbAnglePerturbation, m_maxLimbAnglePerturbation); newRotation.y += Randf(-m_maxLimbAnglePerturbation, m_maxLimbAnglePerturbation); newRotation.z += Randf(-m_maxLimbAnglePerturbation, m_maxLimbAnglePerturbation); newRotation.w += Randf(-m_maxLimbAnglePerturbation, m_maxLimbAnglePerturbation); newRotation.NormalizeThis(); Vec3f normal(NormalFromPosition(pLG->m_relativeAttachmentPositionOnParent)); // If perturbed angle is legal, set it if((newRotation * Vec3f(1.0f, 0.0f, 0.0f)).Dot(normal) > 0.0f) pLG->m_relativeRotation = newRotation; else { // Not legal, get one that is for sure float currentAngle = acosf(normal.Dot(pLG->m_relativeRotation * Vec3f(1.0f, 0.0f, 0.0f))); float maxAdditionalAngle = pLG->m_bendLimit - currentAngle; newRotation.Reset(); // Random axis Vec3f axis(Randf(-1.0f, 1.0f), Randf(-1.0f, 1.0f), Randf(-1.0f, 1.0f)); axis.NormalizeThis(); newRotation.Rotate(Randf() * maxAdditionalAngle, axis); pLG->m_relativeRotation *= newRotation; } } if(Randf() < m_limbBendAndTwistMutationRate) pLG->m_bendLimit = Clamp(pLG->m_bendLimit + Randf(-m_maxLimbBendAndTwistPerturbation, m_maxLimbBendAndTwistPerturbation), m_minLimbBend, m_maxLimbBend); if(Randf() < m_limbBendAndTwistMutationRate) pLG->m_twistLimit = Clamp(pLG->m_twistLimit + Randf(-m_maxLimbBendAndTwistPerturbation, m_maxLimbBendAndTwistPerturbation), m_minLimbTwist, m_maxLimbTwist); if(Randf() < m_limbStrengthMutationRate) pLG->m_strength = Clamp(pLG->m_strength + Randf(-m_maxLimbStrengthPerturbation, m_maxLimbStrengthPerturbation), m_minLimbStrength, m_maxLimbStrength); if(Randf() < m_densityMutationRate) pLG->m_density = Clamp(pLG->m_density + Randf(-m_maxDensityPerturbation, m_maxDensityPerturbation), m_minDensity, m_maxDensity); if(Randf() < m_frictionMutationRate) pLG->m_friction = Clamp(pLG->m_friction + Randf(-m_maxFrictionPerturbation, m_maxFrictionPerturbation), m_minFriction, m_maxFriction); if(Randf() < m_contactSensorMutationRate) pLG->m_hasContactSensor = !pLG->m_hasContactSensor; if(Randf() < m_mainBrainInputNeuronsMutationRate) { int choice = rand() % 2; if(choice == 1) pLG->m_mainBrainInputNeurons.push_back(rand() % (m_maxNumMainBrainInputNeurons + 1)); else if(!pLG->m_mainBrainInputNeurons.empty()) pLG->m_mainBrainInputNeurons.erase(pLG->m_mainBrainInputNeurons.begin() + rand() % pLG->m_mainBrainInputNeurons.size()); } if(Randf() < m_parentLimbInputNeuronsMutationRate) { int choice = rand() % 2; if(choice == 1) pLG->m_parentLimbInputNeurons.push_back(rand() % (m_maxNumParentLimbInputNeurons + 1)); else if(!pLG->m_parentLimbInputNeurons.empty()) pLG->m_parentLimbInputNeurons.erase(pLG->m_parentLimbInputNeurons.begin() + rand() % pLG->m_parentLimbInputNeurons.size()); } if(Randf() < m_childLimbInputNeuronsMutationRate) { int choice = rand() % 2; if(choice == 1) { LimbGenes::ChildAndOutputIndex coai; coai.m_childIndex = rand() % m_maxNumBranches; coai.m_outputIndex = rand() % m_maxNumChildLimbInputNeurons; pLG->m_childLimbInputNeurons.push_back(coai); } else if(!pLG->m_childLimbInputNeurons.empty()) pLG->m_childLimbInputNeurons.erase(pLG->m_childLimbInputNeurons.begin() + rand() % pLG->m_childLimbInputNeurons.size()); } // Mutate weights before changing structure randomly for(unsigned int j = 0, numNeurons = pLG->m_neuronData.size(); j < numNeurons; j++) { //if(Randf() < m_neuralWeightMutationRate) // pLG->m_neuronData[j].m_threshold = Clamp(pLG->m_neuronData[j].m_threshold + Randf(-m_neuralWeightPerturbation, m_neuralWeightPerturbation), -1.0f, 1.0f); for(unsigned int k = 0, numWeights = pLG->m_neuronData[j].m_weights.size(); k < numWeights; k++) if(Randf() < m_neuralWeightMutationRate) pLG->m_neuronData[j].m_weights[k] = Clamp(pLG->m_neuronData[j].m_weights[k] + Randf(-m_neuralWeightPerturbation, m_neuralWeightPerturbation), m_minPossibleNeuronWeight, m_maxPossibleNeuronWeight); } // Mutate timers before changing structure randomly for(unsigned int j = 0, numTimers = pLG->m_timerSensorData.size(); j < numTimers; j++) { if(Randf() < m_timerRateMutationRate) pLG->m_timerSensorData[j].m_rate = Clamp(pLG->m_timerSensorData[j].m_rate + Randf(-m_maxTimerRatePerturbation, m_maxTimerRatePerturbation), m_minTimerRate, m_maxTimerRate); if(Randf() < m_timerTimeMutationRate) pLG->m_timerSensorData[j].m_initTime = Clamp(pLG->m_timerSensorData[j].m_initTime + Randf(-m_maxTimerTimePerturbation, m_maxTimerTimePerturbation), 0.0f, 1.0f); } // Mutate neuron structure if(Randf() < m_neuralStructureMutationRate_numLayers) pLG->m_numHiddenLayers = Clamp(pLG->m_numHiddenLayers + rand() % 3 - 1, m_minHiddenLayers, m_maxHiddenLayers); if(Randf() < m_neuralStructureMutationRate_numNeuronsPerHiddenLayer) { int pert = static_cast<int>(Randf(-m_maxNeuronsPerHiddenLayerPerturbation, m_maxNeuronsPerHiddenLayerPerturbation)); int nphl = Clamp(static_cast<signed>(pLG->m_numNeuronsPerHiddenLayer) + pert, static_cast<signed>(m_minNeuronsPerHiddenLayer), static_cast<signed>(m_maxNeuronsPerHiddenLayer)); pLG->m_numNeuronsPerHiddenLayer = static_cast<unsigned>(nphl); } // Mutate number of timers if(Randf() < m_timerCountMutationRate) pLG->m_numTimerSensors = Clamp(pLG->m_numTimerSensors + rand() % 3 - 1, m_minTimerCount, m_maxTimerCount); } }
bool BgEffectTile::ShouldBranch() const { return Randf(0, 1) < m_BranchChance; }
float Randf(float min, float max) { return min + Randf() * (max - min); }