public double Evaluate(IChromosome chromosome)
{
var chrom = chromosome as ShortArrayChromosome;
double[] hpLoss;
int invalidGenes = 0;
var builds = new List<HeroBuild>();
int frontRow = 1;
for (int heroI = 0; heroI < simulator.PartySize; heroI++)
{
int offset = heroI * BuildSize;
var items = new int[(int)ItemSlot.N];
var itemCount = items.Length;
Array.Copy(chrom.Value, offset + 1, items, 0, itemCount);
var build = new HeroBuild(
chrom.Value[offset],
items,
new int[] { chrom.Value[offset + itemCount + 1], chrom.Value[offset + itemCount + 2] },
new int[] { chrom.Value[offset + itemCount + 3], MaxEnhancment - chrom.Value[offset + itemCount + 3] }
);
builds.Add(build);
if (build.HeroType >= Library.Heroes.Length)
invalidGenes += build.HeroType - Library.Heroes.Length + 1;
else
for (int i = 0; i < build.Items.Length; i++)
{
var maxIndex = simulator.ItemChoices(Library.Heroes[build.HeroType], i);
if (maxIndex == 0)
continue; //skip if there is no item for a slot
if (build.Items[i] >= maxIndex)
invalidGenes += build.Items[i] - maxIndex + 1;
}
if (build.EnhancmentTypes[0] >= EnhancmentTypes)
invalidGenes += build.EnhancmentTypes[0] - EnhancmentTypes + 1;
if (build.EnhancmentTypes[1] >= EnhancmentTypes)
invalidGenes += build.EnhancmentTypes[1] - EnhancmentTypes + 1;
if (build.EnhancmentCounts[0] >= MaxEnhancment)
invalidGenes += build.EnhancmentCounts[0] - MaxEnhancment;
/*for(int i = heroI + 1; i < simulator.PartySize; i++)
if (build.HeroType == chrom.Value[i * BuildSize])
invalidGenes++;*/
}
if (simulator.PartySize > 1)
{
frontRow = chrom.Value[simulator.PartySize * BuildSize];
if (frontRow < 1 || frontRow < simulator.PartySize - 3)
invalidGenes += 1;
if (frontRow > 3)
invalidGenes += chrom.Value[simulator.PartySize * BuildSize] - 3;
}
if (invalidGenes > 0)
{
descriptions.Add(chrom.Value, new ChromosomeDescription(null, 0, 0, invalidGenes));
return 1 / (InvalidChromosomeScore + invalidGenes);
}
hpLoss = simulator.Run(builds, frontRow);
double healCost = 0;
for (int i = 0; i < hpLoss.Length; i++)
healCost += Math.Abs(hpLoss[i] - ASimulator.HeroDead) < 1e-2 ?
2 :
hpLoss[i];
descriptions.Add(chrom.Value, new ChromosomeDescription(builds, frontRow, hpLoss.Count(x => Math.Abs(x - ASimulator.HeroDead) < 1e-2), 0));
return 1 / (healCost + 1);
}