// Author : Chris Tolley
// Date   : 7/28/2004
// Gene.h contains the class declaration for a gene class that generates
// a string of bytes to use in a GA

#include <vector>
//#include <iostream>

using namespace std;

#include "Gene.h"
#include "logger.h"
#include "Bug.h"

// Some constants to help us out
const int MUTATION_RATE = 50;

// Constructor
Gene::Gene( const int length )
{
	// Generate length number of bytes
	for( int n = 0; n < length; ++n )
	{
		m_ucGenotype.push_back( rand() % 256 );
	}// End for n
}// End Gene::Constructor


// Copy Constructor
Gene::Gene( const Gene& rhs )
{
	m_ucGenotype = rhs.m_ucGenotype;
}// End for Gene


// Creates a gene from a group of threshold values and a patrol path
Gene::Gene( const ThresholdValues& thresholds, const PatrolPath& path )
{
	// Resize the vector to hold all the data
	m_ucGenotype.resize( sizeof( ThresholdValues ) +
						 sizeof( PatrolPath ) );

	// Copy the bytes from thresholds and patrol path
	memcpy( &m_ucGenotype[0], &path, sizeof( PatrolPath ) );

	memcpy( &m_ucGenotype[ sizeof( PatrolPath ) ],
			&thresholds, sizeof( ThresholdValues ) );
}// End Gene::Constructor


// Copies this gene into a new gene and returns it.  Includes mutation
Gene Gene::Polymerize() const
{
	// Create a new gene to store the results in
	Gene gene;

	// Copy the bits in this gene into the new gene
	int size = m_ucGenotype.size();
	for( int n = 0; n < size; ++n )
	{
		// Add the n'th byte to the new gene
		gene.m_ucGenotype.push_back( m_ucGenotype[n] );

		// Check and see if mutation should occur now
		if( ( rand() % MUTATION_RATE ) == 0 )
		{
			// Choose the bit to flip
			int index = rand() % 8;

			// Make a copy of the n'th byte
			unsigned char copy = gene.m_ucGenotype[n];

			// Shift the byte to the left and then to the right to zero out
			// each bit except the one indicated by index
			copy = copy << ( 7 - index );
			copy = copy >> 7;
			if( copy == 0 )
				copy = 0x01;
			copy = copy << index;

			// Preform an xor between copy and the n'th byte in the new gene's
			// genotype which will flip the correct bit
			gene.m_ucGenotype[n] ^= copy;
		}// End if

	}// End for n

	// Return the new gene
	return gene;
}// End Gene::Polymerize


// Destructor
Gene::~Gene()
{
}// End Gene::Destructor


/*
// Prints the gene to the screen
void Gene::Print()
{
	// Print each char to the screen
	for( int n = 0; n < m_ucGenotype.size(); ++n )
	{
		cout << m_ucGenotype[n] << " ";
	}// End for n
}// End Gene::Print
*/