/*******************************************************************************
* Copyright (c) 2016 Alex Shapiro - github.com/shpralex
* This program and the accompanying materials
* are made available under the terms of the The MIT License (MIT)
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*******************************************************************************/
package com.sproutlife.model.step;
import java.awt.Point;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
import com.sproutlife.Settings;
import com.sproutlife.model.GameModel;
import com.sproutlife.model.echosystem.Cell;
import com.sproutlife.model.echosystem.Genome;
import com.sproutlife.model.echosystem.Mutation;
import com.sproutlife.model.echosystem.Organism;
public class MutationStep extends Step {
GameModel gameModel;
Random random;
public MutationStep(GameModel gameModel) {
super(gameModel);
random = new Random();
}
public void perform() {
doExistingMutations();
if (getGameModel().getSettings().getBoolean(Settings.MUTATION_ENABLED)) {
addNewMutations();
}
}
private void doExistingMutations() {
HashMap<Mutation, Integer> popularMutations = new HashMap<Mutation, Integer>();
Mutation frequentMutation = null;
int maxFreq = 0;
//getStats().mutationCount=0;
//getStats().mutationMiss=0;
for (Organism o : getEchosystem().getOrganisms()) {
int age = o.getAge();
ArrayList<Point> mutationPoints = o.getMutationPoints(age);
if (mutationPoints == null) {
continue;
}
for (int pi =0; pi<mutationPoints.size();pi++) {
Point p = mutationPoints.get(pi);
getStats().mutationCount++;
Cell c = getBoard().getCell(p);
if (c!=null) {
if (c.getOrganism()==o) {
boolean result = getEchosystem().removeCell(c);
c.getOrganism().removeFromTerritory(c);
//getBoard().removeCell(c);
Mutation m = o.getGenome().getMutation(age, pi);
Integer freq = popularMutations.get(m);
if (freq==null) {
freq = 0;
}
else {
freq = freq;
}
popularMutations.put(m, freq+1);
if (freq+1>maxFreq) {
maxFreq = freq+1;
frequentMutation = m;
}
}
else {
getStats().mutationMiss++;
}
}
else {
getStats().mutationMiss++;
}
}
}
if (getStats().freqMuteFreq < maxFreq) {
getStats().freqMutation = frequentMutation;
getStats().freqMuteFreq = maxFreq;
}
}
private void addNewMutations() {
ArrayList<Cell> allCells = getEchosystem().getCells();
if (allCells.size()==0) {
return;
}
//int size = Math.max(2000, allCells.size());
int repeatTimes = 1;
int invMutationRate = 160;
switch (getSettings().getInt(Settings.MUTATION_RATE)) {
case 1: invMutationRate = 1215; break;
case 2: invMutationRate = 810; break;
case 3: invMutationRate = 540; break;
case 4: invMutationRate = 360; break;
case 5: invMutationRate = 240; break;
case 6: invMutationRate = 160; break;
case 7: invMutationRate = 100; break;
case 8: invMutationRate = 70; break;
case 9: invMutationRate = 50; break;
case 10: invMutationRate = 30; break;
default: return;
}
if(getEchosystem().getOrganisms().size()>invMutationRate) {
repeatTimes = getEchosystem().getOrganisms().size()/invMutationRate;
}
if (getEchosystem().getOrganisms().size()<invMutationRate/3 ) {
repeatTimes = random.nextInt(10)==0 ? 1:0;
}
else if (getEchosystem().getOrganisms().size()<invMutationRate ) {
repeatTimes = random.nextInt(3)==0 ? 1:0;
}
for (int repeat=0;repeat<repeatTimes;repeat++) {
int size = allCells.size();
int mutationIndex = (new Random()).nextInt(size);
if (mutationIndex>=allCells.size()) {
return;
}
Cell c = allCells.get(mutationIndex);
Organism org = c.getOrganism();
int rand6 = random.nextInt(6);
int decreaseOdds = 3;
//if("friendly".equals(getSettings().getString(Settings.LIFE_MODE))) {
// decreaseOdds = 4; //50% odds of decreasing vs. 33% odds of increasing
//}
if (rand6 <=1 && org.lifespan<getSettings().getInt(Settings.MAX_LIFESPAN)) {
org.lifespan +=1;
if (random.nextInt(2)==1) {
continue;
}
}
else if (rand6<=decreaseOdds) {
//2,3 33%
org.lifespan -=1;
if (random.nextInt(2)==1) {
continue;
}
}
else {
//do nothing
}
/*
if (org.lifespan>160) {
org.lifespan=160;
}
*/
if (org.getId()!=0) {
Genome g = org.getGenome();
int age = org.getAge();
int x = c.x - org.x;
int y = c.y - org.y;
if (age<25) {
//continue;
}
boolean mutationIsAdd = (random.nextInt(7)>=4);//&& (g.getMutationCount(age)==0||age>=30);
/*
int mutationSum = 0;
for (int t=0;t<org.getLifespan();t++) {
mutationSum+=g.getMutationCount(t);
}
*/
if (mutationIsAdd){// && mutationSum<Math.sqrt(getTime()/2000.0)) {
//if(Math.abs(x)+Math.abs(y)+Math.abs(age)>=8) {
/*
while (g.getMutationCount(age)>5) {
int removeIndex = (new Random()).nextInt(g.getMutationCount(age));
g.removeMutation(g.getMutation(age, removeIndex));
}
*/
Mutation m = org.addMutation(x, y);
for (Organism childOrg : org.getChildren()) {
//Ok because, children are not yet old enough to have
//encountered this mutation
childOrg.getGenome().addMutation(m);
}
//experiment
if (org.getParent()!=null && random.nextInt(3)==0) {
org.getParent().getGenome().addMutation(m);
}
getEchosystem().removeCell(c);
//getBoard().removeCell(c);
//}
}
else { //remove random mutation
if(g.getMutationCount(age)>0) {
int removeIndex = random.nextInt(g.getMutationCount(age));
Mutation removeM = g.getMutation(age, removeIndex);
g.removeMutation(removeM);
for (Organism childOrg : org.getChildren()) {
//Ok because, children are not yet old enough to have
//encountered this mutation
//if (childOrg.getGenome().getMutationCount(age)<10) {
childOrg.getGenome().removeMutation(removeM);
//}
}
}
}
}
}
}
}