Support ratio attribute for structures.
This commit is contained in:
parent
dec5671af3
commit
44e95ab1cc
2 changed files with 64 additions and 21 deletions
|
@ -64,7 +64,7 @@ public class Asteroid extends Orb {
|
|||
@Override
|
||||
public boolean generate(World world, Random rand, int x, int y, int z) {
|
||||
int randRadius = MIN_RADIUS + rand.nextInt(Math.max(1, getRadius() - MIN_RADIUS));
|
||||
int numberCoreBlocks = minCoreSize + rand.nextInt(maxCoreSize - minCoreSize);
|
||||
int numberCoreBlocks = minCoreSize + rand.nextInt(Math.max(1, maxCoreSize - minCoreSize));
|
||||
|
||||
WarpDrive.logger.info("Asteroid generation: radius=" + randRadius + ", numCoreBlocks=" + numberCoreBlocks + ", coreRad=" + coreRad);
|
||||
|
||||
|
|
|
@ -147,30 +147,63 @@ public class StructureManager {
|
|||
* @param <E>
|
||||
*/
|
||||
private static class RandomCollection<E extends XmlRepresentable> {
|
||||
private final NavigableMap<Double, E> map = new TreeMap<Double, E>();
|
||||
private final NavigableMap<Double, E> weightMap = new TreeMap<Double, E>();
|
||||
private double totalWeight = 0;
|
||||
private final NavigableMap<Double, E> ratioMap = new TreeMap<Double, E>();
|
||||
private double totalRatio = 0;
|
||||
private final ArrayList<E> list = new ArrayList<E>();
|
||||
private double total = 0;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add new object and its weight.
|
||||
* @param weight Used for random pick. The higher the value is relatively to others, the higher odds of choosing the object.
|
||||
* @param obj Object to add
|
||||
*/
|
||||
public void add(double weight, E obj) {
|
||||
if (weight <= 0) return;
|
||||
total += weight;
|
||||
map.put(total, obj);
|
||||
if (weight <= 0) {
|
||||
WarpDrive.logger.warn("Structure weight is negative or zero, skipping");
|
||||
return;
|
||||
}
|
||||
totalWeight += weight;
|
||||
weightMap.put(totalWeight, obj);
|
||||
list.add(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new object and its ratio.
|
||||
* Warning: if total ratio goes higher than 1.0, element won't be added to collection.
|
||||
* @param ratio Chance of random pick in range (0, 1.0]. In contrast to weights, ratio is fixed and chances don't change if you add more elements.
|
||||
* @param obj Object to add
|
||||
*/
|
||||
public void addRatio(double ratio, E obj) {
|
||||
if (ratio <= 0 || ratio >= 1.0) {
|
||||
WarpDrive.logger.warn("Structure ratio isn't in (0, 1.0] bounds, skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
if (totalRatio + ratio > 1.0) {
|
||||
WarpDrive.logger.warn("Structures total ratio is greater than 1.0, skipping");
|
||||
return;
|
||||
}
|
||||
totalRatio += ratio;
|
||||
ratioMap.put(totalRatio, obj);
|
||||
list.add(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pick random object according their weights
|
||||
* @param random
|
||||
* @return Random object
|
||||
* @return Random object or null if there is no objects to pick.
|
||||
*/
|
||||
public E next(Random random) {
|
||||
double value = random.nextDouble() * total;
|
||||
return map.ceilingEntry(value).getValue();
|
||||
double value = random.nextDouble();
|
||||
|
||||
if (value < totalRatio) { // hit ratio part of values
|
||||
return ratioMap.ceilingEntry(value).getValue();
|
||||
} else { // hit dynamic part of values, weighted ones
|
||||
double weight = (value - totalRatio)*totalWeight;
|
||||
return weightMap.ceilingEntry(weight).getValue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -189,17 +222,27 @@ public class StructureManager {
|
|||
public void loadFromXML(E obj, Element struct) throws InvalidXmlException {
|
||||
obj.loadFromXmlElement(struct);
|
||||
|
||||
try {
|
||||
int weight = 1;
|
||||
String weightStr = struct.getAttribute("weight");
|
||||
if(!weightStr.isEmpty()) {
|
||||
weight = Integer.parseInt(struct.getAttribute("weight"));
|
||||
weight = Math.max(1, weight);
|
||||
}
|
||||
|
||||
this.add(weight, obj);
|
||||
} catch (NumberFormatException gdbg) {
|
||||
throw new InvalidXmlException("Weight must be int!");
|
||||
try {
|
||||
String ratioStr = struct.getAttribute("ratio");
|
||||
if(!ratioStr.isEmpty()) {
|
||||
double ratio = Double.parseDouble(ratioStr);
|
||||
this.addRatio(ratio, obj);
|
||||
} else { // try weight
|
||||
try {
|
||||
int weight = 1;
|
||||
String weightStr = struct.getAttribute("weight");
|
||||
if(!weightStr.isEmpty()) {
|
||||
weight = Integer.parseInt(weightStr);
|
||||
weight = Math.max(1, weight);
|
||||
}
|
||||
|
||||
this.add(weight, obj);
|
||||
} catch (NumberFormatException gdbg) {
|
||||
throw new InvalidXmlException("Weight must be int!");
|
||||
}
|
||||
}
|
||||
} catch (NumberFormatException gdbg) {
|
||||
throw new InvalidXmlException("Ratio must be double!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue