void MedeaSpAgentObserver::checkGenomeList()
{


	if (_wm->_agentId == gAgentIndexFocus && gVerbose) // debug
	{
		std::cout << "agent #" << gAgentIndexFocus << " is renewed" << std::endl;
		std::cout << "agent #" << gAgentIndexFocus << " imported " << _wm->_genomesList.size() << " genomes. Energy is " << _wm->getEnergyLevel() << ". Status is "  << _wm->getActiveStatus() << "." <<std::endl;
	}


	// note: at this point, agent got energy, wether because it was revived or because of remaining energy.
	if (_wm->_genomesList.size() > 0) 
	{
		// case: 1+ genome(s) imported, random pick.

		_wm->setDateOfBirth(gWorld->getIterations());
		//
	//	if((int)MedeaSpSharedData::gTournamentSize < 0) selectFitnessProp();
	//	else elitSelection();
		// 		_wm->setRobotLED_status(true);
		//Print the new genome on the logFile
		//gLogFile << gWorld->getIterations() <<" : "<< _wm->_agentId << " use "<<_wm->getAbilityToForage();

		//gLogFile << " at "<<_wm->getXReal()<< std::endl;
			switch ( MedeaSpSharedData::gSelectionMethod )
			{
				case 0:
					pickRandomGenome();
					break;
				case 1:
					elitSelection(); //elite
					break;
				case 2:
					selectFitnessProp();
					break;
				case 3:
					selectRankProp();
					break;
				default:
					std::cerr << "[ERROR] unknown selection method (gSelectionMethod = " << MedeaSpSharedData::gSelectionMethod << ")\n";
					exit(-1);
			}
		_wm->setWaitForGenome(false); // !N.20100407 : revive takes imported genome if any
		_wm->setActiveStatus(true);
	}
	else
	{

		// case: no imported genome - wait for new genome.

		_wm->resetActiveGenome(); // optional -- could be set to zeroes.
		_wm->setWaitForGenome(true); // inactive robot *must* import a genome from others (ie. no restart).

		_wm->setActiveStatus(false);//The robot is waiting for genome but not active yet
	}

}
void BasicProjectMedeaAgentObserver::step()
{
	// debug verbose
	if ( gVerbose && gInspectAgent && gAgentIndexFocus == _wm->_agentId )
	{
		std::cout << "target: " << _wm->getEnergyPointDirectionAngleValue() << std::endl;
	}

	// * genome spreading (current agent broadcasts its genome to all neighbors - ie. write its own genome in genomeList on neighboring agents)
	// note: could be move in WorldObserver to go from N^2 to Summation(N) complexity

	if ( _wm->getActiveStatus() == true )  	// broadcast only if agent is active (ie. not just revived) and deltaE>0.
	{
		for (int i = 0 ; i < gAgentCounter ; i++)
		{
			if ( ( i != _wm->_agentId ) && ( gRadioNetworkArray[_wm->_agentId][i] ) ) //&& (_wm->getEnergyLevel() > 0.0) ) --> always true as status is active
			{
				BasicProjectMedeaAgentObserver* targetAgentObserver = dynamic_cast<BasicProjectMedeaAgentObserver*>(gWorld->getAgent(i)->getObserver());
				if ( ! targetAgentObserver )
				{
					std::cerr << "Error from robot " << _wm->_agentId << " : the observer of robot " << i << " isn't a SwarmOnlineObserver" << std::endl;
					exit(1);
				}
				if ( BasicProjectMedeaSharedData::gDynamicSigma == true )
				{
					float dice = float(rand() %100) / 100.0;
					float sigmaSendValue = 0.0;
					if ( ( dice >= 0.0 ) && ( dice < BasicProjectMedeaSharedData::gProbAdd) )
					{
						sigmaSendValue = _wm->_currentSigma * ( 1 + BasicProjectMedeaSharedData::gDynaStep );
						if (sigmaSendValue > BasicProjectMedeaSharedData::gSigmaMax)
						{
							sigmaSendValue = BasicProjectMedeaSharedData::gSigmaMax;
						}
					}
					else if ( ( dice >= BasicProjectMedeaSharedData::gProbAdd ) && ( dice < BasicProjectMedeaSharedData::gProbAdd+BasicProjectMedeaSharedData::gProbSub) )
					{
						sigmaSendValue = _wm->_currentSigma * ( 1 - BasicProjectMedeaSharedData::gDynaStep );
						if (sigmaSendValue < BasicProjectMedeaSharedData::gSigmaMin)
						{
							sigmaSendValue = BasicProjectMedeaSharedData::gSigmaMin;
						}
					}
					else
					{
						std::cerr << "Error : In SwarmOnlineObserver, the rand value is out of bound. The sum of BasicProjectMedeaSharedData::gProbRef and BasicProjectMedeaSharedData::gProbMax is probably not equal to one" << std::endl;
						exit(1);
					}
					targetAgentObserver->writeGenome(_wm->_currentGenome, _wm->_agentId, sigmaSendValue);
				}
				else
				{
					targetAgentObserver->writeGenome(_wm->_currentGenome, _wm->_agentId, _wm->_currentSigma);
				}
			}
		}
	}

	// * Genome selection/replacement

	if( dynamic_cast<BasicProjectMedeaWorldObserver*>(gWorld->getWorldObserver())->getLifeIterationCount() >= BasicProjectMedeaSharedData::gEvaluationTime-1 ) // at the end of a generation
	{
		if (_wm->_agentId == gAgentIndexFocus && gVerbose) // debug
		{
			std::cout << "agent #" << gAgentIndexFocus << " is renewed" << std::endl;
			std::cout << "agent #" << gAgentIndexFocus << " imported " << _wm->_genomesList.size() << " genomes. Energy is " << _wm->getEnergyLevel() << ". Status is "  << _wm->getActiveStatus() << "." <<std::endl;
		}

		// Display the current state of the controller
		gLogFile << "#GIteration: " << gWorld->getIterations() << " #Robot: " << _wm->_agentId
				 << " #Energy: " <<  _wm->getEnergyLevel()
				 << " #DeltaEnergy: " << _wm->getDeltaEnergy()
				 << " #GenomeListSize: " << _wm->_genomesList.size() <<std::endl;

		// note: at this point, agent got energy, whether because it was revived or because of remaining energy.
		if (_wm->_genomesList.size() > 0)
		{
			// case: 1+ genome(s) imported, random pick.

			pickRandomGenome();
			_wm->setActiveStatus(true); // !N.20100407 : revive takes imported genome if any
		}
		else
		{
			// case: no imported genome - wait for new genome.

			gLogFile << "Info(" << gWorld->getIterations() << ") : robot nb." << _wm->_agentId
			//					<< " is trying a whole new genome" << std::endl;
								<< " is waiting for a new genome" << std::endl;

			_wm->resetActiveGenome(); // optional -- could be set to zeroes.
			_wm->setActiveStatus(false); // inactive robot *must* import a genome from others (ie. no restart).
		}

		//log the genome

		if ( _wm->getActiveStatus() == true )
		{
			gLogFile << "Info("<< gWorld->getIterations() <<") : robot nb."<< _wm->_agentId << " use genome :";
			for(unsigned int i=0; i<_wm->_genome.size(); i++)
			{
				gLogFile << std::fixed << std::showpoint << _wm->_genome[i] << " ";
			}
			gLogFile << std::endl;
		}

		//Re-initialize the main parameters

		if ( BasicProjectMedeaSharedData::gExperimentNumber == 1 || BasicProjectMedeaSharedData::gExperimentNumber == 2 )
		{
			_wm->setDeltaEnergy(0.0); // !n : used to be 10.0
		}
	}
}
void MedeaAltUtilityBattleAgentObserver::step()
{
	_iterationCount++;
	if ( _wm->_agentId == 0 )
	{
			if ( MedeaAltUtilitySharedData::gExperimentNumber == 2 )
			{
					if (_wm->_agentId ==  gAgentIndexFocus ) // && gVerbose ) // debug
					{
						std::cout << std::endl << "#### Experiment no.2 starts now. ####" << std::endl;
					}
				
					// * remove energy points.
				
					for(std::vector<EnergyPoint>::iterator it = gEnergyPoints.begin(); it != gEnergyPoints.end(); it++)
					{
						it->hide();
					}
					gEnergyPoints.clear();
				
					// * setup new energy zone
				
					Uint32 colorShown = 0xeab71fff;
					Uint32 colorZone  = 0xAAAAAAFF; // for floor sensor.
				
					for (Sint16 xColor = MedeaAltUtilitySharedData::g_xStart_EnergyZone ; xColor < MedeaAltUtilitySharedData::g_xEnd_EnergyZone ; xColor++)
					{
						for (Sint16 yColor = Sint16 (MedeaAltUtilitySharedData::g_yStart_EnergyZone) ; yColor < Sint16 (MedeaAltUtilitySharedData::g_yEnd_EnergyZone) ; yColor ++)
						{
								pixelColor(gBackgroundImage, xColor, yColor, colorShown);
								pixelColor(gZoneImage, xColor, yColor, colorZone);
						}
					}
			
			}
	}
					
//	std::cout << "robot #" << _wm->_agentId << "\n" ;

	MedeaAltUtilityPerceptronControlArchitecture* currentBehavior = dynamic_cast<MedeaAltUtilityPerceptronControlArchitecture*>(gWorld->getAgent(_wm->_agentId)->getBehavior());

	if ( ! currentBehavior )
	{
		std::cerr << "Error from robot " << _wm->_agentId << " : the behavior architecture of this robot  isn't a MedeaAltUtilityPerceptronControlArchitecture" << std::endl;
		exit(1);
	}

	/*if (_wm->_agentId == 1)
	{
		std::cout << _key <<std::endl;
	}*/
	if ( gVerbose && gInspectAgent && gAgentIndexFocus == _wm->_agentId )
	{
		//std::cout << "target: " << _wm->getEnergyPointDirectionAngleValue() << std::endl;// " (" << _wm->_agentAbsoluteOrientation << "," << angleToClosestEnergyPoint << ")" << std::endl;
	}

	if ( MedeaAltUtilitySharedData::gExperimentNumber == 1 )
	{
		// * update the energy of the robot (if needed)
	
		Point2d posRobot(_wm->_xReal,_wm->_yReal);
		if ( gEnergyMode )
		{
			for(std::vector<EnergyPoint>::iterator it = gEnergyPoints.begin(); it != gEnergyPoints.end(); it++)
			{

				if( (getEuclidianDistance (posRobot,it->getPosition()) < gEnergyPointRadius) && (it->getActiveStatus()))
				{
					float loadingEnergy = gEnergyPointValue; // test?
					//float loadingEnergy = 5*(1.0/(2.0*sqrt(2.0*M_PI)))*gEnergyPointValue; // test?
					//float loadingEnergy = 5*(1.0/(2.0*sqrt(2.0*M_PI)))*exp(-(pow((_key - it->getKey()),2.0)/(pow(2.0,2.0))))*gEnergyPointValue;

					// update energy level
					_wm->setEnergyLevel(_wm->getEnergyLevel() + loadingEnergy);
					_wm->setDeltaEnergy(_wm->getDeltaEnergy() + loadingEnergy);

					//saturate
					if ( _wm->getEnergyLevel() > MedeaAltUtilitySharedData::gEnergyMax ) // should be at least one lifetime
						_wm->setEnergyLevel(MedeaAltUtilitySharedData::gEnergyMax);
					if ( _wm->getDeltaEnergy() > MedeaAltUtilitySharedData::gEnergyMax )
						_wm->setDeltaEnergy(MedeaAltUtilitySharedData::gEnergyMax);

					gLogFile << "Info(" << gWorld->getIterations() << ") : " << _wm->_agentId
						<< "(" << posRobot.x << "," << posRobot.y << ")" 
						<< " get an energy point at " << it->getPosition().x << "," << it->getPosition().y << " :: Value : " << loadingEnergy  << std::endl;

					it->setActiveStatus(false);
				}
			}
		}
	}
	else 
	{
		if ( MedeaAltUtilitySharedData::gExperimentNumber == 2 )
		{
			// * once per world update (TODO: move to worldobserver)
			
			if (_wm->_agentId ==  0 ) // debug
			{
				int agentsOnZone = 0;
				for ( int i = 0 ; i != gAgentCounter ; i++ )
				{
					int x = (int)(gWorld->getAgent(i)->getWorldModel()->getXReal());
					int y = (int)(gWorld->getAgent(i)->getWorldModel()->getYReal());
					// std::cout << "x =" << x << " , y = " << y << std::endl;

					if ( x >= MedeaAltUtilitySharedData::g_xStart_EnergyZone && y >= MedeaAltUtilitySharedData::g_yStart_EnergyZone && x <= MedeaAltUtilitySharedData::g_xEnd_EnergyZone && y <= MedeaAltUtilitySharedData::g_yEnd_EnergyZone )
						agentsOnZone++;
				}
				// update MedeaAltUtilitySharedData::gZoneEnergy_harvestValue
				//MedeaAltUtilitySharedData::gZoneEnergy_harvestValue = 10; // TODO :: TEMPORARY !!!!!!!!!!TEMPORARY !!!!!!!!!!TEMPORARY !!!!!!!!!!TEMPORARY !!!!!!!!!!TEMPORARY !!!!!!!!!!
			
				if ( gVerbose )
					std::cout << "There are " << agentsOnZone << " agents on the energy zone" <<  std::endl;
			
				/**/
				if ( agentsOnZone <= MedeaAltUtilitySharedData::gZoneEnergy_maxFullCapacity )
				{
					// best case
					MedeaAltUtilitySharedData::gZoneEnergy_harvestValue = MedeaAltUtilitySharedData::gZoneEnergy_maxHarvestValue;
				}
				else
				{
					if ( agentsOnZone <= MedeaAltUtilitySharedData::gZoneEnergy_saturateCapacityLevel )
					{
						double energyValueSpan = MedeaAltUtilitySharedData::gZoneEnergy_maxHarvestValue - MedeaAltUtilitySharedData::gZoneEnergy_minHarvestValue;
						int agentsOverheadCount = MedeaAltUtilitySharedData::gZoneEnergy_saturateCapacityLevel - MedeaAltUtilitySharedData::gZoneEnergy_maxFullCapacity;
						double costPerAgents = energyValueSpan / (double)agentsOverheadCount;
						MedeaAltUtilitySharedData::gZoneEnergy_harvestValue = MedeaAltUtilitySharedData::gZoneEnergy_maxHarvestValue - costPerAgents * ( agentsOnZone- MedeaAltUtilitySharedData::gZoneEnergy_maxFullCapacity ) ;
					}
					else 
					{
						// worst case
						MedeaAltUtilitySharedData::gZoneEnergy_harvestValue = MedeaAltUtilitySharedData::gZoneEnergy_minHarvestValue;
					}
				}
				/**/
				
				// debug : MedeaAltUtilitySharedData::gZoneEnergy_harvestValue = MedeaAltUtilitySharedData::gZoneEnergy_maxHarvestValue;
			
			}

		
			// * for each agent -- TODO: could be optimized by merging with previous block in the worldobserve

			if ( _wm->_xReal >= MedeaAltUtilitySharedData::g_xStart_EnergyZone && _wm->_xReal <= MedeaAltUtilitySharedData::g_xEnd_EnergyZone && _wm->_yReal >= MedeaAltUtilitySharedData::g_yStart_EnergyZone && _wm->_yReal <= MedeaAltUtilitySharedData::g_yEnd_EnergyZone )
			{
				float loadingEnergy = MedeaAltUtilitySharedData::gZoneEnergy_harvestValue;
				
				// update energy level
				_wm->setEnergyLevel(_wm->getEnergyLevel() + loadingEnergy);
				_wm->setDeltaEnergy(_wm->getDeltaEnergy() + loadingEnergy);

				// saturate
				if ( _wm->getEnergyLevel() > MedeaAltUtilitySharedData::gEnergyMax ) // assume: need MedeaAltUtilitySharedData::gEvaluationTime to live full life
					_wm->setEnergyLevel(MedeaAltUtilitySharedData::gEnergyMax);
				if ( _wm->getDeltaEnergy() > MedeaAltUtilitySharedData::gEnergyMax ) // assume: need MedeaAltUtilitySharedData::gEvaluationTime to live full life 
					_wm->setDeltaEnergy(MedeaAltUtilitySharedData::gEnergyMax);

				Point2d posRobot(_wm->_xReal,_wm->_yReal);				
				gLogFile << "Info(" << gWorld->getIterations() << ") : " << _wm->_agentId
						<< "(" << posRobot.x << "," << posRobot.y << ")" 
						<< " get an energy point at 0,0 :: Value : " << loadingEnergy  << std::endl; // hack to comply with python log analyser
			}
		}
	}

	// * check energy level

	if ( MedeaAltUtilitySharedData::gExperimentNumber == 1 || MedeaAltUtilitySharedData::gExperimentNumber == 2 )
	{
		if ( _wm->getEnergyLevel() <= 0 )
		{
			_wm->setDeltaEnergy(0); // must be set to zero to avoid broadcasting.
			_wm->setActiveStatus(false);
		}
	}

	// * broadcast the genome (current agent writes its genome to all neighbors
		
	// broadcast only if agent is active (ie. not just revived) and deltaE>0.
	if ( 
			/*( _wm->getDeltaEnergy()>0.0 && _wm->getActiveStatus() == true )
			||
			( MedeaAltUtilitySharedData::gExperimentNumber == 0 && _wm->getActiveStatus() == true )*/
			_wm->getActiveStatus() == true
		)  
	{
		for (int i = 0 ; i < gAgentCounter ; i++)
		{
			if ( ( i != _wm->_agentId ) && ( gRadioNetworkArray[_wm->_agentId][i] ) ) //&& (_wm->getEnergyLevel() > 0.0) ) --> always true as status is active
			{
				MedeaAltUtilityBattleAgentObserver* agentObserver = dynamic_cast<MedeaAltUtilityBattleAgentObserver*>(gWorld->getAgent(i)->getObserver());
				if ( ! agentObserver )
				{
					std::cerr << "Error from robot " << _wm->_agentId << " : the observer of robot " << i << " isn't a MedeaAltUtilityBattleAgentObserver" << std::endl;
					exit(1);
				}
				agentObserver->writeGenome(_currentGenome, _wm->_agentId);
			}
		}
	}

	// * handle genome renewal

	//"restart" the robot in case it runs out of energy -- case: no synchronisation
	/*
	if ( ( _wm->getEnergyLevel()  <= 0.0 ) &&  ( MedeaAltUtilitySharedData::gSynchronization == false ) ){
		logStatus();
		//resetActiveGenome();
		_wm->setEnergyLevel( currentBehavior->getInitialEnergy());
		_wm->setDeltaEnergy(0.0);

		gLogFile << "Info(" << gWorld->getIterations() << ") : Human intervention on robot " << _wm->_agentId << " (Energy)" << std::endl;
		_iterationCount = 0;
		_wm->setActiveStatus(false); // !N.20100407 : inactive robot should get a new genome and move until it imports one from neighbors.
	}
	*/
	
	// case: default for Medea, synchronised
	if( _iterationCount >= MedeaAltUtilitySharedData::gEvaluationTime )
	{
		/**/
		if (_wm->_agentId ==  gAgentIndexFocus && gVerbose) // debug
		{
			std::cout << "agent #" << gAgentIndexFocus << " is renewed" << std::endl;
			std::cout << "agent #" << gAgentIndexFocus << " imported " << _genomesList.size() << " genomes. Energy is " << _wm->getEnergyLevel() << ". Status is "  << _wm->getActiveStatus() << "." <<std::endl;
		}
		/**/

	
		logStatus();
		
		//"revive" the robot in case it runs out of energy
		if ( MedeaAltUtilitySharedData::gExperimentNumber == 1 || MedeaAltUtilitySharedData::gExperimentNumber == 2 )
		{
			if  ( _wm->getEnergyLevel()  <= 0.0 )
			{
				gLogFile << "Info(" << gWorld->getIterations() << ") : Human intervention on robot " << _wm->_agentId << " (Energy)" << std::endl;
				// reformulate (check python script compatibility before): gLogFile << "Info(" << gWorld->getIterations() << ") : robot " << _wm->_agentId << " was revived (human intervention)" << std::endl;

				if (_wm->_agentId == gAgentIndexFocus && gVerbose) // debug
				{
					std::cout << "agent #" << gAgentIndexFocus << " is revived (energy was 0)." << std::endl;
				}

				logStatus();
				//resetActiveGenome();
			
				_wm->setEnergyLevel(MedeaAltUtilitySharedData::gEnergyRevive); // !n : too few?

				_wm->setActiveStatus(false); // true: restart, false: no-restart
			
				_genomesList.empty();
			}
		}
		
		//else // uncomment if restart
		// note: at this point, agent got energy, wether because it was revived or because of remaining energy.
		// case: genome(s) imported, random pick.
		if (_genomesList.size() > 0)
		{
			pickRandomGenome();
			_wm->setActiveStatus(true); // !N.20100407 : revive takes imported genome if any
		}
		// case: no imported genome - wait for new genome.
		else
		{
			gLogFile << "Info(" << gWorld->getIterations() << ") : robot nb." << _wm->_agentId
			//					<< " is trying a whole new genome" << std::endl;
								<< " is waiting for a new genome" << std::endl;

			//resetActiveGenome(); // optional -- could be set to zeroes.
			_wm->setActiveStatus(false); // !N.20100407 : inactive robot must import a genome from others.
		}
		
		//log the genome
		gLogFile << "get active status" << std::endl ;
		if ( _wm->getActiveStatus() == true )
		{
			gLogFile << "Info("<< gWorld->getIterations() <<") : robot nb."<< _wm->_agentId << " use genome :";
			for(unsigned int i=0; i<_wm->_genome.size(); i++)
			{
				gLogFile << std::fixed << std::showpoint<< _wm->_genome[i] << " ";
			}
			gLogFile << std::endl;
		}

		//Re-initialize the main parameters

		if ( MedeaAltUtilitySharedData::gExperimentNumber == 1 || MedeaAltUtilitySharedData::gExperimentNumber == 2 )
		{
			_wm->setDeltaEnergy(0.0); // !n : avant: 10.0
		}
		
		_iterationCount = 0;
		_generationCount ++;
		
		
		if ( _wm->_agentId == 0 )
		{
			if ( !gVerbose )
			{
				//std::cout << ".";
				int activeCount = 0;
				for ( int i = 0 ; i != gAgentCounter ; i++ )
				{
					if ( _wm->getActiveStatus() == true )  
						activeCount++;
				}
				std::cout << "[" << activeCount << "]";
			}
				
			
		}
	}


	
}