Newer
Older
ecologia / src / model / Genome.java
package model;

import java.util.HashMap;
import java.util.Random;

import main.EcologiaIO;
import controller.OccupantType;

/**
 * A genome holds a number of variables ("genes") that determine an animals characteristics.
 * Note: this class has three constructors!
 * 
 * @author Daniel Vedder
 * @version 30.8.2014
 */
public class Genome 
{
	private int mutationRate; //The probability of a mutation occurring in percent.
	private int speed; //How fast is the animal (fields/update)?
	//XXX Remove stamina again?
	private int stamina; //For how long can this animal keep moving before it needs a rest?
	private int sight; //How far can the animal see (fields distant)?
	private int metabolism; //How efficient is it's metabolism?
	private int ageLimit; //The age at which it will die of old age
	private int strength; //How strong is it in a fight
	private int reproductiveEnergy; //How much energy it needs before it will reproduce - 50% will be transferred to the child
	private int maturityAge; //The age at which it reaches sexual maturity
	private int gestation; //The minimum time needed for the reproductive cycle
	private int reproductionRate; //How many offspring are produced at once?
	
	private final int DEFAULT_MUTATION_RATE = 0; //Suggested default: 0
	
	private static Genome herbivoreGenome, carnivoreGenome;
	
	private Random random;
	
	/**
	 * The default constructor provides a standard genome.
	 */
	public Genome()
	{
		mutationRate = 5;
		speed = 1;
		stamina = 10;
		sight = 3;
		metabolism = 10;
		ageLimit = 180;
		strength = 10;
		reproductiveEnergy = 140;
		maturityAge = 20;
		gestation = 10;
		reproductionRate = 1;
	}
	
	/**
	 * This constructor creates a new genome based on the parent genome passed 
	 * to it, mutating it at random.
	 */
	public Genome(Genome parentGenome)
	{
		random = new Random();
		/* Before we can mutate the mutation rate, we need to know a 
		 * preliminary mutation rate or we get a NullPointerException
		 */
		mutationRate = DEFAULT_MUTATION_RATE;
		// Mutate the parent's genes to get this genome
		// XXX Warning: magic numbers!
		mutationRate = parentGenome.getMutationRate()+mutation(1);
		speed = parentGenome.getSpeed()+mutation(1);
		stamina = parentGenome.getStamina()+mutation(1);
		sight = parentGenome.getSight()+mutation(1);
		metabolism = parentGenome.getMetabolism()+mutation(1);
		ageLimit = parentGenome.getAgeLimit()+mutation(10);
		strength = parentGenome.getStrength()+mutation(1);
		reproductiveEnergy = parentGenome.getReproductiveEnergy()+mutation(10);
		maturityAge = parentGenome.getMaturityAge()+mutation(1);
		gestation = parentGenome.getGestation()+mutation(1);
		reproductionRate = parentGenome.getReproductionRate()+mutation(1);
		checkGenome();
	}
	
	/**
	 * This constructor creates a genome from the values passed to it.
	 */
	public Genome(int mutationRate, int speed, int stamina, int sight, int metabolism,
				  int ageLimit, int strength, int reproductiveEnergy, int maturityAge,
				  int gestation, int reproductionRate)
	{
		this.mutationRate = mutationRate;
		this.speed = speed;
		this.stamina = stamina;
		this.sight = sight;
		this.metabolism = metabolism;
		this.ageLimit = ageLimit;
		this.strength = strength;
		this.reproductiveEnergy = reproductiveEnergy;
		this.maturityAge = maturityAge;
		this.gestation = gestation;
		this.reproductionRate = reproductionRate;
		checkGenome();
	}
	
	/**
	 * This constructor creates a genome from a HashMap.
	 */
	public Genome(HashMap<String, Integer> genVars)
	{
		this.mutationRate = genVars.get("mutationRate");
		this.speed = genVars.get("speed");
		this.stamina = genVars.get("stamina");
		this.sight = genVars.get("sight");
		this.metabolism = genVars.get("metabolism");
		this.ageLimit = genVars.get("ageLimit");
		this.strength = genVars.get("strength");
		this.reproductiveEnergy = genVars.get("reproductiveEnergy");
		this.maturityAge = genVars.get("maturityAge");
		this.gestation = genVars.get("gestation");
		this.reproductionRate = genVars.get("reproductionRate");
		checkGenome();
	}
	
	/**
	 * Returns a mutation factor depending on the specified mutation rate.
	 * @param coefficient Influences the size of the returned factor.
	 * @return factor The wanted mutation factor.
	 */
	private int mutation(int coefficient)
	{
		int factor = 0;
		if (random.nextInt(100) < mutationRate) { //Does a mutation take place?
			if (random.nextInt(2) == 0) { //If yes there is a 50% chance of...
				factor = factor+coefficient;  //...adding the coefficient to the factor
			}
			else {
				factor = factor-coefficient; //...subtracting the coefficient from the factor
			}
		}
		return factor; //return the (perhaps) mutated factor
	}
	
	/**
	 * Check to make sure that no "gene" has a value below zero
	 */
	private void checkGenome()
	{
		if (mutationRate < 0) mutationRate = 0;
		if (speed < 0) speed = 0;
		if (sight < 0) sight = 0;
		if (metabolism < 0) metabolism = 0;
		if (ageLimit < 0) ageLimit = 0;
		if (strength < 0) strength = 0;
		if (reproductiveEnergy < 0) reproductiveEnergy = 0;
		if (maturityAge < 0) maturityAge = 0;
		if (gestation < 0) gestation = 0;
		if (reproductionRate < 0) reproductionRate = 0;
	}
	
	/**
	 * Return all the "genes" of this genome in a single HashMap.
	 * @return genomeInfo
	 */
	public HashMap<String, Integer> asHashMap()
	{
		HashMap<String, Integer> genomeInfo = new HashMap<String, Integer>();
		genomeInfo.put("mutationRate", mutationRate);
		genomeInfo.put("speed", speed);
		genomeInfo.put("stamina", stamina);
		genomeInfo.put("sight", sight);
		genomeInfo.put("metabolism", metabolism);
		genomeInfo.put("ageLimit", ageLimit);
		genomeInfo.put("strength", strength);
		genomeInfo.put("reproductiveEnergy", reproductiveEnergy);
		genomeInfo.put("maturityAge", maturityAge);
		genomeInfo.put("gestation", gestation);
		genomeInfo.put("reproductionRate", reproductionRate);
		return genomeInfo;
	}
	
	/*
	 * The Getters for each "gene"
	 * XXX Are these invalidated with asHashMap()?
	 */
	
	public int getMutationRate() 
	{
		return mutationRate;
	}

	public int getSpeed() 
	{
		return speed;
	}
	
	public int getStamina()
	{
		return stamina;
	}

	public int getSight() 
	{
		return sight;
	}

	public int getMetabolism() 
	{
		return metabolism;
	}

	public int getAgeLimit() 
	{
		return ageLimit;
	}

	public int getStrength() 
	{
		return strength;
	}

	public int getReproductiveEnergy() 
	{
		return reproductiveEnergy;
	}

	public int getMaturityAge() 
	{
		return maturityAge;
	}

	public int getGestation() 
	{
		return gestation;
	}

	public int getReproductionRate()
	{
		return reproductionRate;
	}
	
}