package io.vivarium.core;
import io.vivarium.serialization.ClassRegistry;
import io.vivarium.serialization.SerializedParameter;
import io.vivarium.serialization.VivariumObject;
import io.vivarium.util.Rand;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@EqualsAndHashCode(callSuper = true)
@ToString
@SuppressWarnings("serial") // Default serialization is never used for a durable store
public class DynamicBalancer extends VivariumObject
{
static
{
ClassRegistry.getInstance().register(DynamicBalancer.class);
}
@SerializedParameter
private int _lastLowPopTickstamp = 0;
@SerializedParameter
private int _timePeriod = 2_000;
@SerializedParameter
private int _safePopulation = 300;
@SerializedParameter
private double _minimumFoodGenerationProbability = 0.002;
@SerializedParameter
private int _minimumBreedingFoodRate = -1500;
private DynamicBalancer()
{
}
public void balance(GridWorld target)
{
GridWorldBlueprint blueprint = target.getGridWorldBlueprint();
CreatureBlueprint species = blueprint.getCreatureBlueprints().get(0);
if (target.getCreatureCount() > _safePopulation)
{
if (target.getTickCounter() - _timePeriod > _lastLowPopTickstamp)
{
double traitSelector = Rand.getInstance().getRandomPositiveDouble();
if (traitSelector < 0.01)
{
// Try to lower food spawn rate
double oldFoodGenerationProbability = blueprint.getFoodGenerationProbability();
if (oldFoodGenerationProbability > _minimumFoodGenerationProbability)
{
// Lower food spawn rate
double newFoodGenerationProbability = Math.max(oldFoodGenerationProbability * 0.95,
_minimumFoodGenerationProbability);
blueprint.setFoodGenerationProbability(newFoodGenerationProbability);
// Reset the low tick population tracker
_lastLowPopTickstamp = target.getTickCounter();
}
}
else if (traitSelector < 1)
{
// Try to raise breeding cost
int oldBreedingFoodRate = species.getBreedingFoodRate();
if (oldBreedingFoodRate > _minimumBreedingFoodRate)
{
// Raise breeding cost
int newBreedingFoodRate = (int) Math.max(
Math.min(oldBreedingFoodRate * 1.01, oldBreedingFoodRate - 1),
_minimumBreedingFoodRate);
species.setBreedingFoodRate(newBreedingFoodRate);
// Reset the low tick population tracker
_lastLowPopTickstamp = target.getTickCounter();
}
}
else
{
}
}
}
else
{
_lastLowPopTickstamp = target.getTickCounter();
}
}
public static DynamicBalancer makeDefault()
{
DynamicBalancer b = new DynamicBalancer();
return b;
}
@Override
public void finalizeSerialization()
{
// Do nothing
}
}