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);
	}
}
예제 #4
0
파일: Random.cpp 프로젝트: erenik/engine
/// 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;
}
예제 #9
0
파일: GA.cpp 프로젝트: cuihao0532/GA_UI
// 变异
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);
}
예제 #12
0
bool BgEffectTile::ShouldChangeDir() const
{
	return Randf(0, 1) < ConfigManager::GetFloat("[Bg Effect]fChangeDirChance");
}
예제 #13
0
파일: GA.cpp 프로젝트: cuihao0532/GA_UI
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 
    
}
예제 #14
0
파일: Rand.cpp 프로젝트: boskee/lamos
float Randf(float pl_min,float pl_max) {
	float dif = pl_max - pl_min;
	return Randf() * dif + pl_min;
}
예제 #15
0
파일: Random.cpp 프로젝트: erenik/engine
/// 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);
	}
}
예제 #20
0
bool BgEffectTile::ShouldBranch() const
{
	return Randf(0, 1) < m_BranchChance;
}
float Randf(float min, float max)
{
	return min + Randf() * (max - min);
}